1. 程式人生 > >演算法導論第六章之最大、最小堆

演算法導論第六章之最大、最小堆

堆是很重要的一種資料結構,常常用在排序和優先佇列的實現上,當然在C++ STL中有優先佇列的實現,但是者並不妨礙我們去學習他。

堆其實是一種陣列物件,也就是說他的資料全部都儲存在陣列中,它可以被視為一棵完全二叉樹(不懂二叉樹的請自行百度)。(二叉堆)堆有兩種:最大堆和最小堆。

最大堆
通俗來講,滿足下面要求的完全二叉樹為最大堆:
除了根節點以外的每一個節點i,有:
A[Parent]>=A[i]
注:陣列A[]是儲存堆元素的陣列。
這樣堆中的最大值明顯是儲存在根節點中的(如果有和根節點同樣大的值,其子節點也會儲存最大的資料)。

最小堆:
最小堆和最大堆有點相反的意思,其滿足的條件是在完全二叉樹中,除了根節點以外的節點i,有:
A[Parent]<=a[i]

主要的運用的基本過程:
下面以最大堆來描述各個過程和實現

MAX-HEAPIFY()過程:
保持最大堆的性質,那麼我們假設某個節點i,他的左子樹LEFT(i)和右子數都是最大堆,那麼節點i對於他的兩棵子樹來說可能會小於子數節點,這時候就需要對堆進行調整。執行時間O(lgn);

實現程式碼:
**

//這裡和書上不太一樣,因為他的虛擬碼直接有heapSize
MAX—HEAPIFY(a,int i,int heapSize){
int largest;
int change;
int l = a[i/2];
int r = a[i/2+1];
if(l<=heapSize&&a
[l]>a[i]) largest = l; if(r<=heapSize&&a[r]>a[l]) largest = r; if(largest!=i){ change = a[i]; a[i] = a[largest]; a[largest] = change; MAX-HEAPFIPY(A,largest,heapSize); } } 注:只有節點i和其子節點有過交換才會繼續判斷,否則就是滿足最大堆的要求的。

BUILD-MAX-HEAP()過程:
對於一個儲存陣列(儲存著堆 的節點的值),我們知道1…..n個節點的時候從n/2+1到n是葉子節點,那麼一個葉子節點肯定是一個堆,所以我們對堆進行處理一般是對非葉子結點進行處理。程式碼如下:

BUILD—MAX-HEAP(A,int heapSize){
    for(int i = heapSize/2+1;i<n;i++)
         MAX-HEAPIFY(A,i,heapSize);
}

HEAPSORT()過程:
HEAP()就是堆排序過程,首先將給定的資料排列成一個最大,最小堆(這裡以最大堆為例),然後在對堆進行排序:

HEAPSORT(A,int heapSize){
   BUILD—MAX-HEAP(A,heapsize);
    int leap;
    for(int i = heapSsize-1;i>0;i--){
        leap = a[0];
        a[0] = a[i];
        a[i] = leap;
        heapSize -= 1;
        BUILD-MAX-HEAP(A,a[0],heapSize);  
     }
  }

最小堆的運用實現:

最小堆其實很像最大堆的一個相反的過程。

MIN-HEAPIFY()過程:

MIN—HEAPIFY(a,int i,int heapSize){
int smallest;
int change;
int l = a[i/2];
int r = a[i/2+1];
if(l<=heapSize&&a[l]<a[i])
    largest = l;
if(r<=heapSize&&a[r]<a[l])
    smallest = r;
if(smallest!=i){
    change = a[i];
    a[i] = a[smallest];
    a[smallest] = change;
    MAX-HEAPFIPY(A,smallest,heapSize);
}
}

BUILD—MIN-HEAP過程

BUILD—MIN-HEAP(A,int heapSize){
    for(int i = heapSize/2+1;i<n;i++)
         MIn-HEAPIFY(A,i,heapSize);
}

HEAPSORT()過程

