亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > C++ > 正文

C++線性時間的排序算法分析

2020-01-26 15:24:33
字體:
來源:轉載
供稿:網友

前面的文章已經介紹了幾種排序算法,如插入排序(直接插入排序,折半插入排序,希爾排序)、交換排序(冒泡排序,快速排序)、選擇排序(簡單選擇排序,堆排序)、2-路歸并排序(可以參考前一篇文章:各種內部排序算法的實現)等,這些排序算法都有一個共同的特點,就是基于比較。

本文將介紹三種非比較的排序算法:計數排序,基數排序,桶排序。它們將突破比較排序的Ω(nlgn)下界,以線性時間運行。

一、比較排序算法的時間下界

所謂的比較排序是指通過比較來決定元素間的相對次序。

“定理:對于含n個元素的一個輸入序列,任何比較排序算法在最壞情況下,都需要做Ω(nlgn)次比較。”
也就是說,比較排序算法的運行速度不會快于nlgn,這就是基于比較的排序算法的時間下界。

通過決策樹(Decision-Tree)可以證明這個定理,關于決策樹的定義以及證明過程在這里就不贅述了。讀者可以自己去查找資料,這里推薦大家看一看麻省理工學院公開課:算法導論的《MIT公開課:線性時間排序》

根據上面的定理,我們知道任何比較排序算法的運行時間不會快于nlgn。那么我們是否可以突破這個限制呢?當然可以,接下來我們將介紹三種線性時間的排序算法,它們都不是通過比較來排序的,因此,下界Ω(nlgn)對它們不適用。

二、計數排序(Counting Sort)

計數排序的基本思想就是對每一個輸入元素x,確定小于x的元素的個數,這樣就可以把x直接放在它在最終輸出數組的位置上,例如:

 

算法的步驟大致如下:

①.找出待排序的數組中最大和最小的元素

②.統計數組中每個值為i的元素出現的次數,存入數組C的第i項

③.對所有的計數累加(從C中的第一個元素開始,每一項和前一項相加)

④.反向填充目標數組:將每個元素i放在新數組的第C(i)項,每放一個元素就將C(i)減去1

C++代碼如下:

/*************************************************************************   > File Name: CountingSort.cpp   > Author: SongLee  ************************************************************************/ #include<iostream> using namespace std;  /*  *計數排序:A和B為待排和目標數組,k為數組中最大值,len為數組長度  */ void CountingSort(int A[], int B[], int k, int len) {   int C[k+1];   for(int i=0; i<k+1; ++i)     C[i] = 0;   for(int i=0; i<len; ++i)     C[A[i]] += 1;   for(int i=1; i<k+1; ++i)     C[i] = C[i] + C[i-1];   for(int i=len-1; i>=0; --i)   {     B[C[A[i]]-1] = A[i];     C[A[i]] -= 1;   } }  /* 輸出數組 */ void print(int arr[], int len) {   for(int i=0; i<len; ++i)     cout << arr[i] << " ";   cout << endl; }  /* 測試 */ int main() {   int origin[8] = {4,5,3,0,2,1,15,6};   int result[8];   print(origin, 8);   CountingSort(origin, result, 15, 8);   print(result, 8);   return 0; }

當輸入的元素是0到k之間的整數時,時間復雜度是O(n+k),空間復雜度也是O(n+k)。當k不是很大并且序列比較集中時,計數排序是一個很有效的排序算法。計數排序是一個穩定的排序算法。

可能你會發現,計數排序似乎饒了點彎子,比如當我們剛剛統計出C,C[i]可以表示A中值為i的元素的個數,此時我們直接順序地掃描C,就可以求出排序后的結果。的確是這樣,不過這種方法不再是計數排序,而是桶排序,確切地說,是桶排序的一種特殊情況。

三、桶排序(Bucket Sort)

桶排序(Bucket Sort)的思想是將數組分到有限數量的桶子里。每個桶子再個別排序(有可能再使用別的排序算法)。當要被排序的數組內的數值是均勻分配的時候,桶排序可以以線性時間運行。桶排序過程動畫演示:Bucket Sort,桶排序原理圖如下:

 

C++代碼如下:

