C++經典排序算法總結


轉發請注明出處:https://www.cnblogs.com/fnlingnzb-learner/p/9374732.html

 最近在研究一些經常用到的東西想把它們做一個匯總,想了想用到最多的應該是排序算法,所以對排序算法做了個總結,並自己用C++實現了一下。

一、算法概述

0.1 算法分類

十種常見排序算法可以分為兩大類:

非線性時間比較類排序:通過比較來決定元素間的相對次序,由於其時間復雜度不能突破O(nlogn),因此稱為非線性時間比較類排序。

線性時間非比較類排序:不通過比較來決定元素間的相對次序,它可以突破基於比較排序的時間下界,以線性時間運行,因此稱為線性時間非比較類排序。 

0.2 算法復雜度

0.3 相關概念

穩定:如果a原本在b前面,而a=b,排序之后a仍然在b的前面。

不穩定:如果a原本在b的前面,而a=b,排序之后 a 可能會出現在 b 的后面。

時間復雜度:對排序數據的總的操作次數。反映當n變化時,操作次數呈現什么規律。

空間復雜度:是指算法在計算機內執行時所需存儲空間的度量,它也是數據規模n的函數。 

二、快速排序

假設我們現在對“6  1  2 7  9  3  4  5 10  8”這個10個數進行排序。首先在這個序列中隨便找一個數作為基准數(不要被這個名詞嚇到了,就是一個用來參照的數,待會你就知道它用來做啥的了)。為了方便,就讓第一個數6作為基准數吧。接下來,需要將這個序列中所有比基准數大的數放在6的右邊,比基准數小的數放在6的左邊,類似下面這種排列:

3  1  2 5  4  6  9 7  10  8

在初始狀態下,數字6在序列的第1位。我們的目標是將6挪到序列中間的某個位置,假設這個位置是k。現在就需要尋找這個k,並且以第k位為分界點,左邊的數都小於等於6,右邊的數都大於等於6,遞歸對左右兩個區間進行同樣排序即可。想一想,你有辦法可以做到這點嗎?這就是快速排序所解決的問題。

快速排序是C.R.A.Hoare於1962年提出的一種划分交換排序。它采用了一種分治的策略,通常稱其為分治法(Divide-and-ConquerMethod)。它的平均時間復雜度為O(nlogn),最壞時間復雜度為O(n^2).

首先上圖:

 

 從圖中我們可以看到:

left指針,right指針,base參照數。

其實思想是蠻簡單的,就是通過第一遍的遍歷(讓left和right指針重合)來找到數組的切割點。

第一步:首先我們從數組的left位置取出該數(20)作為基准(base)參照物。(如果是選取隨機的,則找到隨機的哨兵之后,將它與第一個元素交換,開始普通的快排)

第二步:從數組的right位置向前找,一直找到比(base)小的數,如果找到,將此數賦給left位置(也就是將10賦給20),此時數組為:10,40,50,10,60, left和right指針分別為前后的10。

第三步:從數組的left位置向后找,一直找到比(base)大的數,如果找到,將此數賦給right的位置(也就是40賦給10),此時數組為:10,40,50,40,60, left和right指針分別為前后的40。

第四步:重復“第二,第三“步驟,直到left和right指針重合,最后將(base)放到40的位置, 此時數組值為: 10,20,50,40,60,至此完成一次排序。

第五步:此時20已經潛入到數組的內部,20的左側一組數都比20小,20的右側作為一組數都比20大, 以20為切入點對左右兩邊數按照"第一,第二,第三,第四"步驟進行,最終快排大功告成。

