常见的排序方法

常见的排序方法



实用排序算法(复杂度小于等于O(n^2))中效率最低但实现并不是最简单的的两个,C、C++教材却总喜欢拿来大讲特讲,非常不利于初学者养成“程序效率”的思维。实际上,各种排序算法里,除了堆排序实现较为复杂外,从代码量的角度,大多数算法都不比冒泡、选择算法复杂多少。

一 冒泡法排序

[cpp]  view plain copy
  1. #include "stdio.h"   
  2.     
  3. void bubble(int *a, int len)    
  4. {    
  5.     int i,j,temp;    
  6.   
  7.     for(i = 0;i < len - 1;i ++)    
  8.     {    
  9.         for(j = 0;j < len - i - 1;j ++)    
  10.         {    
  11.             if(a[j] > a[j + 1])    
  12.             {    
  13.                 temp = a[j];    
  14.                 a[j] = a[j + 1];    
  15.                 a[j + 1] = temp;    
  16.             }    
  17.         }    
  18.     }    
  19. }    
  20. void main(void)    
  21. {    
  22.     int i,a[ ] = {2,5,4,1,6,3,7,9,8,0};  
  23.       
  24.     int len = sizeof(a) / sizeof(int);  
  25.   
  26.     bubble(a, len);    
  27.   
  28.     for(i = 0; i < len; i ++)    
  29.     {    
  30.         printf("%2d",a[i]);    
  31.     }    
  32.     printf("\n");    
  33.     
  34. }    
二 选择法排序

1)普通方法

[cpp]  view plain copy
  1. #include "stdio.h"  
  2.   
  3. void choiceOne(int *a, int len)  
  4. {  
  5.     int i,j,temp;  
  6.   
  7.     for(i = 0;i < len - 1;i ++)  
  8.     {  
  9.         for(j = i + 1;j < len ;j ++)  
  10.         {  
  11.             if(a[i] > a[j])  
  12.             {  
  13.                 temp = a[i];  
  14.                 a[i] = a[j];  
  15.                 a[j] = temp;  
  16.             }  
  17.         }  
  18.     }  
  19. }  
  20. void main(void)  
  21. {  
  22.     int i,a[]={2,5,4,1,6,3,7,9,8,0};  
  23.   
  24.     int len = sizeof(a) / sizeof(int);  
  25.   
  26.     choiceOne(a, len);  
  27.   
  28.     for(i = 0;i < len;i ++)  
  29.     {  
  30.         printf("%2d",a[i]);  
  31.     }  
  32.     printf("\n");  
  33.   
  34. }  

2)改进方法

[cpp]  view plain copy
  1. #include "stdio.h"  
  2.   
  3. void choiceTwo(int *a, int len)  
  4. {  
  5.     int i,j,k,temp;  
  6.   
  7.     for(i = 0; i < len - 1; i ++)  
  8.     {  
  9.         k = i;  
  10.         for(j = i + 1;j < len ;j ++)  
  11.         {  
  12.             if(a[k] > a[j])  
  13.             {  
  14.                 k = j;  
  15.             }  
  16.         }  
  17.         if(k != i)  
  18.         {  
  19.             temp = a[i];  
  20.             a[i] = a[k];  
  21.             a[k] = temp;          
  22.         }  
  23.     }  
  24. }  
  25. void main(void)  
  26. {  
  27.     int i,a[]={2,5,4,1,6,3,7,9,8,0};  
  28.   
  29.     int len = sizeof(a) / sizeof(int);  
  30.   
  31.     choiceTwo(a, len);  
  32.   
  33.     for(i = 0;i < len;i ++)  
  34.     {  
  35.         printf("%2d",a[i]);  
  36.     }  
  37.     printf("\n");  
  38. }  
