演算法導論 第六章《堆排序》

2021-06-19 20:34:59 字數 3081 閱讀 6998

本章開始介紹了堆的基本概念,然後引入最大堆和最小堆的概念。全章採用最大堆來介紹堆的操作,兩個重要的操作是調整最大堆和建立最大堆,接著著兩個操作引進了堆排序,最後介紹了採用堆實現優先順序佇列。

(二叉)堆資料結構是一種陣列物件,它可以被視為一棵完全二叉樹。除了最底層外,該樹是完全充滿的,而且是從左到右填充的。樹中每個節點與陣列中的存放該節點值的那個元素對應。堆與完全二叉樹的對應關係如下圖所示:

表示堆的陣列a包括兩個屬性: a.length是陣列中的元素個數,a.heap-size是存放在中的堆的元素個數。通常給定節點i,可以根據其在陣列中的位置求出該節點的父親節點、左右孩子節點。輸的根節點是a[1],對於乙個給定結點的下標i,所有可到:

根據節點數值滿足的條件,可以將分為最大堆和最小堆。最大堆的特性是:除了根節點以外的每個節點i,有a[parent(i)] >= a[i],最小堆的特性是:除了根節點以外的每個節點i,有a[parent(i)] >=a[i]。

把堆看成乙個棵樹,有如下的特性:

(1)含有n個元素的堆的高度是lgn。

(2)當用陣列表示儲存了n個元素的堆時,葉子節點的下標是n/2+1,n/2+2,……,n。

(3)在最大堆中,最大元素該子樹的根上;在最小堆中,最小元素在該子樹的根上。

堆的關鍵操作過程是如何維持堆的特有性質,給定乙個節點i,要保證以i為根的子樹滿足堆性質。書中以最大堆作為例子進行講解,並給出了遞迴形式的保持最大堆性的操作過程max-heapify。先從看乙個例子,操作過程如下圖所示:

從圖中可以看出,在節點i=2時,不滿足最大堆的要求,需要進行調整,選擇節點2的左右孩子中最大乙個進行交換,然後檢查交換後的節點i=4是否滿足最大堆的要求,從圖看出不滿足,接著進行調整,直到沒有交換為止。書中給出了遞迴形式的偽**:

max-heapify(a,i)

1 l = left(i)

2 r = right(i)

3 if l<=a.heap-size and a[l] > a[i]

4 largest = l

5 else largest = i

6 if r <= a.heap-size and a[r] > a[largest]

7 largest = r

8 if largest != i

9 exchange a[i] with a[largest]

10 max-heapify(a, largest)

建立最大堆的過程是自底向上地呼叫最大堆調整程式將乙個陣列a[1.....n]變成乙個最大堆。將陣列視為一顆完全二叉樹,從其最後乙個非葉子節點(n/2)開始調整。調整過程如下圖所示:

書中給出了建立堆的為**

build-max-heap(a)

1 a.heap-size = a.length

2 for i = a.length/2 downto 1

3 max-heapify(a, i)

堆排序演算法過程為:先呼叫建立堆函式將輸入陣列a[1...n]造成乙個最大堆,使得最大的值存放在陣列第乙個位置a[1],然後用陣列最後乙個位置元素與第乙個位置進行交換,並將堆的大小減少1,並呼叫最大堆調整函式從第乙個位置調整最大堆。給出堆陣列a=進行堆排序簡單的過程如下:

(1)建立最大堆,陣列第乙個元素最大,執行後結果下圖:

(2)進行迴圈,從length(a)到2,並不斷的調整最大堆,給出乙個簡單過程如下:

書中給出了對排序為**

heapsort(a)

1 build-max-heap(a)

2 for i = a.length downto 2

3 exchange a[1] with a[i]

4 a.heap-size = a.heap-size-1

5 max-heapify(a, 1)

結合上面的調整堆和建立堆 的過程,寫個簡單測試程式連續堆排序,程式如下所示:

/*

*created by rogerking

*email:[email protected]

*/#include #include using namespace std;

int heap_size,i;

int parent(int i)

//查詢堆中節點父母

int left(int i)

//查詢堆中節點左孩子(因為程式下標是從0開始的)

int right(int i)

//查詢堆中節點右孩子

void max_heapify(int a,int i,int n)

}void bulid_max_heap(int a,int n)

void heapsort(int a,int n) }

void display(int a,int n)

return 0;

}

堆排序演算法時間複雜度:調整堆過程滿足遞迴式t(n)<=t(2n/3)+θ(1),有master定義可以知道t(n) = o(lgn),堆排序過程中執行乙個迴圈,呼叫最大堆調整函式,總的時間複雜度為o(nlgn)。

演算法導論 第六章 堆排序

二叉 堆資料結構是一種陣列物件,如下圖所知,他可以被視為一顆完全二叉樹。其有如下性質 1 對於i節點 i表示下標 其父節點為li 2 左孩子節點為2i,右孩子節點為2i 1 2 最大堆滿足 a parent i a i 最小堆滿足 a parent i a i 3 堆的高度為 lgn 4 子陣列元素...

演算法導論第六章 堆排序

堆排序 主要是二叉堆,是乙個陣列,可以近似看作是一棵完全二叉樹。最壞情況執行時間為 n log n 主要性質 1.對於任意乙個下標index,書上寫的是左子女的下標為 2 index,右子女為 2 index 1 但是在實際程式設計中,下標是從0開始的,所以下標的變化應該為 左子女為2 index ...

演算法導論第六章堆排序6 2

6.2 1 第一遍交換10和3 第二遍交換10和9 6.2 2 6.2 2 min heapify a,i 1 l left i 2 r right i 3 if l heap size a and a l a i 4 then smallest l 5 else smallest i 6 if r...