快速排序代碼如下:

 1 //快速排序,隨機選取哨兵放前面 
 2 void QuickSort(int* h, int left, int right)
 3 {
 4     if(h==NULL) return;
 5     if(left>=right) return;
 6     
 7     //防止有序隊列導致快速排序效率降低 
 8     srand((unsigned)time(NULL));
 9     int len=right-left;
10     int kindex=rand()%(len+1)+left;
11     Swap(h[left],h[kindex]);
12     
13     int key=h[left],i=left,j=right;
14     while(i<j)
15     {
16         while(h[j]>=key && i<j) --j;
17         if(i<j) h[i]=h[j];
18         while(h[i]<key && i<j) ++i;
19         if(i<j) h[j]=h[i];
20     }
21     
22     h[i]=key;
23     
24     //QuickSort(&h[left],0,i-1);
25     //QuickSort(&h[j+1],0,right-j-1);
26     
27     QuickSort(h,left,i-1);
28     QuickSort(h,j+1,right);
29 }

 

三、冒泡排序

1.原理

冒泡排序在掃描過程中兩兩比較相鄰記錄,如果反序則交換,最終,最大記錄就被“沉到”了序列的最后一個位置,第二遍掃描將第二大記錄“沉到”了倒數第二個位置,重復上述操作,直到n-1 遍掃描后,整個序列就排好序了。

2.算法實現

 1 //冒泡排序 
 2 void BubbleSort(int* h, size_t len)
 3 {
 4     if(h==NULL) return;
 5     if(len<=1) return;
 6     //i是次數,j是具體下標 
 7     for(int i=0;i<len-1;++i)
 8         for(int j=0;j<len-1-i;++j)
 9             if(h[j]>h[j+1])
10                 Swap(h[j],h[j+1]);
11                 
12     return;
13 } 

 

四、選擇排序

選擇排序也是一種簡單直觀的排序算法。它的工作原理很容易理解:初始時在序列中找到最小(大)元素,放到序列的起始位置作為已排序序列;然后,再從剩余未排序元素中繼續尋找最小(大)元素,放到已排序序列的末尾。以此類推,直到所有元素均排序完畢。

注意選擇排序與冒泡排序的區別:冒泡排序通過依次交換相鄰兩個順序不合法的元素位置,從而將當前最小(大)元素放到合適的位置;而選擇排序每遍歷一次都記住了當前最小(大)元素的位置,最后僅需一次交換操作即可將其放到合適的位置。

算法實現:

 1 //選擇排序
 2 void SelectionSort(int* h, size_t len)
 3 {
 4     if(h==NULL) return;
 5     if(len<=1) return;
 6     
 7     int minindex,i,j;
 8     //i是次數,也即排好的個數;j是繼續排
 9     for(i=0;i<len-1;++i)
10     {
11         minindex=i;
12         for(j=i+1;j<len;++j)
13         {
14             if(h[j]<h[minindex]) minindex=j;
15         }
16         Swap(h[i],h[minindex]); 
17     }
18     
19     return; 
20 }

 

五、插入排序

直接插入排序(straight insertion sort),有時也簡稱為插入排序(insertion sort),是減治法的一種典型應用。其基本思想如下:

  • 對於一個數組A[0,n]的排序問題,假設認為數組在A[0,n-1]排序的問題已經解決了。
  • 考慮A[n]的值,從右向左掃描有序數組A[0,n-1],直到第一個小於等於A[n]的元素,將A[n]插在這個元素的后面。

  很顯然,基於增量法的思想在解決這個問題上擁有更高的效率。

直接插入排序對於最壞情況(嚴格遞減的數組),需要比較和移位的次數為n(n-1)/2;對於最好的情況(嚴格遞增的數組),需要比較的次數是n-1,需要移位的次數是0。當然,對於最好和最壞的研究其實沒有太大的意義,因為實際情況下,一般不會出現如此極端的情況。然而,直接插入排序對於基本有序的數組,會體現出良好的性能,這一特性,也給了它進一步優化的可能性。(希爾排序)。直接插入排序的時間復雜度是O(n^2),空間復雜度是O(1),同時也是穩定排序。

下面用一個具體的場景,直觀地體會一下直接插入排序的過程:

場景:

現有一個無序數組,共7個數:89 45 54 29 90 34 68。

使用直接插入排序法,對這個數組進行升序排序。

89 45 54 29 90 34 68

45 89 54 29 90 34 68

45 54 89 29 90 34 68

29 45 54 89 90 34 68