[cpp]  view plain copy
  1. void func(int *a, int len)  
  2. {  
  3.     int i,j,k;  
  4.   
  5.     for(i = 0; i < len - 1; i ++)  
  6.     {  
  7.         k = i;  
  8.         for(j = i + 1;j < len ;j ++)  
  9.         {  
  10.             if(a[k] > a[j])  
  11.             {  
  12.                 k = j;  
  13.             }  
  14.         }  
  15.         if(k != i)  
  16.         {  
  17.             a[i] ^= a[k] ^= a[i] ^= a[k];          
  18.         }  
  19.     }  
  20. }  


鸽巢排序,排序字节串、宽字节串最快的排序算法,计数排序的变种(将计数缓冲区大小固定,少一次遍历开销),速度是STL中std::sort的20多倍,更重要的是实现极其简单!缺点是需要一个size至少等于待排序数组取值范围的缓冲区,不适合int等大范围数据

[cpp]  view plain copy
  1. void PigeonholeSort(BYTE *array, int length)  
  2. {  
  3.     int b[256] = {0};  
  4.     int i,k,j = 0;  
  5.     for(i = 0; i < length;  i++)  
  6.         b[array[i]] ++;  
  7.     for(i = 0; i < 256; i ++)  
  8.         for(k =0; k < b[i]; k ++)  
  9.             array[j ++] = i;  
  10. }  
四.  多一次遍历的计数排序,排序字节串的话速度约是鸽巢排序的一半
[cpp]  view plain copy
  1. void CountingSort(BYTE *array, int length)  
  2. {  
  3.     int t;  
  4.     int i, z = 0;  
  5.     BYTE min,max;  
  6.     int *count;  
  7.     min = max = array[0];  
  8.     for(i=0; i<length; i++)  
  9.     {  
  10.         if(array[i] < min)  
  11.             min = array[i];  
  12.         else if(array[i] > max)  
  13.             max = array[i];  
  14.     }  
  15.     count = (int*)malloc((max-min+1)*sizeof(int));  
  16.     for(i=0; i<max-min+1; i++)  
  17.         count[i] = 0;  
  18.     for(i = 0; i < length; i++)  
  19.         count[array[i]-min]++;  
  20.   
  21.     for(t = 0; t <= 255; t++)  
  22.         for(i = 0; i < count[t-min]; i++)  
  23.             array[z++] = (BYTE)t;  
  24.     free(count);  
  25. }  

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

[cpp]  view plain copy
  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. }  

六 这是速度与std::sort相当的三路划分快排

[cpp]  view plain copy
  1. void swap(BYTE *a,BYTE *b)  
  2. {  
  3.     BYTE tmp;  
  4.     if ( a != b )  
  5.     {  
  6.         tmp = *a;  
  7.         *a = *b;  
  8.         *b = tmp;  
  9.     }  
  10. }  
  11.   
  12. void quicksort(BYTE *arr, int left, int right)  
  13. {  
  14.     if (left < right)  
  15.     {  
  16.         BYTE v = arr[right];  
  17.         int i = left - 1,j = right,p = left - 1,q = right,k=0;  
  18.         while (1)  
  19.         {  
  20.             while (arr[++i] < v);  
  21.             while (arr[--j] > v)  
  22.                 if(j==left)  
  23.                     break;  
  24.             if (i >= j)  
  25.                 break;  
  26.             swap(&arr[i], &arr[j]);  
  27.             if(arr[i] == v)  
  28.             {  
  29.                 p++;  
  30.                 swap(&arr[p],&arr[i]);  
  31.             }  
  32.             if(arr[j] == v)  
  33.             {  
  34.                 q--;  
  35.                 swap(&arr[q],&arr[j]);  
  36.             }  
  37.         }  
  38.         swap(&arr[i],&arr[right]);  
  39.         j = i - 1;  
  40.         i++;  
  41.         for(k=left; k<=p; k++,j--)  
  42.             swap(&arr[k],&arr[j]);  
  43.         for(k=right-1; k>=q; k--,i++)  
  44.             swap(&arr[k],&arr[i]);  
  45.         quicksort(arr,left,j);  
  46.         quicksort(arr,i,right);  
  47.     }  
  48. }  
  49.   
  50. void QuickSort(BYTE *array,int length)  
  51. {  
  52.     quicksort(array,0,length-1);  
  53. }  
