各種排序的穩定性,時間復雜度、空間復雜度、穩定性總結如下圖:
關於時間復雜度: (1)平方階(O(n2))排序 各類簡單排序:直接插入、直接選擇和冒泡排序; (2)線性對數階(O(nlog2n))排序 快速排序、堆排序和歸並排序; (3)O(n1+§))排序,§是介於0和1之間的常數。 希爾排序 (4)線性階(O(n))排序 基數排序,此外還有桶、箱排序。 關於穩定性: 穩定的排序算法:冒泡排序、插入排序、歸並排序和基數排序 不是穩定的排序算法:選擇排序、快速排序、希爾排序、堆排序 #include<iostream> 2 #include<malloc.h> 3 using namespace std; 4 5 int getdigit(int x,int d) 6 { 7 int a[] = {1, 1, 10}; //因為待排數據最大數據也只是兩位數,所以在此只需要到十位就滿足 8 return ((x / a[d]) % 10); //確定桶號 9 } 10 11 void PrintArr(int ar[],int n) 12 { 13 for(int i = 0; i < n; ++i) 14 cout<<ar[i]<<" "; 15 cout<<endl; 16 } 17 18 void msdradix_sort(int arr[],int begin,int end,int d) 19 { 20 const int radix = 10; 21 int count[radix], i, j; 22 //置空 23 for(i = 0; i < radix; ++i) 24 { 25 count[i] = 0; 26 } 27 //分配桶存儲空間 28 int *bucket = (int *) malloc((end-begin+1) * sizeof(int)); 29 //統計各桶需要裝的元素的個數 30 for(i = begin;i <= end; ++i) 31 { 32 count[getdigit(arr[i], d)]++; 33 } 34 //求出桶的邊界索引,count[i]值為第i個桶的右邊界索引+1 35 for(i = 1; i < radix; ++i) 36 { 37 count[i] = count[i] + count[i-1]; 38 } 39 //這里要從右向左掃描,保證排序穩定性 40 for(i = end;i >= begin; --i) 41 { 42 j = getdigit(arr[i], d); //求出關鍵碼的第d位的數字, 例如:576的第3位是5 43 bucket[count[j]-1] = arr[i]; //放入對應的桶中,count[j]-1是第j個桶的右邊界索引 44 --count[j]; //第j個桶放下一個元素的位置(右邊界索引+1) 45 } 46 //注意:此時count[i]為第i個桶左邊界 47 //從各個桶中收集數據 48 for(i = begin, j = 0;i <= end; ++i, ++j) 49 { 50 arr[i] = bucket[j]; 51 } 52 //釋放存儲空間 53 free(bucket); 54 //對各桶中數據進行再排序 55 for(i = 0;i < radix; i++) 56 { 57 int p1 = begin + count[i]; //第i個桶的左邊界 58 int p2 = begin + count[i+1]-1; //第i個桶的右邊界 59 if(p1 < p2 && d > 1) 60 { 61 msdradix_sort(arr, p1, p2, d-1); //對第i個桶遞歸調用,進行基數排序,數位降 1 62 } 63 } 64 } 65 66 void main() 67 { 68 int ar[] = {12, 14, 54, 5, 6, 3, 9, 8, 47, 89}; 69 int len = sizeof(ar)/sizeof(int); 70 cout<<"排序前數據如下:"<<endl; 71 PrintArr(ar, len); 72 msdradix_sort(ar, 0, len-1, 2); 73 cout<<"排序后結果如下:"<<endl; 74 PrintArr(ar, len); 75 } 76 77 排序前數據如下: 78 12 14 54 5 6 3 9 8 47 89 79 排序后結果如下: 80 3 5 6 8 9 12 14 47 54 89 81 第二種方式排序基數 : #include<iostream> 2 #include<malloc.h> 3 using namespace std; 4 5 #define MAXSIZE 10000 6 7 int getdigit(int x,int d) 8 { 9 int a[] = {1, 1, 10, 100}; //最大三位數,所以這里只要百位就滿足了。 10 return (x/a[d]) % 10; 11 } 12 void PrintArr(int ar[],int n) 13 { 14 for(int i = 0;i < n; ++i) 15 { 16 cout<<ar[i]<<" "; 17 } 18 cout<<endl; 19 } 20 void lsdradix_sort(int arr[],int begin,int end,int d) 21 { 22 const int radix = 10; 23 int count[radix], i, j; 24 25 int *bucket = (int*)malloc((end-begin+1)*sizeof(int)); //所有桶的空間開辟 26 27 //按照分配標准依次進行排序過程 28 for(int k = 1; k <= d; ++k) 29 { 30 //置空 31 for(i = 0; i < radix; i++) 32 { 33 count[i] = 0; 34 } 35 //統計各個桶中所盛數據個數 36 for(i = begin; i <= end; i++) 37 { 38 count[getdigit(arr[i], k)]++; 39 } 40 //count[i]表示第i個桶的右邊界索引 41 for(i = 1; i < radix; i++) 42 { 43 count[i] = count[i] + count[i-1]; 44 } 45 //把數據依次裝入桶(注意裝入時候的分配技巧) 46 for(i = end;i >= begin; --i) //這里要從右向左掃描,保證排序穩定性 47 { 48 j = getdigit(arr[i], k); //求出關鍵碼的第k位的數字, 例如:576的第3位是5 49 bucket[count[j]-1] = arr[i]; //放入對應的桶中,count[j]-1是第j個桶的右邊界索引 50 --count[j]; //對應桶的裝入數據索引減一 51 } 52 53 //注意:此時count[i]為第i個桶左邊界 54 55 //從各個桶中收集數據 56 for(i = begin,j = 0; i <= end; ++i, ++j) 57 { 58 arr[i] = bucket[j]; 59 } 60 } 61 free(bucket); 62 } 63 64 void main() 65 { 66 int br[10] = {20, 80, 90, 589, 998, 965, 852, 123, 456, 789}; 67 cout<<"原數據如下:"<<endl; 68 PrintArr(br,10); 69 lsdradix_sort(br, 0, 9, 3); 70 cout<<"排序后數據如下:"<<endl; 71 PrintArr(br, 10); 72 } 73 /* 74 原數據如下: 75 20 80 90 589 998 965 852 123 456 789 76 排序后數據如下: 77 20 80 90 123 456 589 789 852 965 998 78