29 45 54 89 90 34 68

29 34 45 54 89 90 68

29 34 45 54 68 89 90

 

算法實現:

 1 //插入排序
 2 void InsertSort(int* h, size_t len)
 3 {
 4     if(h==NULL) return;
 5     if(len<=1) return;
 6     
 7     int i,j;
 8     //i是次數,也即排好的個數;j是繼續排
 9     for(i=1;i<len;++i)
10         for(j=i;j>0;--j)
11             if(h[j]<h[j-1]) Swap(h[j],h[j-1]);
12             else break;
13             
14     return;
15 }

 

六、歸並排序

基本思想

  歸並排序(MERGE-SORT)是利用歸並的思想實現的排序方法,該算法采用經典的分治(divide-and-conquer)策略(分治法將問題(divide)成一些小的問題然后遞歸求解,而治(conquer)的階段則將分的階段得到的各答案"修補"在一起,即分而治之)。

分而治之

   可以看到這種結構很像一棵完全二叉樹,本文的歸並排序我們采用遞歸去實現(也可采用迭代的方式去實現)。階段可以理解為就是遞歸拆分子序列的過程,遞歸深度為log2n。

合並相鄰有序子序列

  再來看看階段,我們需要將兩個已經有序的子序列合並成一個有序序列,比如上圖中的最后一次合並,要將[4,5,7,8]和[1,2,3,6]兩個已經有序的子序列,合並為最終序列[1,2,3,4,5,6,7,8],來看下實現步驟。

 

算法實現:

 1 //歸並排序
 2 void  MergeArray(int* arr, size_t left, size_t mid, size_t right, int* temp)
 3 {
 4     if(arr==NULL) return;
 5     
 6     size_t i=left,j=mid+1,k=0;
 7     while(i<=mid && j<=right)
 8     {
 9         if(arr[i]<=arr[j])
10         {
11             temp[k++]=arr[i++];
12             continue;
13         }
14         
15         temp[k++]=arr[j++];
16     }
17     
18     while(i<=mid)
19         temp[k++]=arr[i++];
20         
21     while(j<=right)
22         temp[k++]=arr[j++];
23         
24     memcpy(&arr[left],temp,k*sizeof(int));
25         
26     return;
27 }
28 
29 void MMergeSort(int* arr, size_t left, size_t right, int* temp)
30 {
31     if(left<right)
32     {
33         size_t mid=(left+right)/2;
34         MMergeSort(arr, left, mid, temp);
35         MMergeSort(arr, mid+1,right, temp);
36         MergeArray(arr,left, mid, right, temp);
37     }
38 }
39 
40 void MergeSort(int* h, size_t len)
41 {
42     if(h==NULL) return;
43     if(len<=1) return;
44     int* temp=(int*)calloc(len,sizeof(int));
45     MMergeSort(h, 0, len-1, temp);
46     
47     memcpy(h,temp,sizeof(int)*len);
48     
49     free(temp);
50     
51     return;
52 }

 

七、希爾排序

希爾排序是希爾(Donald Shell)於1959年提出的一種排序算法。希爾排序也是一種插入排序,它是簡單插入排序經過改進之后的一個更高效的版本,也稱為縮小增量排序,同時該算法是沖破O(n2)的第一批算法之一。本文會以圖解的方式詳細介紹希爾排序的基本思想及其代碼實現。