HEAPSORT(A,int heapSize){
    BUILD—MIN-HEAP(A,heapsize);
    int b[N];  ///因為我們的a[0]就是最小,如果想要填補我們有另外一個                                          // 陣列            
    int leap;
    int k = 0;
    for(int i = heapSsize-1;i>0;i--){
        b[k++] = a[0];
        a[0] = a[i];
        heapSize -= 1;
        BUILD-MIN-HEAP(A,a[0],heapSize);  
     }
     b[k++] = a[0];
     for(int i=0;i<k;i++)
        a[i] = b[i];
  }

相關推薦

演算法導論

堆是很重要的一種資料結構,常常用在排序和優先佇列的實現上,當然在C++ STL中有優先佇列的實現,但是者並不妨礙我們去學習他。 堆其實是一種陣列物件,也就是說他的資料全部都儲存在陣列中,它可以被視為一棵完全二叉樹(不懂二叉樹的請自行百度)。(二叉堆)堆有兩種:

演算法導論 排序 筆記(維護的性質排序演算法優先順序佇列排序的程式碼實現)

堆排序(heapsort) 像合併排序而不像插入順序,堆排序的執行時間為O(nlgn) 。像插入排序而不像合併排序,它是一種原地( in place) 排序演算法:在任何時候,陣列中只有常數個元素儲存在輸入陣列以外。 堆: (二叉)堆資料結構是一種陣列物件,它可以被視為一棵完全二叉樹。樹

演算法導論 | 25 所有結點對的短路徑問題

零、前言 前面講了單源最短路徑問題,指定一個原點一個終點,找到最短路徑。但是如果我們要求所有結點對呢? 方案一:可以對每一個結點呼叫一次單源最短路徑演算法,一共呼叫|V|次。(每指定一個原點,可以求出其他任何點到該原點的舉例) 對於權值為非負的圖,可以呼叫Dijkstra

演算法導論排序)

維護堆的性質(MAX-HEAPIFY): 每一步從A[i],A[LEFT(i)],A[RIGHT(i)]中選出最大的。如果A[i]是最大的,程式結束。如果不是,則A[i]和最大的那一個交換。以原來最大的節點為根的字數又可能違反最大堆的性質,因此,對該子樹遞迴呼叫MAX-HE

演算法導論-15-動態規劃-15-2 長迴文子序列(LPS)

