【算法】 冒泡排序 & 快速排序
2016-05-29 14:59
232 查看
冒泡排序(Bubble Sort)
1.算法原理
从后向前,比较相邻的元素。如果第一个比第二个大,就交换他们两个。
对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。在这一点,最后的元素应该会是最大的数。
针对所有的元素重复以上的步骤,除了最后一个。
持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。
2.算法说明
冒泡排序是一种比较简单的算法,但是第一次看还是觉得有些繁琐。
它应用了双重嵌套循环,外面的循环是确定本次循环的范围,内部循环是在确定的范围里找到最大的数放到最前。
这里涉及到有序序列和无序序列,简单来说,就是排好顺序的就是有序的,没排好的就是无序的。
从它的工作机理来看就是“交换”,从最后那个数开始,和旁边的数比较大小,谁大谁往前,其实就是交换一下,然后就是倒数第二个和倒数三个比较,最后,这个数组的第一个数就是本数组最大的数,那么,我们的有序序列就有了一个数!就是最大那个数!
这时候,外部循环进行了一次,内部循环整个循环一圈~
然后外部循环的范围就会减1,其实它一直在确定无序序列的范围。然后内循环是找最大。
总之,就这样,循环往复........
举个例子~
如果有10个数,第一次从10个数中(外循环确定)找最大的数放在第一的位置(内循环整体循环一次可得到);
第二次从9个数中(还是外循环确定的范围,第一个数已经是最大的了)找最大的数放在这9个数的第一的位置(内循环再次整体循环)
就这样一直排下去....
快速排序(Quick Sort)
1.算法原理
设要排序的数组是A[0]……A[N-1],首先任意选取一个数据(通常选用数组的第一个数)作为关键数据,然后将所有比它小的数都放到它前面,所有比它大的数都放到它后面,这个过程称为一趟快速排序。值得注意的是,快速排序不是一种稳定的排序算法,也就是说,多个相同的值的相对位置也许会在算法结束时产生变动。
一趟快速排序的算法是:
1)设置两个变量i、j,排序开始的时候:i=0,j=N-1;
2)以第一个数组元素作为关键数据,赋值给key,即key=A[0];
3)从j开始向前搜索,即由后开始向前搜索(j--),找到第一个小于key的值A[j],将A[j]和A[i]互换;
4)从i开始向后搜索,即由前开始向后搜索(i++),找到第一个大于key的A[i],将A[i]和A[j]互换;
5)重复第3、4步,直到i=j; (3,4步中,没找到符合条件的值,即3中A[j]不小于key,4中A[i]不大于key的时候改变j、i的值,使得j=j-1,i=i+1,直至找到为止。找到符合条件的值,进行交换的时候i, j指针位置不变。另外,i==j这一过程一定正好是i+或j-完成的时候,此时令循环结束)。
2.算法说明
快速排序是对冒泡排序的一种改进。
冒泡排序通常不会使用,但是学习它可以帮助理解快速排序,那么快速排序到底改进了哪些???
在冒泡排序中,我们是和旁边的数比较,然后让大数一步步的从后面换到前面,这样,未免有些笨,因为在日常生活中,如果我们给学生排队的话,肯定是让高个子的直接排到前面,低的排在后面,然后再微调,没人会让最高的那个一次一次的从后面“交换”上来,太慢了。。。
所以,这里引入一个二分法的理念。
简单来说,就是把大的放一块,小的放一块。然后继续划分,这样做的好处就是相比冒泡排序有种一步到位的感觉,因为它一下就把大数和小数分到差不多的位置,而不是笨笨的一点点移上去。
代码对比
下面是冒泡排序和快速排序的代码(C#版)
static void Main(string[] args) { int numberCount; int[] numbers; Console.WriteLine("请问您要对多少个数字进行排序?"); numberCount = Convert.ToInt32(Console.ReadLine()); //生成指定数量的随机数 numbers = new int[numberCount]; System.Random rnd = new System.Random(); for (int i = 0; i < numberCount; i++) { numbers[i] = rnd.Next(1, numberCount); ; } Console.WriteLine(); //冒泡排序 System.Diagnostics.Stopwatch watch1 = new System.Diagnostics.Stopwatch(); watch1.Start(); for (int i = 0; i < numbers.Length - 1; i++) { for (int j = 0; j < numbers.Length - 1 - i; j++) { if (numbers[j] > numbers[j + 1]) { int temp = numbers[j]; numbers[j] = numbers[j + 1]; numbers[j + 1] = temp; } } } watch1.Stop(); Console.WriteLine("冒泡排序 耗费时间为: {0} 毫秒", watch1.ElapsedMilliseconds); Console.WriteLine(); //快速排序 System.Diagnostics.Stopwatch watch5 = new System.Diagnostics.Stopwatch(); watch5.Start(); sort(numbers, 0, numbers.Length - 1); watch5.Stop(); Console.WriteLine("快速排序 耗费时间为: {0} 毫秒", watch5.ElapsedMilliseconds); Console.WriteLine(); Console.ReadKey(); } private static int sortUnit(int[] array, int low, int high) { int key = array[low]; while (low < high) { /*从后向前搜索比key小的值*/ while (array[high] >= key && high > low) --high; /*比key小的放左边*/ array[low] = array[high]; /*从前向后搜索比key大的值,比key大的放右边*/ while (array[low] <= key && high > low) ++low; /*比key大的放右边*/ array[high] = array[low]; } /*左边都比key小,右边都比key大。//将key放在游标当前位置。//此时low等于high */ array[low] = key; return high; } public static void sort(int[] array, int low, int high) { if (low >= high) return; /*完成一次单元排序*/ int index = sortUnit(array, low, high); /*对左边单元进行排序*/ sort(array, low, index - 1); /*对右边单元进行排序*/ sort(array, index + 1, high); } }
输入的结果为:
空间复杂度 & 时间复杂度
在这里要涉及到空间复杂度和时间复杂度的问题,简单来说就是需要多少内存来处理和需要多少时间来处理。
通常情况下,降低空间复杂度会引起时间复杂度的上升。其实这也很好理解,同样的任务量,人少时间用的就多,人多时间用的就少。当然,这也不是绝对的,如果你的方法上升到更高的维度,说不定你所用的空间和时间都会减少。
总结
对算法的研究还会继续进行下去,他们可以很好帮助我们优化我们的代码。
这些凝结的智慧会对我们有很大启发,站在巨人之上,学习并超越。
相关文章推荐
- mysql主从同步-错误记录
- 网络编程和反射机制
- 深入浅析python继承问题
- 无事可做的一天
- Java Collections
- Android仿微信通讯录功能,好友排序+字母索引
- 2016-5-29
- SQL SERVER2012数据库恢复挂起解决
- 学习记录 java 链表知识
- 每天翻译一点点: WPF Application Framework (WAF)
- Linux中ctags、make以及进度条小程序(\r的应用)
- 串和数组自测题
- 第4课时《osg矩阵变换(上)》
- 欢迎使用CSDN-markdown编辑器
- 独木舟上的旅行
- 3 0/1排序背包问题
- 把实体类数据的字段名和值填充到DataTable里
- Android 你才刚上路呢
- JQuery中的类选择器
- 欢迎使用CSDN-markdown编辑器