基本思想

  希爾排序是把記錄按下標的一定增量分組,對每組使用直接插入排序算法排序;隨着增量逐漸減少,每組包含的關鍵詞越來越多,當增量減至1時,整個文件恰被分成一組,算法便終止。

  簡單插入排序很循規蹈矩,不管數組分布是怎么樣的,依然一步一步的對元素進行比較,移動,插入,比如[5,4,3,2,1,0]這種倒序序列,數組末端的0要回到首位置很是費勁,比較和移動元素均需n-1次。而希爾排序在數組中采用跳躍式分組的策略,通過某個增量將數組元素划分為若干組,然后分組進行插入排序,隨后逐步縮小增量,繼續按組進行插入排序操作,直至增量為1。希爾排序通過這種策略使得整個數組在初始階段達到從宏觀上看基本有序,小的基本在前,大的基本在后。然后縮小增量,到增量為1時,其實多數情況下只需微調即可,不會涉及過多的數據移動。

  我們來看下希爾排序的基本步驟,在此我們選擇增量gap=length/2,縮小增量繼續以gap = gap/2的方式,這種增量選擇我們可以用一個序列來表示,{n/2,(n/2)/2...1},稱為增量序列。希爾排序的增量序列的選擇與證明是個數學難題,我們選擇的這個增量序列是比較常用的,也是希爾建議的增量,稱為希爾增量,但其實這個增量序列不是最優的。此處我們做示例使用希爾增量。

 

算法實現:

 1 //希爾排序
 2 void ShellSort(int* h, size_t len)
 3 {
 4     if(h==NULL) return;
 5     if(len<=1) return;
 6     
 7     for(int div=len/2;div>=1;div/=2)
 8         for(int k=0;k<div;++k)
 9             for(int i=div+k;i<len;i+=div)
10                 for(int j=i;j>k;j-=div)
11                     if(h[j]<h[j-div]) Swap(h[j],h[j-div]);
12                     else break;
13                 
14     return;
15 } 

 

八、堆排序

堆排序實際上是利用堆的性質來進行排序的,要知道堆排序的原理我們首先一定要知道什么是堆。 
堆的定義: 
堆實際上是一棵完全二叉樹。 
堆滿足兩個性質: 
1、堆的每一個父節點都大於(或小於)其子節點; 
2、堆的每個左子樹和右子樹也是一個堆。 
堆的分類: 
堆分為兩類: 
1、最大堆(大頂堆):堆的每個父節點都大於其孩子節點; 
2、最小堆(小頂堆):堆的每個父節點都小於其孩子節點; 
這里寫圖片描述 
堆的存儲: 
一般都用數組來表示堆,i結點的父結點下標就為(i – 1) / 2。它的左右子結點下標分別為2 * i + 1和2 * i + 2。如下圖所示: 
這里寫圖片描述 
堆排序: 
由上面的介紹我們可以看出堆的第一個元素要么是最大值(大頂堆),要么是最小值(小頂堆),這樣在排序的時候(假設共n個節點),直接將第一個元素和最后一個元素進行交換,然后從第一個元素開始進行向下調整至第n-1個元素。所以,如果需要升序,就建一個大堆,需要降序,就建一個小堆。 
堆排序的步驟分為三步: 
1、建堆(升序建大堆,降序建小堆); 
2、交換數據; 
3、向下調整。 
假設我們現在要對數組arr[]={8,5,0,3,7,1,2}進行排序(降序): 
首先要先建小堆: 
這里寫圖片描述
堆建好了下來就要開始排序了: 
這里寫圖片描述
現在這個數組就已經是有序的了。 

 

算法實現:

 1 //堆排序
 2 /*
 3 大頂堆sort之后,數組為從小到大排序 
 4 */ 
 5 //====調整=====
 6 void AdjustHeap(int* h, int node, int len)  //----node為需要調整的結點編號,從0開始編號;len為堆長度 
 7 {
 8     int index=node;
 9     int child=2*index+1; //左孩子,第一個節點編號為0 
10     while(child<len)
11     {
12         //右子樹 
13         if(child+1<len && h[child]<h[child+1])
14         {
15             child++;
16         }
17         if(h[index]>=h[child]) break;
18         Swap(h[index],h[child]);
19         index=child;
20         child=2*index+1;
21     }
22 }
23 
24 
25 //====建堆=====
26 void MakeHeap(int* h, int len)
27 {
28     for(int i=len/2;i>=0;--i)
29     {
30         AdjustHeap(h, i, len);
31     }
32 }
33 
34 //====排序=====
35 void HeapSort(int* h, int len)
36 {
37     MakeHeap(h, len);
38     for(int i=len-1;i>=0;--i)
39     {
40         Swap(h[i],h[0]);
41         AdjustHeap(h, 0, i);
42     }
43 }

 