/*************************************************************************   > File Name: BucketSort.cpp   > Author: SongLee  ************************************************************************/ #include<iostream> using namespace std;  /* 節點 */ struct node {   int value;   node* next; };  /* 桶排序 */ void BucketSort(int A[], int max, int len) {   node bucket[len];   int count=0;   for(int i=0; i<len; ++i)   {     bucket[i].value = 0;     bucket[i].next = NULL;   }      for(int i=0; i<len; ++i)   {     node *ist = new node();     ist->value = A[i];     ist->next = NULL;     int idx = A[i]*len/(max+1); // 計算索引     if(bucket[idx].next == NULL)     {       bucket[idx].next = ist;     }     else /* 按大小順序插入鏈表相應位置 */     {       node *p = &bucket[idx];       node *q = p->next;       while(q!=NULL && q->value <= A[i])       {         p = q;         q = p->next;       }       ist->next = q;       p->next = ist;     }   }    for(int i=0; i<len; ++i)   {     node *p = bucket[i].next;     if(p == NULL)       continue;     while(p!= NULL)     {       A[count++] = p->value;       p = p->next;     }   } }  /* 輸出數組 */ void print(int A[], int len) {   for(int i=0; i<len; ++i)     cout << A[i] << " ";   cout << endl; }  /* 測試 */ int main() {   int row[11] = {24,37,44,12,89,93,77,61,58,3,100};   print(row, 11);   BucketSort(row, 235, 11);   print(row, 11);   return 0; } 

四、基數排序(Radix Sort)

基數排序(Radix Sort)是一種非比較型排序算法,它將整數按位數切割成不同的數字,然后按每個位分別進行排序?;鶖蹬判虻姆绞娇梢圆捎肕SD(Most significant digital)或LSD(Least significant digital),MSD是從最高有效位開始排序,而LSD是從最低有效位開始排序。

當然我們可以采用MSD方式排序,按最高有效位進行排序,將最高有效位相同的放到一堆,然后再按下一個有效位對每個堆中的數遞歸地排序,最后再將結果合并起來。但是,這樣會產生很多中間堆。所以,通常基數排序采用的是LSD方式。

LSD基數排序實現的基本思路是將所有待比較數值(正整數)統一為同樣的數位長度,數位較短的數前面補零。然后,從最低位開始,依次進行一次排序。這樣從最低位排序一直到最高位排序完成以后, 數列就變成一個有序序列。需要注意的是,對每一個數位進行排序的算法必須是穩定的,否則就會取消前一次排序的結果。通常我們使用計數排序或者桶排序作為基數排序的輔助算法。基數排序過程動畫演示:Radix Sort

C++實現(使用計數排序)如下:

/*************************************************************************   > File Name: RadixSort.cpp   > Author: SongLee  ************************************************************************/ #include<iostream> using namespace std;  // 找出整數num第n位的數字 int findIt(int num, int n) {   int power = 1;   for (int i = 0; i < n; i++)   {     power *= 10;   }   return (num % power) * 10 / power; }  // 基數排序(使用計數排序作為輔助) void RadixSort(int A[], int len, int k) {   for(int i=1; i<=k; ++i)   {     int C[10] = {0};  // 計數數組     int B[len];    // 結果數組      for(int j=0; j<len; ++j)     {       int d = findIt(A[j], i);       C[d] += 1;     }      for(int j=1; j<10; ++j)       C[j] = C[j] + C[j-1];      for(int j=len-1; j>=0; --j)     {       int d = findIt(A[j], i);       C[d] -= 1;       B[C[d]] = A[j];     }          // 將B中排好序的拷貝到A中     for(int j=0; j<len; ++j)       A[j] = B[j];   } }  // 輸出數組 void print(int A[], int len) {   for(int i=0; i<len; ++i)     cout << A[i] << " ";   cout << endl; }  // 測試 int main() {   int A[8] = {332, 653, 632, 5, 755, 433, 722, 48};   print(A, 8);   RadixSort(A, 8, 3);   print(A, 8);   return 0; }

基數排序的時間復雜度是 O(k?n),其中n是排序元素個數,k是數字位數。注意這不是說這個時間復雜度一定優于O(nlgn),因為n可能具有比較大的系數k。

