白话经典算法系列 - 七大排序总结篇
原文链接:
http://blog.csdn.net/MoreWindows/article/category/859207
1.冒泡排序
核心思路:
双重循环
外层是进行多少轮,一轮冒泡只能排好一个数,所以有n轮;(这是最好的理解方式)
内层是单次冒泡,冒泡的核心是逐个,相邻元素两两比较,如此,一轮冒泡后,最大(最小)元素就跑到最后面了
//核心代码 void sort(int *a, int len) { for (int i = 0; i < len; i++) for (int j = 1; j < len - i; j++) { if (a[j - 1] > a[j]) swap(a[j - 1], a[j]); } }
实现:外层从0到len-1;内层从1到len-i,因为已经排过的就不需要再参与下一次的冒泡了;两两比较,反序则交换。
改进版1:
核心思想:如果某一趟内层没有进行交换,那显然整个数组已经有序,那就可以退出了。
//核心代码 void sort(int *a, int len) { bool flag = true; for (int i = 0; i < len; i++) { for (int j = 1; j < len - i; j++) { if (a[j - 1] > a[j]) { swap(a[j - 1], a[j]); flag = false; } } if (!flag) break; } }
实现:在所有循环外部设置一个标签true,表示此时数组有序;最内层如果交换执行,标签就会被设置为false,表明此时数组无序,仍需进入下一轮;如果内层循环一个也没执行,那标签就是原始的true;在外层循环内设置一个条件跳出器,一旦检测到true就结束外层循环。
改进版,网上有很多有意思的写法,总体就是一个多米诺玩具,相互触发,很好玩。
//巧妙的改写版本 void sort(int *a, int len) { int k = len; bool flag = true; while (flag) { flag = false; for (int j = 1; j < k; j++) { if (a[j - 1] > a[j]) { swap(a[j - 1], a[j]); flag = true; } } k--; } }
改进2:
还有一种情况需要改进,即数组前面部分无序,后面有序(3,2,1,4,5,6,7,8)。此时可以记录那个临界的位置,下次内层冒泡的终点就可以提前。
//这种算法还是少些得好,太晦涩 void sort(int *a, int len) { int flag = len; while (flag > 0) { int k = flag; flag = 0; for (int j = 1; j < k; j++) { if (a[j - 1] > a[j]) { swap(a[j - 1], a[j]); flag = j; } } } }