九、基數排序

基數排序與本系列前面講解的七種排序方法都不同,它不需要比較關鍵字的大小

它是根據關鍵字中各位的值,通過對排序的N個元素進行若干趟“分配”與“收集”來實現排序的。 

1.LSD(低位到高位的排序)

不妨通過一個具體的實例來展示一下,基數排序是如何進行的。 

設有一個初始序列為: R {50, 123, 543, 187, 49, 30, 0, 2, 11, 100}。

我們知道,任何一個阿拉伯數,它的各個位數上的基數都是以0~9來表示的。

所以我們不妨把0~9視為10個桶。 

我們先根據序列的個位數的數字來進行分類,將其分到指定的桶中。例如:R[0] = 50,個位數上是0,將這個數存入編號為0的桶中。

 

分類后,我們在從各個桶中,將這些數按照從編號0到編號9的順序依次將所有數取出來。

這時,得到的序列就是個位數上呈遞增趨勢的序列。 

按照個位數排序: {50, 30, 0, 100, 11, 2, 123, 543, 187, 49}。

接下來,可以對十位數、百位數也按照這種方法進行排序,最后就能得到排序完成的序列。

LSD 算法實現:

  1 int GetMaxDight(int* h, int len)
  2 {
  3     if(h==NULL) return 0;
  4     if(len<1) return 0;
  5     
  6     int max=h[0];
  7     for(int i=1;i<len;++i)
  8     {
  9         if(h[i]>max) max=h[i];
 10     }
 11     
 12     int digit=1;
 13     while(max/10!=0)
 14     {
 15         max/=10;
 16         ++digit;
 17     }
 18     
 19     return digit;
 20 } 
 21 
 22 int GetReminder(int value,int digit)
 23 {
 24     int div=1;
 25     for(int i=1;i<digit;++i)
 26         div*=10;
 27     
 28     return value/div%10;
 29 }
 30 
 31 void RadixSort_LSD(int* h, int len)
 32 {
 33     if(h==NULL) return;
 34     if(len<=1) return;
 35     
 36     int digit=GetMaxDight(h,len);
 37     //printf("MaxDigit:%d\n", digit);
 38     
 39     int count[10]={0};
 40     int *tmp=(int*)calloc(len,sizeof(int));
 41     
 42     for(int d=1;d<=digit;++d)
 43     {
 44         memset(count,0,sizeof(count));
 45         
 46         for(int i=0;i<len;++i)
 47         {
 48             count[GetReminder(h[i],d)]++;
 49         }
 50         
 51         //求右邊界 
 52         for(int i=1;i<10;++i)
 53         {
 54             count[i]+=count[i-1];
 55         }
 56         
 57         for(int i=len-1;i>=0;--i)
 58         {
 59             int r=GetReminder(h[i],d);
 60             int index=count[r];
 61             tmp[index-1]=h[i];
 62             count[r]--;
 63         }
 64         
 65         memcpy(h,tmp,len*sizeof(int));
 66     }
 67     
 68     free(tmp);
 69 }
 70 
 71 void RadixSort_LSD_Reverse(int* h, int len)
 72 {
 73     if(h==NULL) return;
 74     if(len<=1) return;
 75     
 76     int digit=GetMaxDight(h,len);
 77     //printf("MaxDigit:%d\n", digit);
 78 
 79     int count[10]={0};
 80     
 81     int *tmp=(int*)calloc(len,sizeof(int));
 82     
 83     for(int d=1;d<=digit;++d)
 84     {
 85         memset(count,0,sizeof(count));
 86         
 87         for(int i=0;i<len;++i)
 88         {
 89             count[GetReminder(h[i],d)]++;
 90         }
 91         
 92         //printf("haha\n");
 93         
 94         //求右邊界 
 95         for(int i=8;i>=0;--i)
 96         {
 97             count[i]+=count[i+1];
 98         }
 99         
100         
101         
102         for(int i=len-1;i>=0;--i)
103         {
104             int r=GetReminder(h[i],d);
105             int index=count[r];
106             tmp[index-1]=h[i];
107             count[r]--;
108         }
109         
110         memcpy(h,tmp,len*sizeof(int));
111     }
112     
113     free(tmp);
114 }

 

