無聊時總結總結演算法之07堆排序

2021-07-10 01:30:05 字數 1812 閱讀 8127

二叉堆的定義

二叉堆是完全二叉樹或者是近似完全二叉樹。

二叉堆滿足二個特性:

1.父結點的鍵值總是大於或等於(小於或等於)任何乙個子節點的鍵值。

2.每個結點的左子樹和右子樹都是乙個二叉堆(都是最大堆或最小堆)。

當父結點的鍵值總是大於或等於任何乙個子節點的鍵值時為最大堆。當父結點的鍵值總是小於或等於任何乙個子節點的鍵值時為最小堆。下圖展示乙個最小堆:

由於其它幾種堆(二項式堆,斐波納契堆等)用的較少,一般將二叉堆就簡稱為堆

實現堆排序

實現堆排序需解決兩個問題:

1. 如何將n 個待排序的數建成堆;

2. 輸出堆頂元素後,怎樣調整剩餘n-1 個元素,使其成為乙個新堆。

首先討論第二個問題:輸出堆頂元素後,對剩餘n-1元素重新建成堆的調整過程。

調整小頂堆的方法:

1)設有m 個元素的堆,輸出堆頂元素後,剩下m-1 個元素。將堆底元素送入堆頂((最後乙個元素與堆頂進行交換),堆被破壞,其原因僅是根結點不滿足堆的性質。

2)將根結點與左、右子樹中較小元素的進行交換。

3)若與左子樹交換:如果左子樹堆被破壞,即左子樹的根結點不滿足堆的性質,則重複方法 (2).

4)若與右子樹交換,如果右子樹堆被破壞,即右子樹的根結點不滿足堆的性質。則重複方法 (2).

5)繼續對不滿足堆性質的子樹進行上述交換操作,直到葉子結點,堆被建成。

再討論對n 個元素初始建堆的過程

建堆方法:對初始序列建堆的過程,就是乙個反覆進行篩選的過程。

1)n 個結點的完全二叉樹,則最後乙個結點是第個結點的子樹。

2)篩選從第個結點為根的子樹開始,該子樹成為堆。

3)之後向前依次對各結點為根的子樹進行篩選,使之成為堆,直到根結點。

/**

* 已知h[s…m]除了h[s] 外均滿足堆的定義

* 調整h[s],使其成為大頂堆.即將對第s個結點為根的子樹篩選,

* *@param h是待調整的堆陣列

*@param s是待調整的陣列元素的位置

*@param length是陣列的長度

* */

void heapadjust(int h,int s, int length)

if(h[s]// 如果較大的子結點大於父結點

h[s] = h[child]; // 那麼把較大的子結點往上移動,替換它的父結點

s = child; // 重新設定s ,即待調整的下乙個結點的位置

child = 2*s+1;

}else

// 如果當前待調整結點大於它的左右孩子,則不需要調整,直接退出

h[s] = tmp; // 當前待調整的結點放到比其大的孩子結點位置上

}print(h,length);

}/**

* 初始堆進行調整

* 將h[0..length-1]建成堆

* 調整完之後第乙個元素是序列的最小的元素

*/void buildingheap(int h, int length)

/** * 堆排序演算法

*/void heapsort(int h,int length)

}int main();

cout<

print(h,10);

heapsort(h,10);

//selectsort(a, 8);

cout<

print(h,10);

}

無聊時總結總結演算法之08桶排序

桶排序 bucket sort 或所謂的箱排序的原理是將陣列分到有限數量的桶子裡,然後對每個桶子再分別排序 有可能再使用別的排序演算法或是以遞迴方式繼續使用桶排序進行排序 最後將各個桶中的資料有序的合併起來。排序過程 假設待排序的一組數統一的分布在乙個範圍中,並將這一範圍劃分成幾個子範圍,也就是桶 ...

無聊時總結總結演算法之01遞迴

1 階乘 n n n 1 n 2 1 n 0 first problem 階乘n int jiecheng int n 2 河內塔問題 second problem 河內塔問題 1 把1座上 n 1 個盤子借助3座移到2座。2 把1座上第n個盤子移動3座。3 把2座上 n 1 個盤子借助1座移動3座...

六一兒童節之LeetCode習題總結 演算法(14)

首先先上原題 背景闡述 輸入 candies 2,3,5,1,3 extracandies 3 輸出 true,true,true,false,true 解釋 孩子 1 有 2 個糖果,如果他得到所有額外的糖果 3個 那麼他總共有 5 個糖果,他將成為擁有最多糖果的孩子。孩子 2 有 3 個糖果,如...