乡下人产国偷v产偷v自拍,国产午夜片在线观看,婷婷成人亚洲综合国产麻豆,久久综合给合久久狠狠狠9

  • <output id="e9wm2"></output>
    <s id="e9wm2"><nobr id="e9wm2"><ins id="e9wm2"></ins></nobr></s>

    • 分享

      堆排序

       renhl252 2014-09-29

      【1】完全二叉樹(shù)

      在學(xué)習(xí)堆排序之前,我們先要了解一下完全二叉樹(shù)。

      若設(shè)二叉樹(shù)的深度為h,除第h層外,其它各層 (1...h-1) 的結(jié)點(diǎn)數(shù)都達(dá)到最大個(gè)數(shù),第h層所有的結(jié)點(diǎn)都連續(xù)集中在最左邊,這就是完全二叉樹(shù)。 

      完全二叉樹(shù)特點(diǎn): 

      (1) 滿二叉樹(shù)是完全二叉樹(shù),完全二叉樹(shù)不一定是滿二叉樹(shù)。 

      (2) 在滿二叉樹(shù)的最下一層上,從最右邊開(kāi)始連續(xù)刪去若干結(jié)點(diǎn)后得到的二叉樹(shù)仍然是一棵完全二叉樹(shù)。 

      (3) 在完全二叉樹(shù)中,若某個(gè)結(jié)點(diǎn)沒(méi)有左孩子,則它一定沒(méi)有右孩子,即該結(jié)點(diǎn)必是葉結(jié)點(diǎn)。

      (4)如下圖所示,結(jié)點(diǎn)C沒(méi)有左孩子而有右孩子F,故它不是一棵完全二叉樹(shù)。

      (5)如下圖所示,兩棵完全二叉樹(shù)(右邊b為滿二叉樹(shù))。

      (6)下圖是一棵天然的完全二叉樹(shù)

      【2】堆(Heap)

      在程序設(shè)計(jì)領(lǐng)域,堆(Heap)的概念主要有以下兩種:

      (1)一種數(shù)據(jù)結(jié)構(gòu),邏輯上是一顆完全二叉樹(shù),存儲(chǔ)上是一個(gè)數(shù)組對(duì)象(二叉堆)。也正是本文談及的堆。

      (2)存儲(chǔ)區(qū),是軟件系統(tǒng)可以編程的內(nèi)存區(qū)域(即就是動(dòng)態(tài)申請(qǐng)的區(qū)域)。

      數(shù)據(jù)結(jié)構(gòu)中的堆實(shí)質(zhì)上是滿足一定性質(zhì)的完全二叉樹(shù):二叉樹(shù)中任一非葉子結(jié)點(diǎn)關(guān)鍵字的值均小于(大于)它的孩子結(jié)點(diǎn)的關(guān)鍵字。

      在小根堆中,第一個(gè)元素(完全二叉樹(shù)的根結(jié)點(diǎn))的關(guān)鍵字最?。?/span>

      大根堆中,第一個(gè)元素(完全二叉樹(shù)的根結(jié)點(diǎn))的關(guān)鍵字最大,

      顯然,堆中任一子樹(shù)仍是一個(gè)堆。

      假設(shè),節(jié)點(diǎn)I是數(shù)組A中下標(biāo)為i的節(jié)點(diǎn):

      那么,節(jié)點(diǎn)I的父節(jié)點(diǎn)下標(biāo)為:(i-1)/2

      節(jié)點(diǎn)I的左子節(jié)點(diǎn)下標(biāo)為:2 * i + 1

      節(jié)點(diǎn)I的右子節(jié)點(diǎn)下標(biāo)為:2 * i + 2

      詳細(xì)圖解如下存儲(chǔ)與邏輯表示

      【3】堆存儲(chǔ)與邏輯結(jié)構(gòu)表示

      如下圖所示:

      注意:示例中的邏輯結(jié)構(gòu)堆不是最大堆也不是最小堆,僅僅只是為了便于理解堆的邏輯結(jié)構(gòu)。

      【4】堆排序定義

      n個(gè)關(guān)鍵字序列Kl,K2,…,Kn稱(chēng)為堆,當(dāng)且僅當(dāng)該序列滿足如下性質(zhì)(簡(jiǎn)稱(chēng)為堆性質(zhì)):

      (1) ki ≤ K2i 且 ki ≤ K2i+1  或  (2) Ki ≥ K2i 且 ki ≥ K2i+1((i=1,2,…,[n/2],其中[]表示上取整)

      若將此序列所存儲(chǔ)的向量R[1..n]看做是一棵完全二叉樹(shù)的存儲(chǔ)結(jié)構(gòu),則堆實(shí)質(zhì)上是滿足如下性質(zhì)的完全二叉樹(shù):

      樹(shù)中任一非葉結(jié)點(diǎn)的關(guān)鍵字均不大于(或不小于)其左右孩子(若存在)結(jié)點(diǎn)的關(guān)鍵字。

      【5】堆排序思想

      堆排序利用了大根堆(或小根堆)堆頂(根節(jié)點(diǎn))記錄的關(guān)鍵字最大(或最小)這一特征,使得在當(dāng)前無(wú)序區(qū)中選取最大(或最小)關(guān)鍵字的記錄變得簡(jiǎn)單。

      (1)用大根堆排序的基本思想

      <1>先將初始文件R[1.....N]建成一個(gè)大根堆,此堆為初始的無(wú)序區(qū)。

      <2>再將關(guān)鍵字最大的記錄R[1](即堆頂)和無(wú)序區(qū)的最后一個(gè)記錄R[n]交換

      由此得到新的無(wú)序區(qū)R[1..n-1]和有序區(qū)R[n],且滿足R[1..n-1].keys ≤ R[n].key

      <3>由于交換后新的根R[1]可能違反堆性質(zhì),故應(yīng)將當(dāng)前無(wú)序區(qū)R[1..n-1]調(diào)整為堆。

      然后再次將R[1..n-1]中關(guān)鍵字最大的記錄R[1]和該區(qū)間的最后一個(gè)記錄R[n-1]交換

      由此得到新的無(wú)序區(qū)R[1..n-2]和有序區(qū)R[n-1..n],且仍滿足關(guān)系R[1..n-2].keys  ≤  R[n-1..n].keys,同樣要將R[1..n-2]調(diào)整為堆。

      直到無(wú)序區(qū)只有一個(gè)元素為止。

      (2)大根堆排序算法的基本操作:

      <1> 初始化操作:將R[1..n]構(gòu)造為初始堆;

      <2>每一趟排序的基本操作:將當(dāng)前無(wú)序區(qū)的堆頂記錄R[1]和該區(qū)間的最后一個(gè)記錄交換,然后將新的無(wú)序區(qū)調(diào)整為堆(亦稱(chēng)重建堆)。

      注意:

      <1>只需做n-1趟排序,選出較大的n-1個(gè)關(guān)鍵字即可以使得文件遞增有序。

      <2>用小根堆排序與利用大根堆類(lèi)似,只不過(guò)其排序結(jié)果是遞減有序的。

      堆排序和直接選擇排序相反:在任何時(shí)刻,堆排序中無(wú)序區(qū)總是在有序區(qū)之前,且有序區(qū)是在原向量的尾部由后往前逐步擴(kuò)大至整個(gè)向量為止。

      (3)排序邏輯結(jié)構(gòu)演示如下圖所示:

      請(qǐng)結(jié)合以上邏輯分析內(nèi)容或以下實(shí)現(xiàn)代碼加深對(duì)堆排序的理解。

      【6】堆排序?qū)崿F(xiàn)

      (1)C++實(shí)現(xiàn)與測(cè)試代碼如下:

      復(fù)制代碼
        1 #include<iostream>
        2 using namespace std;
        3 
        4 void swap(int &a,int &b)
        5 {
        6     int temp = a;
        7     a = b;
        8     b = temp;
        9 }
       10 
       11 void  PrintArr(int ar[],int n)
       12 {
       13     for(int i = 0; i < n; ++i)
       14         cout<<ar[i]<<" ";
       15     cout<<endl;
       16 }
       17 
       18 void AdjustHeap(int data[], int start, int m)  
       19 {  
       20     int i = 0, j = 0;  
       21     int value = data[start];  
       22     for(i = start, j = 2*i + 1; j <= m; i = j, j = 2*j+1)  
       23     {  
       24         cout<<"i = "<<i<<" j = "<<j<<" value = "<<value<<endl;
       25         if(j < m  && data[j] < data[j+1])  
       26         {
       27             ++j;
       28         }
       29         if(value > data[j])    
       30             break;  
       31         else   
       32             data[i] = data[j];     
       33         PrintArr(data, 6);
       34     }  
       35     data[i] = value; 
       36     PrintArr(data, 6);
       37 }  
       38 
       39 void HeapSort(int data[],int size)
       40 {
       41     int i = 0;
       42     cout<<"調(diào)整為最大堆的過(guò)程:"<<endl;
       43     for(i = size/2-1; i >= 0; --i)
       44     {
       45         cout<<"i = "<<i<<" size = "<<size<<endl;
       46         AdjustHeap(data, i, size-1);
       47     }
       48     cout<<"調(diào)整為最大堆結(jié)果如下:"<<endl;
       49     PrintArr(data, size);
       50     cout<<"整個(gè)排序過(guò)程如下:"<<endl;
       51     for(i = size - 1; i >= 1; --i)
       52     {
       53         swap(data[0], data[i]);
       54         PrintArr(data, size);
       55         AdjustHeap(data, 0, i-1);        
       56         PrintArr(data, size);
       57     }
       58 } 
       59 
       60 void  main()
       61 {
       62     int  ar[] = {12, 88, 32, 5, 16, 67};
       63     int len = sizeof(ar)/sizeof(int);
       64     cout<<"原數(shù)據(jù)序列為:"<<endl;
       65     PrintArr(ar, len);
       66     HeapSort(ar, len);
       67     cout<<"排序后結(jié)果如下:"<<endl;
       68     PrintArr(ar, len);
       69 } 
       70 /*
       71 原數(shù)據(jù)序列為:
       72 12 88 32 5 16 67
       73 調(diào)整為最大堆的過(guò)程:
       74 i = 2 size = 6
       75 i = 2 j = 5 value = 32
       76 12 88 67 5 16 67
       77 12 88 67 5 16 32
       78 i = 1 size = 6
       79 i = 1 j = 3 value = 88
       80 12 88 67 5 16 32
       81 i = 0 size = 6
       82 i = 0 j = 1 value = 12
       83 88 88 67 5 16 32
       84 i = 1 j = 3 value = 12
       85 88 16 67 5 16 32
       86 88 16 67 5 12 32
       87 調(diào)整為最大堆結(jié)果如下:
       88 88 16 67 5 12 32
       89 整個(gè)排序過(guò)程如下:
       90 32 16 67 5 12 88
       91 i = 0 j = 1 value = 32
       92 67 16 67 5 12 88
       93 67 16 32 5 12 88
       94 67 16 32 5 12 88
       95 12 16 32 5 67 88
       96 i = 0 j = 1 value = 12
       97 32 16 32 5 67 88
       98 32 16 12 5 67 88
       99 32 16 12 5 67 88
      100 5 16 12 32 67 88
      101 i = 0 j = 1 value = 5
      102 16 16 12 32 67 88
      103 16 5 12 32 67 88
      104 16 5 12 32 67 88
      105 12 5 16 32 67 88
      106 i = 0 j = 1 value = 12
      107 12 5 16 32 67 88
      108 12 5 16 32 67 88
      109 5 12 16 32 67 88
      110 5 12 16 32 67 88
      111 5 12 16 32 67 88
      112 排序后結(jié)果如下:
      113 5 12 16 32 67 88
      114  */
      復(fù)制代碼

      (2)堆排序代碼示例:

      復(fù)制代碼
       1 void swap(int &a,int &b)
       2 {
       3     int temp = a;
       4     a = b;
       5     b = temp;
       6 }
       7 
       8 void AdjustHeap(int data[], int start, int m)  
       9 {  
      10     int i = 0, j = 0;  
      11     int value = data[start];  
      12     for(i = start, j = 2*i + 1; j <= m; i = j, j = 2*j+1)  
      13     {  
      14         if(j < m  && data[j] < data[j+1])  
      15         {
      16             ++j;
      17         }
      18         if(value > data[j])    
      19             break;  
      20         else   
      21             data[i] = data[j];     
      22     }  
      23     data[i] = value; 
      24 
      25 }  
      26 
      27 void HeapSort(int data[],int size)
      28 {
      29     int i = 0;
      30     for(i = size/2-1; i >= 0; --i)
      31     {
      32         AdjustHeap(data, i, size-1);
      33     }
      34     for(i = size - 1; i >= 1; --i)
      35     {
      36         swap(data[0], data[i]);
      37         AdjustHeap(data, 0, i-1);        
      38     }
      39 } 
      復(fù)制代碼

      堆排序的實(shí)現(xiàn)代碼有很多種實(shí)現(xiàn)方式,在此僅作為參考。

      【7】堆排序分析

      堆排序的時(shí)間,主要由建立初始堆和反復(fù)重建堆這兩部分的時(shí)間開(kāi)銷(xiāo)構(gòu)成,它們均是通過(guò)調(diào)用堆調(diào)整函數(shù)實(shí)現(xiàn)的。

      堆排序的最壞時(shí)間復(fù)雜度為O(nlgn)(參見(jiàn)隨筆《算法復(fù)雜度》)。堆排序的平均性能較接近于最壞性能。

      由于建初始堆所需的比較次數(shù)較多,所以堆排序不適宜于記錄數(shù)較少的文件。

      堆排序是就地排序,輔助空間為O(1)。

      它是不穩(wěn)定的排序方法(參見(jiàn)隨筆《常用排序算法穩(wěn)定性分析》)。

       

      Good Good Study, Day Day Up.

      順序  選擇  循環(huán)  堅(jiān)持  總結(jié)

        本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶(hù)發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買(mǎi)等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
        轉(zhuǎn)藏 分享 獻(xiàn)花(0

        0條評(píng)論

        發(fā)表

        請(qǐng)遵守用戶(hù) 評(píng)論公約

        類(lèi)似文章 更多