另外,基數排序不僅可以對整數排序,也可以對有多個關鍵字域的記錄進行排序。例如,根據三個關鍵字年、月、日來對日期進行排序。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
亚洲视频在线观看网站| 久久激情五月丁香伊人| 久操成人在线视频| 欧美最顶级的aⅴ艳星| 欧美激情伊人电影| 国产精品高潮呻吟久久av无限| 午夜精品美女自拍福到在线| 92看片淫黄大片欧美看国产片| 久久影视电视剧免费网站清宫辞电视| 欧美伊久线香蕉线新在线| 性色av一区二区三区在线观看| 亚洲aⅴ日韩av电影在线观看| 中文字幕精品—区二区| 日韩av电影国产| 久久久精品国产一区二区| 欧美一区二区三区四区在线| 精品福利一区二区| 日本亚洲精品在线观看| 日韩欧美第一页| 美女扒开尿口让男人操亚洲视频网站| 欧美成人免费播放| 日韩av高清不卡| 亚洲第一网站免费视频| 欧美国产中文字幕| 国产日韩欧美影视| 中文字幕免费国产精品| 91理论片午午论夜理片久久| 精品亚洲一区二区三区在线播放| 日韩欧美国产激情| 国产亚洲视频中文字幕视频| 精品国产31久久久久久| 黄色91在线观看| 欧美亚洲日本黄色| 国产精品热视频| 美女久久久久久久| 亚洲精品乱码久久久久久金桔影视| 不用播放器成人网| 欧美精品在线播放| 一区二区三区动漫| 欧美一级在线亚洲天堂| 日韩高清a**址| 日韩欧美国产激情| 国产精品激情av在线播放| 久久久久久久久久国产| 亚洲视频国产视频| 亚洲综合在线做性| 亚洲天堂影视av| 2019中文字幕在线观看| 欧美自拍视频在线| 91免费观看网站| 亚洲国产日韩欧美在线99| xxxx欧美18另类的高清| 亚洲精品视频在线播放| 日韩av电影免费观看高清| xx视频.9999.com| 欧美精品第一页在线播放| 91精品国产自产在线老师啪| 亚洲色图校园春色| 在线观看不卡av| 国产成人亚洲综合青青| 国内精品美女av在线播放| 成人午夜两性视频| 一区二区三区精品99久久| 亚洲精品小视频在线观看| 国产mv免费观看入口亚洲| 欧美高清一级大片| 夜色77av精品影院| 国产欧美va欧美va香蕉在| 欧美成人激情视频免费观看| 亚洲激情久久久| 国产97色在线|日韩| 久久亚洲精品一区| 亚洲精品在线看| 黄色91在线观看| 另类天堂视频在线观看| 成人字幕网zmw| 81精品国产乱码久久久久久| 成人久久久久久| 精品国内产的精品视频在线观看| 欧美猛少妇色xxxxx| 亚洲人成电影网站色| 成人精品在线视频| 欧美日韩成人精品| 国产成人精品在线| 亚洲精品98久久久久久中文字幕| 欧美成人免费大片| 欧美日韩亚洲系列| 国产精品露脸自拍| 精品动漫一区二区| 久99久在线视频| 精品亚洲永久免费精品| 亚洲日韩欧美视频一区| 欧美国产日韩二区| 韩剧1988免费观看全集| 亚洲成人a级网| 日韩av手机在线看| 日本人成精品视频在线| 国产成人精品999| 欧美日韩中文字幕在线| 日韩激情av在线播放| 懂色av一区二区三区| 日本精品视频在线播放| 欧美午夜性色大片在线观看| 中文综合在线观看| 国产婷婷97碰碰久久人人蜜臀| 97色在线播放视频| 黑人与娇小精品av专区| 国产精品久久久久91| 欧美黑人又粗大| 欧美俄罗斯性视频| 久久91亚洲精品中文字幕奶水| 欧美一区二区视频97| 亚洲视频电影图片偷拍一区| 国产一区二区三区在线观看视频| 91免费高清视频| 久久久久久网址| 亚洲国产精品网站| 亚洲色图五月天| 亚洲的天堂在线中文字幕| 亚洲另类图片色| 欧美国产精品va在线观看| 欧美激情精品久久久久久免费印度| 久久亚洲电影天堂| 亚洲欧美日韩精品久久亚洲区| 亚洲国产三级网| 中文字幕一精品亚洲无线一区| www.日韩.com| 国产成人中文字幕| 国产一区av在线| 亚洲乱码国产乱码精品精天堂| 91久久精品在线| 欧美日韩在线视频首页| 亚洲精品成人久久电影| 亚洲精品国产综合久久| 午夜精品久久久久久久男人的天堂| 久久91亚洲人成电影网站| 国产亚洲欧洲在线| 日本高清不卡的在线| 最近中文字幕2019免费| 69久久夜色精品国产7777| 国产91在线播放精品91| 久久福利网址导航| 国产91在线播放精品91| 亚洲精品第一国产综合精品| 国产偷国产偷亚洲清高网站| 国内成人精品一区| 日韩视频第一页| 欧美精品在线免费播放| 国产玖玖精品视频| 欧美视频在线免费看| 亚洲欧美精品一区二区| 国产精品成人久久久久| 26uuu另类亚洲欧美日本一| 国产精品a久久久久久| 亚洲999一在线观看www| 国产精品成人品| 日韩视频免费大全中文字幕| 亚洲欧美日韩在线一区| 欧美一级视频一区二区| 久久av在线播放| 欧美日本中文字幕| 91大神在线播放精品| 久久露脸国产精品| 欧美在线性视频|