2.MSD(高位到低位排序)

下面我們直接來介紹MSD基數排序的步驟。

MSD基數排序是從最高位開始對序列進行分組,到最低位為止。但是其實現過程是和LSD基數排序不同的,排序過程中需要用到遞歸函數。

待排序序列

170, 45, 75, 90, 2, 24, 802, 66

我們看到,這里面的最大的數是3位數。所以說我們開始從百位對這些數進行分組

0: 045, 075, 090,002, 024, 066
1: 170
2-7: 空
8: 802
9: 空

從這里開始就和LSD基數排序有差別了。在LSD基數排序中,每次分好組以后開始對桶中的數據進行收集。然后根據下一位,對收集后的序列進行分組。而對於MSD,在這里不會對桶中的數據進行收集。我們要做的是檢測每個桶中的數據。當桶中的元素個數多於1個的時候,要對這個桶遞歸進行下一位的分組。

在這個例子中,我們要對0桶中的所有元素根據十位上的數字進行分組

0: 002
1: 空
2: 024
3: 空
4: 045
5: 空
6: 066
7: 075
8: 空
9: 090

按照上面所說,我們應該再遞歸的對每個桶中的元素根據個位上的數進行分組。但是我們發現,現在在每個桶中的元素的個數都是小於等於1的。因此,到這一步我們就開始回退了。也就是說我們開始收集桶中的數據。收集完成以后,回退到上一層。此時按照百位進行分組的桶變成了如下的形式

0: 002, 024, 045,066, 075, 090
1: 170
2-7: 空
8: 802
9: 空

然后我們在對這個桶中的數據進行收集。收集起來以后序列如下

2, 24, 45, 66, 75, 90, 170, 802

整個MSD基數排序就是按照上面的過程進行的。

在我對MSD基數排序步驟進行敘述的時候,中間遞歸函數的過程可能敘述的不夠清楚。我個人建議對遞歸函數不了解的可以先了解一下遞歸函數的原理,然后再回來看這個過程可能對MSD基數排序過程更容易理解。