問題描述 迴文序列(Palindromic sequence, Palindrome)是指正向遍歷和反向遍歷完全相同的序列,例如字串“AAAAA”顯然是一個迴文序列,又如字串“[email 

演算法導論 23 小生成樹 思考題

23-1 次最優的最小生成樹     (c)根據普利姆演算法計算出最小生成樹,並得到樹的parent陣列(裡面記錄了各頂點的父頂點)。 運用動態規劃方法即可,狀態轉移方程如下: 設頂點個數為V,那麼時間複雜度為O(V2) 。 (d) 1、根據普利姆演算法計算得出最

演算法導論 十三:紅黑樹 筆記(紅黑樹的性質旋轉插入刪除)

紅黑樹(red-black tree) 是許多“平衡的”查詢樹中的一種,它能保證在最壞情況下,基本的動態集合操作的時間為O(lgn) 。 紅黑樹的性質: 紅黑樹是一種二叉查詢樹,但在每個結點上增加一個儲存位表示結點的顏色,可以是RED或BLACK 。通過對任何一條從根到葉子的路徑上各個結

演算法導論 :快速排序 筆記(快速排序的描述快速排序的效能快速排序的隨機化版本快速排序分析)

快速排序的最壞情況時間複雜度為Θ(n^2)。雖然最壞情況時間複雜度很差,但是快速排序通常是實際排序應用中最好的選擇,因為它的平均效能很好。它的期望執行時間複雜度為Θ(n lg n),而且Θ(n lg n)中蘊含的常數因子非常小,而且它還是原址排序的。 快速排序是一種排序演算法,對包含n個數的

演算法導論 :概率分析和隨機演算法 筆記(僱傭問題指示器隨機變數隨機演算法概率分析和指示器隨機變數的進一步使用)

僱傭問題: 假設你需要僱用一名新的辦公室助理。你先前的僱傭嘗試都以失敗告終,所以你決定找一個僱用代理。僱用代理每天給你推薦一個應聘者。你會面試這個人,然後決定要不要僱用他。你必須付給僱用代理一小筆費用來面試應聘者。要真正地僱用一個應聘者則要花更多的錢,因為你必須辭掉目前的辦公室助理,還要付一

演算法導論 :遞迴式 筆記(代換法遞迴樹方法主方法主定理的證明)

三種解遞迴式的方法:代換法、遞迴樹方法、主方法。 代換法: 用代換法解遞迴式需要兩個步驟: 猜測解的形式; 用數學歸納法找出使解真正有效的常數。 如: T(n) = 2T(n/2) + n,這個是合併排序的執行時間的遞迴表示式。歸併排序法的執行時間是O(nlgn),那麼我

演算法導論 :函式的增長 筆記(Θ記號O記號Ω記號o記號ω記號漸近記號的性質標準記號與常用函式)

Θ記號: 該記號圓圈中是個M。Θ記號漸近地給出一個函式的上界和下界。 對於一個給定的函式g(n),我們用Θ(g(n))來表示以下函式的集合: Θ(g(n))={f(n):存在正常量c1、c2和n0,使得對於所有n⩾n0,有0⩽c1g(n)⩽f(n)⩽c2g(n)}。 即若存在正常

演算法部分程式 part 1

▶ 書中第六章部分程式,包括在加上自己補充的程式碼,粒子碰撞系統及用到的粒子類 ● 粒子系統 1 package package01; 2 3 import java.awt.Color; 4 import edu.princeton.cs.algs4.StdIn; 5 imp

演算法部分程式 part 2

▶ 書中第六章部分程式,包括在加上自己補充的程式碼,B-樹 ● B-樹 1 package package01; 2 3 import edu.princeton.cs.algs4.StdOut; 4 5 public class class01<Key extends

強化學習導論 瞬時時間差分法

這一次開第六章,Temporal-Difference 方法,簡稱TD,可以翻譯為瞬時差分法。 TD方法在強化學習演算法中有很重要的地位,因為它是一個集大成的演算法。TD綜合了第五章所說的蒙特卡洛演算法和第四章所說的DP演算法的特點,既可以從真實經驗序列學習,無需環境模型,又可以根據已得到的估計

2018/11/29 演算法時空(2) 演算法導論 函式的增長

漸進記號:   O記號:   歐米茄記號: 注意: O記號是複雜度函式的上限, 歐米茄記號是複雜度函式的下限. 等式/不等式漸進記號:  極限的定義: 通過極限的方法, 來求複雜度函式.   當極限的值是一個大於零

【學習筆記】演算法導論2演算法基礎

//====================================== //Ch2_1_Basic_Sort_Algorthm //====================================== #include<iostream> #

演算法導論貪婪演算法

動態規劃是先分析子問題,再做選擇。而貪心演算法則是先做貪心選擇,做完選擇後,生成了子問題,然後再去求解子問題 與動態規劃方法相似,是更簡單的解決優化問題的方法,通常用於求解優化問題 貪婪演算法不能保證一定得到最優解 對於具有某些特徵的問題,貪婪演算法有最優

演算法導論 13 紅黑樹(圖文詳細解說)

1、二叉查詢樹的不足 二叉查詢樹的基本操作包括搜尋、插入、刪除、取最大和最小值等都能夠在O(h)(h為樹的高度)時間複雜度內實現,因此能在期望時間O(lgn)下實現,但是二叉查詢樹的平衡性在這些操作中並沒有得到維護,其高度可能會變得很高,當其高度較高時,二叉查詢樹的效能就未

演算法導論 10 10.2 連結串列

一、概念 (1)陣列的線性序是由陣列的下標決定的,連結串列中的順序是由各物件中的指標所決定的 (2)連結串列結點結構 node *prev; node *next; int key; (3)連結串列

演算法導論 18 B樹

一、定義 1、B樹 B樹是為磁碟或其它直接存取輔助儲存裝置而設計的一種平衡查詢樹,主要特點是降低磁碟I/O操作次數。 B樹以自然的方式推廣二叉查詢樹。 B樹的分支因子由磁碟特性所決定。  2、B數的資料結構 int n:當前儲存在結點x中的關鍵字數 key[N]:n個關鍵,