線性排序演算法 --- 計數排序,基數排序,桶排序
計數排序應用:
J - Jeronimo's List
http://codeforces.com/gym/101466/problem/J
線性排序演算法計數排序應該挺好理解的,每次把數字出現的次數記錄下來,然後做成字首,字首就是小於等於當前數的個數。
比如 2,3,0,3,6,2,3,5,首先記錄出現次數
0 1 2 3 4 5 6
1 0 2 3 0 1 1
然後對這個陣列做一個字首
c[0] c[1] c[2] c[3] c[4] c[5] c[6]
1 1 3 6 6 7 8
就是這樣 ,然後排序的時候就 輸出數字對應的地方
如 a[i]= 5 那麼 b[c[a[i]]]=a[i]; 把b 數組裡面 7的位置賦值為5.然後小於等於5的數量-1;
#include<bits/stdc++.h> using namespace std; int a[8]= {2,3,0,3,6,2,3,5}; int b[8]; int c[7]; int main() { for(int i=0; i<8; i++) { c[a[i]]++; } for(int i=1; i<7; i++) { //把這個for倒過來就是從大到小 c[i]=c[i-1]+c[i]; } printf("C陣列:\n"); for(int i=0; i<7; i++) { printf("c[%d]\t",i); } printf("\n"); for(int i=0; i<7; i++) { printf(" %d\t",c[i]); } printf("\n"); printf("排序過程\n"); for(int i=7; i>=0; i--) { b[--c[a[i]]]=a[i]; for(int i=0; i<7; i++) { printf("%d ",b[i]); } printf("\n"); } return 0; }
基數排序:
實際上和計數排序沒啥太大的區別 ,計數排序如果數太大,你 C陣列的就要浪費非常大的記憶體,或者根本開不了這麼大的記憶體。
基數排序,就是把每個 位拆分出來,實際上和計數排序差距不大。
12,13,120,33,46,52,3,25
120 12 52 13 33 3 25 46
以最後一位遞增
3 12 13 120 25 33 46 52
在最後一位為遞增基礎上倒數第2位遞增
3 12 13 25 33 46 52 120
最後以 第一位 遞增,就是排序好的
#include<bits/stdc++.h> using namespace std; int a[8]= {12,13,120,33,46,52,3,25}; int b[8]; int c[10]; int main() { int mx=0,pos=0,cot=1; for(int i=0; i<8; i++) { mx=max(mx,a[i]); } while(mx/cot>0) { memset(c,0,sizeof(c)); for(int i=0; i<8; i++) { c[a[i]/cot%10]++; } for(int i=1; i<10; i++) { //把這個for倒過來就是從大到小 c[i]=c[i-1]+c[i]; } printf("計數陣列:\n"); for(int i=0; i<10; i++) { printf("c[%d]\t",i); } printf("\n"); for(int i=0; i<10; i++) { printf(" %d\t",c[i]); } printf("\n"); printf("排序第%d位結果:\n",pos); for(int i=7; i>=0; i--) { b[--c[a[i]/cot%10]]=a[i]; } for(int i=0; i<8; i++) { a[i]=b[i]; } for(int i=0;i<8;i++){ printf("%d ",a[i]); } puts(""); cot*=10; pos++; } return 0; }
桶排序,實際上和計數排序也差不多,但是到目前位置我還沒用過。
計數排序就相當於 桶的大小為 1 的排序 。(基數排序實際上有點類似於以10 的桶裡面套著一個10 的桶)個人理解
開一個桶的大小 b 然後把他一個數x丟到 x/b 那個桶裡面去,然後把每個桶裡面排序。把桶分成1不就是計數排序。。個人理解
理論上來說:在分佈桶均勻的情況下,是O(n+n*(2-1/n));
有些情況下可能退化成 普通排序一樣的複雜度。
程式碼就不敲了,還沒用過。。。。