排序算法作为程序员必备基础技能,在工作和面试中经常会拿来使用或者扩展。今天就针对常使用的冒泡排序、选择排序、插入排序、希尔排序、快速排序、归并排序、堆排序进行简单的分析总结。下图是7种排序算法对10000个随机数的排序时间消耗对比。完整测试代码详见:https://github.com/Kunpeng1989/Sort
公众平台见二维码
1、冒泡排序:
冒泡排序的实现原理和它的名字相似,“重的”元素往下沉,“轻的”元素像水中的气泡一样往上冒。我们通过图示说明,以数组a[5] = {8,6,2,10,4}为例说明。
第一轮:从第一个元素开始两两比较,将较大的元素放到后边。如第一个元素8大于第二个元素6,那么这两个元素交换位置。交换位置后再拿第二个元素8和第三个元素2进行比对交换。这样一轮遍历下来,在最后一个位置的一定是最大的元素。
第二轮继续从第一个元素开始两两对比,同样较大的元素往后移动,第二轮遍历比对后是第二大的元素调整到倒数第二个位置。
第三轮继续从第一个元素开始两两对比,记录最大元素位置,第三轮对比后确认的是第三大的元素位于倒数第三个位置。
第四轮继续从第一个元素开始两两对比,较大的元素往后移动,第四轮对比后确认的是第四大的元素位于倒数第四个位置。
由于一共有5个元素,4轮比对后后四个元素的位置确定了,那么剩下的一个元素位置自然确定。冒泡算法对N个元素一个需要比对(N-1)轮, 每轮比对的次数为与轮数i的关系为(N-i),即第一轮比较N-1次,第二轮比较N-2次,第三轮比较N-3次……,因此冒泡排序的时间复杂度为O(N*N)。
void BubbleSort(int array[], int length){
unsigned int i = 0, j =0;
int flag = 1;
for(i=0; i< length-1 && flag; i++){
flag = 0;
for(j = 0; j < MAX-i-1; j++){
if(array[j] > array[j+1]){
swap(&array[j], &array[j+1]);
flag = 1; /*一轮数据循环后,有交换说明数据还可能不是有序态*/
}
}
}
}
2、选择排序:
排序的时间消耗主要有两方面,分别是比对和交换。为了提高排序效率,我们可以通过较少比对次数或交换次数入手,选择排序就是从减少交换次数入手的。选择排序类似于冒泡排序,不同的是选择排序每一轮遍历过程中只记录最大元素的位置,但是不会立即交换,而是这一轮遍历结束后将最大的元素交换到后边合适的位置,这样每轮遍历只交换1次。同样以数组a[5] = {8,6,2,10,4}为例说明。
第一轮:从第一个元素开始两两比较,不过不进行位置交换,只记录当前比较过元素中最大元素的位置即index(位置从0开始计数)。。这样一轮遍历下来,在最后一个位置的一定是最大的元素位置index为3,然后拿index为3的元素与最后一个元素进行位置交换。
第二轮继续从第一个元素开始两两对比,同样记录最大元素的位置,不同的是这轮遍历不和最后一个元素进行比对,因为最后一个元素是第一轮选出的最大元素。第二轮遍历过后将选出的最大元素与倒数第二个位置的元素交换。
第三轮继续从第一个元素开始两两对比,记录最大元素位置,第三轮对比后确认的是第三大的元素位于倒数第三个位置。
第四轮继续从第一个元素开始两两对比,较大的元素往后移动,第四轮对比后确认的是第四大的元素位于倒数第四个位置。
由于一共有5个元素,4轮比对后后四个元素的位置确定了,那么剩下的一个元素位置自然确定。选择算法对N个元素一个需要比对(N-1)轮, 每轮比对的次数为与轮数i的关系为(N-i),即第一轮比较N-1次,第二轮比较N-2次,第三轮比较N-3次……,因此冒泡排序的时间复杂度为O(N*N)。
void SelectSort(int array[], int length){
int i =0, j =0;
int max_index = 0;
for(i=0; i< MAX-1; i++){
max_index = 0;
for(j = 1; j < MAX-i; j++){
/*每一轮选出一个本轮最大数组元素,并记录这个数组元素的下标max_index*/
if(array[j] > array[max_index]){
max_index = j;
&