算法實現:

  1 int GetMaxDight(int* h, int len)
  2 {
  3     if(h==NULL) return 0;
  4     if(len<1) return 0;
  5     
  6     int max=h[0];
  7     for(int i=1;i<len;++i)
  8     {
  9         if(h[i]>max) max=h[i];
 10     }
 11     
 12     int digit=1;
 13     while(max/10!=0)
 14     {
 15         max/=10;
 16         ++digit;
 17     }
 18     
 19     return digit;
 20 } 
 21 
 22 int GetReminder(int value,int digit)
 23 {
 24     int div=1;
 25     for(int i=1;i<digit;++i)
 26         div*=10;
 27     
 28     return value/div%10;
 29 }
 30 
 31 void RRadixSort_MSD(int* h, int begin, int end, int digit)
 32 {
 33     if(h==NULL) return;
 34     if(begin>=end) return;
 35     if(digit<1) return;
 36     
 37     int start[10];
 38     int count[10]={0};
 39     int *tmp=(int*)calloc(end-begin+1,sizeof(int));
 40     
 41     for(int i=begin;i<=end;++i)
 42     {
 43         count[GetReminder(h[i],digit)]++;
 44     }
 45     
 46     memcpy(start,count,sizeof(start));
 47     
 48     //求右邊界
 49     for(int i=1;i<10;++i)
 50     {
 51         start[i]+=start[i-1];
 52     } 
 53     
 54     for(int i=end;i>=begin;--i)
 55     {
 56         int r=GetReminder(h[i],digit);
 57         int index=start[r];
 58         tmp[index-1]=h[i];
 59         start[r]--;
 60     }
 61     
 62     /*
 63     for(int i=0;i<10;++i)
 64     {
 65         printf("%d ",start[i]);
 66     }
 67     
 68     printf("\n");
 69     */
 70     
 71     memcpy(&h[begin],tmp,(end-begin+1)*sizeof(int));
 72     
 73     for(int i=0;i<10;++i)
 74     {
 75         if(count[i]>1)
 76         {
 77             RRadixSort_MSD(h, start[i], start[i]+count[i]-1, digit-1);
 78         }
 79     }
 80 }
 81 
 82 void RadixSort_MSD(int* h, int len)
 83 {
 84     if(h==NULL) return;
 85     if(len<=1) return;
 86     
 87     int digit=GetMaxDight(h,len);
 88     
 89     //printf("MaxDigit:%d\n",digit);
 90     
 91     RRadixSort_MSD(h, 0, len-1, digit);
 92 }
 93 
 94 void RRadixSort_MSD_Reverse(int* h, int begin, int end, int digit)
 95 {
 96     if(h==NULL) return;
 97     if(begin>=end) return;
 98     if(digit<1) return;
 99     
100     int start[10];
101     int count[10]={0};
102     int *tmp=(int*)calloc(end-begin+1,sizeof(int));
103     
104     for(int i=begin;i<=end;++i)
105     {
106         count[GetReminder(h[i],digit)]++;
107     }
108     
109     memcpy(start,count,sizeof(start));
110     
111     //求右邊界
112     for(int i=8;i>=0;--i)
113     {
114         start[i]+=start[i+1];
115     } 
116     
117     for(int i=end;i>=begin;--i)
118     {
119         int r=GetReminder(h[i],digit);
120         int index=start[r];
121         tmp[index-1]=h[i];
122         start[r]--;
123     }
124     
125     /*
126     for(int i=0;i<10;++i)
127     {
128         printf("%d ",start[i]);
129     }
130     
131     printf("\n");
132     */
133     
134     memcpy(&h[begin],tmp,(end-begin+1)*sizeof(int));
135     
136     for(int i=0;i<10;++i)
137     {
138         if(count[i]>1)
139         {
140             RRadixSort_MSD_Reverse(h, start[i], start[i]+count[i]-1, digit-1);
141         }
142     }
143 }
144 
145 void RadixSort_MSD_Reverse(int* h, int len)
146 {
147     if(h==NULL) return;
148     if(len<=1) return;
149     
150     int digit=GetMaxDight(h,len);
151     
152     //printf("MaxDigit:%d\n",digit);
153     
154     RRadixSort_MSD_Reverse(h, 0, len-1, digit);
155 }

 

十、主函數

 

 1 void Swap(int& a, int& b)
 2 {
 3     int t=a;
 4     a=b;
 5     b=t;
 6     
 7     return;
 8 }
 9 
10 int main()
11 {
12     int A[10]={0};
13     srand((unsigned)time(NULL));
14     
15     printf("before:\n");
16     for(int i=0;i<10;++i)
17     {
18         A[i]=rand()%100;
19         printf("%d ",A[i]);
20     }
21     printf("\n");
22     
23     printf("after:\n");
24     //QuickSort(A,0,9);
25     //BubbleSort(A,sizeof(A)/sizeof(int));
26     //SelectionSort(A,sizeof(A)/sizeof(int));
27     //InsertSort(A,sizeof(A)/sizeof(int));
28     //MergeSort(A,sizeof(A)/sizeof(int));
29     //ShellSort(A,sizeof(A)/sizeof(int));
30     //HeapSort(A,sizeof(A)/sizeof(int));
31     //RadixSort_LSD(A,sizeof(A)/sizeof(int));
32     //RadixSort_MSD(A,sizeof(A)/sizeof(int));
33     //RadixSort_LSD_Reverse(A,sizeof(A)/sizeof(int));
34     RadixSort_MSD_Reverse(A,sizeof(A)/sizeof(int));
35     for(int i=0;i<sizeof(A)/sizeof(int);++i)
36     {
37         printf("%d ",A[i]);
38     }
39     printf("\n");
40     
41     return 0;
42 }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM