排序系列算法——堆排序

堆:大根堆與小根堆ios

      堆排序是創建在堆基礎上的排序方法,首先了解一下什麼是堆。數組

      經常使用的堆通常有兩種,大根堆和小根堆。堆能夠看作是一棵二叉樹,其父節點的值老是大於(大根堆)或者小於(小根堆)子節點的值。舉一個例子:ui

 

                         圖1 不知足堆的條件                 圖2大根堆                             圖3 小根堆spa

      圖1不是堆,由於不知足父節點的值大於或者小於子節點的值;3d

      圖2是大根堆,根節點是最大值,父節點都大於或等於子節點的值;code

      圖3是小根堆,根節點是最小值,父節點都小於或等於子節點的值。blog

堆排序排序

      下面以大根堆爲例講解堆排序:io

      大根堆有一個很好的性質,根節點的數值老是大於其餘全部節點的數值,利用這個性質,能夠實現排序的工做。堆排序的步驟能夠描述以下:class

      1.構建大根堆。首先咱們的原始數組通常狀況下是不知足堆的條件,既然咱們要可用大根段的性質進行排序,第一步固然是對原始數組進行處理,構建大根堆。

      2.根節點數據處理以及大根堆重構。構建了大根堆以後,根節點的數據是最大值,將該數值取出,對剩下的元素重構大根堆,這時根節點是剩下元素的最大值,取出。只要不斷重複上述的操做,不斷取出未排序元素的最大值,直到未排序的元素只剩一個,就完成了排序工做。

      說得有點抽象,直接用一個實際的例子說明堆排序的工做步驟:

      對一個無序的序列A={5,4,17,13,15,12,10 }按從小到大進行排序,序列的下標分別爲{1,2,3,4,5,6,7},A[i]表示下標爲i的元素。

      第一步:對無序的數組構造大根堆

 

大根堆的根節點是整個序列的最大值。

       第二步

       將A[1]與A[7]互換,此時A[7]爲序列的最大值,A[7]已經排序完畢,剩餘的元素A[1]~A[6]造成新的未排序序列,因爲此時序列不是大根堆,須要重構大根堆。


       第三步

       將A[1]與A[6]互換,此時A[6]爲序列的最大值,A[6]已經排序完畢,剩餘的元素A[1]~A[5]造成新的未排序序列,因爲此時序列不是大根堆,須要重構大根堆。

      第四步

      將A[1]與A[5]互換,此時A[5]爲序列的最大值,A[5]已經排序完畢,剩餘的元素A[1]~A[4]造成新的未排序序列,因爲此時序列不是大根堆,須要重構大根堆。

      第五步

      將A[1]與A[4]互換,此時A[4]爲序列的最大值,A[4]已經排序完畢,剩餘的元素A[1]~A[3]造成新的未排序序列,因爲此時序列不是大根堆,須要重構大根堆。

      第六步

      將A[1]與A[3]互換,此時A[3]爲序列的最大值,A[3]已經排序完畢,因爲此時未排序的序列只剩下兩個元素,並且A[0]>A[1],將A[0]與A[1]互換便可獲得最終的已排序序列。

 

 

C++程序實現

從上述的排序過程可知,堆排序主要有兩個過程,大根堆的構建與重構:

一、大根堆的重構

  如何實現大根堆的重構?若是一個原有的數組知足大根堆的性質,而只有其中一個元素改變從而破壞了大根堆的性質,那麼能夠從該元素出發,不斷」逐級降低「,讓子節點小於等於父子節點,知足大根堆的性質。以一個實例說明重構的過程:

  堆排序的過程當中,每一次改變的只有根節點的元素,所以只須要從根節點出發,進行如上圖的操做便可實現大根堆的重構。C++代碼以下:

 1 void ReBuildMaxHeap(int *array,int arraylength,int startIndex){
 2     int index=0;
 3     //int j=0;
 4     int max=0;
 5     while((2*startIndex+1)<arraylength){
 6         index = startIndex;
 7         max = array[index];
 8         if(max<(array[2*startIndex+1])){
 9             max=array[2*startIndex+1];
10             index=2*startIndex+1;
11         }
12         if(2*startIndex+2<arraylength&&max<array[2*startIndex+2]){
13             max=array[2*startIndex+2];
14             index=2*startIndex+2;
15         }
16         if(index==startIndex){
17             break;
18         }
19         swap(array,index,startIndex);
20         startIndex = index;
21     }
22 }

