算法導論-排序(三) 堆排序

目錄                                                                                  

    一、堆排序介紹

    二、堆排序實例

    三、c++ 完整代碼

    四、參考資料

內容                                                                                   

    一、堆排序介紹                                                                  

       1.1 、堆是什麼html

              堆是一顆徹底二叉樹,(設某一個節點爲i,根節點從0開始,則其左孩子節點爲2*i+1,右孩子節點爲2*i+2),堆任意一個非葉節點知足:ios

     Key[i]>=Key[2*i+1] &&  Key[i]>=Key[2*i+2] 或者 Key[i]<=Key[2*i+1] &&  Key[i]<=Key[2*i+2],c++

      就是說對於任意一個父節點,要麼大於等於子節點,要麼小於等於子節點,對於Key[i]>=Key[2*i+1] &&  Key[i]>=Key[2*i+2]的堆叫作大頂堆;對於 Key[i]<=Key[2*i+1] &&  Key[i]<=Key[2*i+2]的叫作小頂堆;由上述性質可知大頂堆的堆頂的關鍵字確定是全部關鍵字中最大的,小頂堆的堆頂的關鍵字是全部關鍵字中最小的windows

       1.二、什麼是堆排序數組

             就是在堆的基礎上進行排序,如何排序呢?函數

             [1] 首先,從要排序的數組開始創建一個大頂堆(這裏以大頂堆說明,如何建大頂堆,下面詳解),這樣由大頂堆的性質可知,堆頂的數最大;測試

             [2] 而後,交換堆頂key[0]和堆的最後一個元素Key[n-1],Key[0]<->Key[n-1] ,這樣最大的數就放到堆的最後Key[n-1]了;因爲交換了元素,0 ~ (n-2)的節點可能不知足大頂堆要求,因此而後對堆的Key[0]--Key[n-2]調整爲大頂堆;ui

             [3] 將調整好的大頂堆[0~(N-2)],交換堆頂Key[0]和堆的最後一個元素Key[n-2],Key[0]<->Key[n-2],這樣,Key[n-2]、Key[n-1]最大的兩個數都已經排好了;從新調整[0~(n-3)]爲大頂堆;不斷重複此過程直到整個排序過程完成spa

            如何建大頂堆呢?.net

             [1] 首先,從最大的非葉節點(設爲Key[i])開始,往下進行調整,若是子孩子節點Key[2*i+1]和Key[2*i+2]較大的值比Key[i]的值大,則,交換該節點Key[i]與子節點中較大的節點。而後 以交換後的子節點做爲當前節點,往下進行調整,直到遇到葉節點;

             [2] 最大非葉節點Key[i]調整完畢後,對節點Key[i-1]進行往下調整,直到出現葉節點;不斷重複此過程,直到對根節點往下調整完畢;

            下面是建大頂堆的實例:待排序數組爲[5 16 3 20 17 4]

    二、堆排序實例                                                                  

        上面圖說明了如何建大頂堆,建好大頂堆後就能夠進行排序了,下面是堆排序的實例:

    三、c++ 完整代碼                                                             

    Sort.h(堆排序函數實現)

  1 #ifndef SORT_HH
  2 #define SORT_HH
  3 template<typename T >
  4 class Sort
  5 {
  6 public:    
  7     void Swap(T &m,T &n);//交換數據    
  8     void print_element(vector<T> A);//打印數組
  9     void HeapSort(vector<T> &A,bool IsRecurFlag);        
 10 private:
 11     void HeapAdjust(vector<T> &A,int i,int n);//非遞歸調整堆
 12     void HeapAdjust_Recursive(vector<T> &A,int i,int n);//遞歸調整堆
 13     void BuildBigHeap(vector<T> &A,bool IsRecurFlag);//建大頂堆
 14 };
 15 template<typename T>//交換數據
 16 void Sort<T>::Swap(T &m,T &n)
 17 {
 18     T tmp;
 19     tmp=m;
 20     m=n;
 21     n=tmp;
 22 }
 23 //從i節點開始調整,n爲節點總數 從0開始計算 i節點的子節點爲 2*i+1, 2*i+2
 24 template<typename T>
 25 void Sort<T>::HeapAdjust(vector<T> &A,int i,int n)
 26 {
 27     T temp = A[i];
 28     int j = 2*i+1;//下標從0開始
 29     while (j<n)//非遞歸實現
 30     {
 31         if (j+1<n&&A[j+1]>A[j])//找出子節點的最小值
 32             j++;
 33         if(A[j]<=temp)//子節點不大於父節點,調整結束
 34             break;
 35 
 36         A[i] = A[j];// 子節點最大值大於父節點,值賦給父節點;
 37         i = j;
 38         j = 2*i+1;//下標從0開始
 39     }
 40     A[i] = temp;//調整結束
 41 }
 42 //從i節點開始調整,n爲節點總數 從0開始計算 i節點的子節點爲 2*i+1, 2*i+2
 43 template<typename T>
 44 void Sort<T>::HeapAdjust_Recursive(vector<T> &A,int i,int n)//遞歸調整堆
 45 {
 46     int lchild = 2*i+1;
 47     int rchild = 2*i+2;
 48     int max = i;
 49     if (i<=(n-1)/2)//從最大非葉節點開始調整
 50     {
 51         if (lchild<n&&A[lchild]>A[max])
 52         {
 53             max=lchild;
 54         }
 55         if(rchild<n&&A[rchild]>A[max])
 56         {
 57             max=rchild;
 58         }
 59         if (max!=i)//子節點值比父節點大,調整
 60         {
 61             Swap(A[i],A[max]);
 62             HeapAdjust_Recursive(A,max,n);//遞歸
 63         }
 64     }
 65 }
 66 //初始從待排序數組建大頂堆
 67 //數組從0開始計算,建堆從p到q
 68 template<typename T>
 69 void Sort<T>::BuildBigHeap(vector<T> &A,bool IsRecurFlag)
 70 {
 71     int n=A.size();
 72     for(int i=(n-1)/2;i>=0;i--)//從最大的非葉節點開始
 73     {
 74         if (IsRecurFlag)
 75             HeapAdjust_Recursive(A,i,n);
 76         else
 77             HeapAdjust(A,i,n);
 78     }
 79 }
 80 //堆排序,首先建大頂堆
 81 template<typename T>
 82 void Sort<T>::HeapSort(vector<T> &A,bool IsRecurFlag)
 83 {
 84     int len = A.size();
 85     BuildBigHeap(A,IsRecurFlag);//建大頂堆
 86     for(int i=len-1;i>=0;i--)
 87     {
 88         Swap(A[0],A[i]);//未排序堆第一個和最後一個交換
 89         if (IsRecurFlag)//遞歸
 90             HeapAdjust_Recursive(A,0,i);
 91         else//非遞歸
 92             HeapAdjust(A,0,i);//調整爲大頂堆
 93     }
 94 }
 95 
 96 template<typename T>//打印數組
 97 void Sort<T>::print_element(vector<T> A)
 98 {
 99     int len=A.size();
100     for (int i=0;i<len;i++)
101     {
102         std::cout<<A[i]<<" ";
103     }
104     std::cout<<std::endl;
105 }
106 #endif

 

Sort.cpp(主測試函數)

 1 #include <iostream>
 2 #include <vector>
 3 using namespace std;
 4 #include "Sort.h"
 5 
 6 int main()
 7 {
 8     Sort<int> sort1;
 9     int a[]={2,4,3,178,23,134,1,-27,1345,80};
10     vector<int > vec_int1(a,a+10);
11     cout<<"源數組:";
12     sort1.print_element(vec_int1);
13     cout<<"非遞歸實現排序:";
14     sort1.HeapSort(vec_int1,false);
15     sort1.print_element(vec_int1);
16 
17     vector<int > vec_int2(a,a+10);
18     cout<<"遞歸實現排序:";
19     sort1.HeapSort(vec_int2,true);
20     sort1.print_element(vec_int2);
21     system("PAUSE");
22     return 0;
23 }

 

輸出:

    四、參考資料                                                                      

     【1】 http://www.cnblogs.com/dolphin0520/archive/2011/10/06/2199741.html

 

     【2】 http://blog.csdn.net/morewindows/article/details/6709644

相關文章
相關標籤/搜索