七  相当简单的梳排序,效率是std::sort的三分之一
[cpp]  view plain copy
  1. void CombSort(BYTE *arr, int size)  
  2. {  
  3.     UINT gap = size, swapped = 1, i = 0;  
  4.     BYTE swap = 0;  
  5.     while ((gap > 1) || swapped)  
  6.     {  
  7.         if (gap > 1)  
  8.             gap = gap / 1.3;  
  9.         swapped = 0;   
  10.         i = 0;  
  11.         while ((gap + i) < size)  
  12.         {  
  13.             if (arr[i] - arr[i + gap] > 0)  
  14.             {  
  15.                 swap = arr[i];  
  16.                 arr[i] = arr[i + gap];  
  17.                 arr[i + gap] = swap;  
  18.                 swapped = 1;  
  19.             }  
  20.             ++i;  
  21.         }  
  22.     }  
  23. }  
八  LSD基数排序,与std::sort速度相当,但是需要一个与输入缓冲一样大的缓冲区
[cpp]  view plain copy
  1. #define R 256  
  2.   
  3. #define digit(a, d)    ( a >> 8*d )  
  4.   
  5. static BYTE *aux;  
  6.   
  7. void radix_sort(BYTE *arr, int left, int right)  
  8. {  
  9.     if(left < right)  
  10.     {  
  11.         int d = 0;  
  12.         for(d=3; d>=0; d--)  
  13.         {  
  14.             int i=0, j=0, count[R+1];  
  15.             for(j=0; j<R; j++)  
  16.                 count[j] = 0;  
  17.             for(i=left; i<=right; i++)  
  18.                 count[digit(arr[i],d) + 1]++;  
  19.             for(j=1; j<R; j++)  
  20.                 count[j] += count[j-1];  
  21.             for(i=left; i<=right; i++)  
  22.                 aux[count[digit(arr[i],d)]++] = arr[i];  
  23.             for(i=left; i<=right; i++)  
  24.                 arr[i] = aux[i-1];  
  25.         }      
  26.     }  
  27. }  
  28.   
  29. void RadixSort(BYTE *array,int length)  
  30. {  
  31.     aux = (BYTE*)malloc(length);  
  32.     radix_sort(array,0,length-1);  
  33.     free(aux);  
  34. }  
九  归并排序,效率越是std::sort的六分之一,通常的实现是递归,但和快排不同,归并改循环极其容易
[cpp]  view plain copy
  1. void merge(BYTE *array, int low, int mid, int high)  
  2. {  
  3.     int i, k;  
  4.     BYTE *temp = (BYTE *) malloc(high-low+1);  
  5.     int begin1 = low;  
  6.     int end1 = mid;  
  7.     int begin2 = mid + 1;  
  8.     int end2 = high;  
  9.   
  10.     for (k = 0; begin1 <= end1 && begin2 <= end2; ++k)  
  11.         if(array[begin1]<array[begin2])  
  12.             temp[k] = array[begin1++];  
  13.         else  
  14.             temp[k] = array[begin2++];      
  15.     while(begin1<=end1)  
  16.         temp[k++] = array[begin1++];  
  17.     while(begin2<=end2)  
  18.         temp[k++] = array[begin2++];  
  19.     for (i = 0; i < (high-low+1); i++)  
  20.         array[low+i] = temp[i];  
  21.     free(temp);  
  22. }  
  23.   
  24. void merge_sort(BYTE *array, UINT first, UINT last)  
  25. {  
  26.     UINT mid,i;  
  27.     for(mid=1; mid<=last-first; mid += mid)  
  28.         for(i=first; i<=last-mid; i+=mid+mid)  
  29.             merge(array,i,i+mid-1,min(i+mid+mid-1,last));  
  30. }  
  31.   
  32. void MergeSort(BYTE *array, UINT length)  
  33. {  
  34.     merge_sort(array,0,length-1);  
  35. }  

你可能感兴趣的:(常见的排序方法)