一、  構建大根堆。

  要構建大根堆,只須要遍歷全部非葉子節點元素,使其全部的葉子節點均不大於足該節點元素便可。構建大根堆自低向上對數組進行遍歷,若是發現父節點的值小於子節點的值,則將父節點的值與子節點的最大值進行交換,保證父節點的數據老是大於子節點的數據。若是發生了數據的交換,有可能令子節點不知足大根堆條件,須要進行會輸重構大根堆。以一個實際的例子說明構建大根堆的過程:

C++代碼以下:

 1 void createHeap(int *array,int length){
 2     int max=0;
 3     int index=0;
 4     for(int i=floor(length/2)-1;i>=0;i--){
 5         index = i;
 6         max = array[i];
 7         if(max<array[2*i+1]){
 8             index=2*i+1;
 9             max = array[2*i+1];
10         }
11         if(2*i+2<length&&max<array[2*i+2]){
12             index = 2*i+2;
13             max = array[2*i+2];
14         }
15         if(index!=i){
16             swap(array,index,i);
17             ReBuildMaxValue(array,length,index);
18         }
19     }
20 }

 

所有源代碼:

 1 #include "stdafx.h"
 2 #include <iostream>
 3 using namespace std;
 4 
 5 //兩個文位置的數據交換
 6 void swap(int *array,int num1,int num2){
 7     int temp = *(array+num1);
 8     *(array+num1) = *(array+num2);
 9     *(array+num2) = temp;
10 }
11 
12 //重構大根堆
13 void ReBuildMaxValue(int *array,int arraylength,int startIndex){
14     int index=0;
15     //int j=0;
16     int max=0;
17     while((2*startIndex+1)<arraylength){
18         index = startIndex;
19         max = array[index];
20         if(max<(array[2*startIndex+1])){
21             max=array[2*startIndex+1];
22             index=2*startIndex+1;
23         }
24         if(2*startIndex+2<arraylength&&max<array[2*startIndex+2]){
25             max=array[2*startIndex+2];
26             index=2*startIndex+2;
27         }
28         if(index==startIndex){
29             break;
30         }
31         swap(array,index,startIndex);
32         startIndex = index;
33     }
34 }
35 
36 //構建大根堆
37 void createHeap(int *array,int length){
38     int max=0;
39     int index=0;
40     for(int i=floor(length/2)-1;i>=0;i--){
41         index = i;
42         max = array[i];
43         if(max<array[2*i+1]){
44             index=2*i+1;
45             max = array[2*i+1];
46         }
47         if(2*i+2<length&&max<array[2*i+2]){
48             index = 2*i+2;
49             max = array[2*i+2];
50         }
51         if(index!=i){
52             swap(array,index,i);
53             ReBuildMaxValue(array,length,index);
54         }
55     }
56 }
57 
58 //堆排序
59 void heapSort(int *array,int arraylength){
60     createHeap(array,10);
61     for(int i=arraylength-1;i>0;i--){
62         swap(array,i,0);
63         ReBuildMaxValue(array,i,0);
64     }
65 }
66 
67 int main(int argc, _TCHAR* argv[])
68 {
69     int values[10]={5,4,17,13,15,12,10,7,11,9};
70     heapSort(values,10);
71     for(int i=0;i<10;i++){
72         cout<<*(values+i)<<endl;
73     }
74     return 0;
75 }
相關文章
相關標籤/搜索