常见排序总结

来源:互联网 发布:手机淘宝改评价 编辑:程序博客网 时间:2024/06/05 23:36

各算法的时间复杂度
①平均时间复杂度
插入排序 O(n^2),冒泡排序 O(n^2),选择排序 O(n^2),快速排序 O(n log n)
堆排序 O(n log n),归并排序 O(n log n),基数排序 O(n),希尔排序 O(n^1.25)

②算法稳定性

选择排序、快速排序、希尔排序、堆排序不是稳定的排序算法;
冒泡排序、插入排序、归并排序和基数排序是稳定的排序算法。

一、 冒泡法排序

[cpp] view plaincopy
  1. void BubbleSort(int *v, const int len)    
  2. {    
  3.     int i, j, temp;    
  4.   
  5.     for(i = 0; i < len - 1; ++ i)    
  6.     {    
  7.         for(j = 0; j < len - i - 1; ++ j)    
  8.         {    
  9.             if(v[j] > v[j + 1])    
  10.             {    
  11.                 temp = v[j];    
  12.                 v[j] = v[j + 1];    
  13.                 v[j + 1] = temp;    
  14.             }    
  15.         }    
  16.     }    
  17. }    

二 、选择法排序

1) 普通方法

[cpp] view plaincopy
  1. void SelectSort(int *v, const int len)  
  2. {  
  3.     int i,j,temp;  
  4.   
  5.     for(i = 0; i < len - 1; ++ i)  
  6.     {  
  7.         for(j = i + 1; j < len ; ++ j)  
  8.         {  
  9.             if(v[i] > v[j])  
  10.             {  
  11.                 temp = v[i];  
  12.                 v[i] = v[j];  
  13.                 v[j] = temp;  
  14.             }  
  15.         }  
  16.     }  
  17. }  

2) 优化方法

[cpp] view plaincopy
  1. void SelectSort(int *v, const int len)  
  2. {  
  3.     int i,j,k,temp;  
  4.   
  5.     for(i = 0; i < len - 1; ++ i)  
  6.     {  
  7.         k = i;  
  8.         for(j = i + 1; j < len; ++ j)  
  9.         {  
  10.             if(v[k] > v[j])  
  11.             {  
  12.                 k = j;  
  13.             }  
  14.         }  
  15.         if(k != i)  
  16.         {  
  17.             temp = v[i];  
  18.             v[i] = v[k];  
  19.             v[k] = temp;  
  20.             //v[i] ^= v[k] ^= v[i] ^= v[k];  
  21.         }  
  22.     }  
  23. }  

三、快速排序,快排最标准的递归实现,速度约是std::sort的一半

[cpp] view plaincopy
  1. #include <stdio.h>  
  2.   
  3. int  Partition(int *iArray, int i, int j)  
  4. {  
  5.     int pivot = iArray[ i ];  
  6.   
  7.     while(i < j)  
  8.     {  
  9.         while(i < j && iArray[ j ] >= pivot )  
  10.         {  
  11.             j --;  
  12.         }  
  13.   
  14.         if(i < j)  
  15.         {  
  16.             iArray[ i ++ ] = iArray[ j ];  
  17.         }  
  18.   
  19.         while(i < j && iArray[ i ] <= pivot)  
  20.         {  
  21.             i ++;  
  22.         }  
  23.   
  24.         if(i < j)  
  25.         {  
  26.             iArray[ j -- ] = iArray[ i ];  
  27.         }  
  28.     }  
  29.   
  30.     iArray[ i ] = pivot;  
  31.   
  32.     return i;  
  33. }  
  34.   
  35. void QuickSort(int *iArray, int low, int high)  
  36. {  
  37.     if(low < high)  
  38.     {  
  39.         int pivotpos = Partition(iArray, low, high);  
  40.   
  41.         QuickSort(iArray, low, pivotpos - 1);  
  42.   
  43.         QuickSort(iArray, pivotpos + 1, high);  
  44.     }  
  45.   
  46. }  
  47. int main()  
  48. {  
  49.     int iArray[] = {1,0,9,3,7,2,-90,78,45,4,77,79,78,37,0,-1,2,3,6,9,5,4,78,78,78,1,1,1};  
  50.   
  51.     int len = sizeof(iArray) / sizeof(int);  
  52.   
  53.     QuickSort(iArray, 0, len - 1);  
  54.   
  55.     for(int i = 0; i < len; ++ i)  
  56.     {  
  57.         printf("%3d ",iArray[ i ]);  
  58.     }  
  59.   
  60.     printf("\n");  
  61. }  

四、直接插入排序

直接插入排序(straight insertion sort)的作法是:
1. 每次从无序表中取出第一个元素,把它插入到有序表的合适位置,使有序表仍然有序。
第一趟比较前两个数,然后把第二个数按大小插入到有序表中; 第二趟把第三个数据与前两个数从前向后扫描,把第三个数按大小插入到有序表中;依次进行下去,进行了(n-1)趟扫描以后就完成了整个排序过程。
2. 直接插入排序属于稳定的排序,最坏时间复杂性为O(n^2),空间复杂度为O(1)。
直接插入排序是由两层嵌套循环组成的。外层循环标识并决定待比较的数值。内层循环为待比较数值确定其最终位置。直接插入排序是将待比较的数值与它的前一个数值进行比较,所以外层循环是从第二个数值开始的。当前一数值比待比较数值大的情况下继续循环比较,直到找到比待比较数值小的并将待比较数值置入其后一位置,结束该次循环。
3. 值得注意的是,我们必需用一个存储空间来保存当前待比较的数值,因为当一趟比较完成时,我们要将待比较数值置入比它小的数值的后一位 插入排序类似玩牌时整理手中纸牌的过程。插入排序的基本方法是:每步将一个待排序的记录按其关键字的大小插到前面已经排序的序列中的适当位置,直到全部记录插入完毕为止。

[cpp] view plaincopy
  1. void InsertSort(int *v, const int len)  
  2.  {  
  3.     int i,j,temp;  
  4.   
  5.     for(i = 1; i < len; ++ i)  
  6.     {  
  7.         //store the original sorted array in temp  
  8.         temp = v[i];  
  9.   
  10.         //compare the new array with temp(maybe -1?)  
  11.         for(j = i ; j > 0 && temp < v[j - 1] ; -- j)  
  12.         {  
  13.             //all larger elements are moved one pot to the right  
  14.             v[j] = v[j - 1];  
  15.         }  
  16.         //此时的j已经是空位的j  
  17.         v[j] = temp;  
  18.     }  
  19. }  

五、归并排序,效率越是std::sort的六分之一,通常的实现是递归,但和快排不同,归并改循环极其容易

[cpp] view plaincopy
  1. void Merge(int *v, int low, int mid, int high)  
  2. {  
  3.     int i = low, j = mid + 1, k = low;  
  4.     int *tempV = new int [high + 1];  
  5.   
  6.     while(i <= mid && j <= high)  
  7.     {  
  8.         // 此处为排序顺序的关键,用小于表示从小到大排序  
  9.         if(v[i] <= v[j])   
  10.         {  
  11.             tempV[k++] = v[i++];  
  12.         }  
  13.         else  
  14.         {  
  15.             tempV[k++] = v[j++];  
  16.         }  
  17.     }  
  18.     while(i <= mid)  
  19.     {  
  20.         tempV[k++] = v[i++];  
  21.     }  
  22.     while(j <= high)  
  23.     {  
  24.         tempV[k++] = v[j++];  
  25.     }  
  26.     // 写回原数组  
  27.     for(i = low; i <= high; i++)  
  28.     {  
  29.         v[i] = tempV[i];  
  30.     }  
  31.     delete [] tempV;  
  32. }  
  33.   
  34. void GetMergeSort(int *v, int low, int high)  
  35. {  
  36.     int mid;  
  37.     if(low < high)  
  38.     {  
  39.         mid = low + (high - low) / 2;  
  40.         GetMergeSort(v, low, mid);  
  41.         GetMergeSort(v, mid + 1, high);  
  42.         Merge(v, low, mid, high);  
  43.     }  
  44. }  
  45.   
  46. void MergeSort(int *v, const int len)  
  47. {  
  48.     GetMergeSort(v, 0, len - 1);  
  49. }