第三章:查詢與排序(下)----------- 3.16堆的概念及堆排序思路
堆的概念及堆排序思路:
二叉堆是完全二叉樹,或者近似完全二叉樹。
二叉堆滿足兩個特性:
---1、父節點的鍵值總是大於或等於(小於或等於)任何一個節點的鍵值;
---2、每個節點的左子樹和右子樹都是一個二叉堆(都是最大堆或最小堆)。
任何節點的值都大於其子節點的值------大頂堆
任何節點的值都小於其子節點的值------小頂堆
堆排序:
1、堆化,反向調整使得每個子樹都是大頂或者小頂堆;
2、按序輸出元素:把堆頂和堆末元素對調,然後調整堆頂元素。
虛擬碼:
MakeMinHeap(A){
n=A.length;
for i from n/2-1 down to 0{
MinHeapFixDown(A,i);
}
}
/*
①、先看有沒有左右孩子;
②、找到左右孩子中較小的那個;
③、調整(交換或者不交換);
④、遞迴地向下調整。
*/
MinHeapFixDown(A,i,n){
//找到左右孩子
left=2*i+1;
right=2*i+2;
//左孩子已經越界,i就是葉子節點
if(left>=n){
return;
}
min=left;
if(right>=n){
min=left;
}
else{
if(A[right]<A[left]){
min=right;
}
}
//min指向了左右孩子中較小的那個
//如果A[i] 比兩個孩子都要小,不用調整
if(A[i]<=A[min]){
return;
}
//否則,找到兩個孩子中較小的,和i交換
temp=A[i];
A[i]=A[min];
A[min]=temp;
//小孩子那個位置的值發生了變化,i變更為小孩子那個位置,遞調整
MinHeapFixDown(A,min,n);
}
//sort函式:
sort(A){
//先對A進行堆化
MakeMinHeap(A);
for(int x=n-1;x>=0;x--)
//把堆頂,0號元素和最後一個元素對調
swap(A,0,x);
//縮小堆的範圍,對堆頂元素進行向下調整
MinHeapFixDown(A,0,x-1);
}
程式碼:
#include<iostream>
using namespace std;
/**
*思路:首先要知道大頂堆和小頂堆,陣列就是一個堆,每個i節點的左右孩子是2i+1和2i+2
* 有了堆,將其堆化:從n/2-1個元素開始向下修復,將每個節點修復為小(大)頂堆
* 修復完成後,陣列具有小(大)頂堆的性質
* 按序輸出:小頂堆可以對陣列逆序排列,每次交換堆頂和末尾元素,對棧頂進行向下修復
*
*時間複雜度:堆化:一半的元素修復,修復是單分支的,所以整體堆化為nlgn。(PS:常數因子較大)
*排序:n個元素都要取出,因此調整為n次,每次調整修復同上是lgn的,整體為nlgn
*空間複雜度:不需要開闢輔助空間
*原址排序
* 穩定性:不穩定
*/
void MinHeapFixDown(int A[],int i,int n);
void makeMinHeap(int A[],int length){
int n=length;
for(int i=n/2-1;i>=0;i--){
MinHeapFixDown(A,i,n);
}
}
//向下調整函式
void MinHeapFixDown(int A[],int i,int n){
//找到左右孩子
int left=2*i+1;
int right=2*i+2;
//左孩子已經越界,i就是葉子節點
if(left>=n){
return;
}
int min=left;
if(right>=n){
min=left;
}
else{
if(A[right]<A[left]){
min=right;
}
}
//min指向了左右孩子中較小的那個
//如果A[i]比兩個孩子都要小,不用調整
if(A[i]<A[min]){
return;
}
//否則,找到兩個孩子中較小的,和i交換
int temp=A[i];
A[i]=A[min];
A[min]=temp;
//小孩子那個位置的值發生了變化,i變更為小孩子的那個位置,遞迴調整
MinHeapFixDown(A,min,n);
}
//排序函式
void sort(int A[],int length){
//先對A進行堆化
makeMinHeap(A,length);
for(int x=length-1;x>=0;x--){
//把堆頂,0號元素和最後一個元素對調
swap(A[0],A[x]);
//縮小堆的範圍,對堆頂元素進行向下調整
MinHeapFixDown(A,0,x);
}
}
int main(){
int arr[]={6,2,5,8,2,1,9,5,6};
int len= 9;
sort(arr,len);
for(int i=0;i<len;i++){
cout<<arr[i]<<" ";
}
return 0;
}
結果:
相關文章
- 看懂堆排序——堆與堆排序(三)排序
- 堆與堆排序(一)排序
- 堆操作與堆排序排序
- 第三章:查詢與排序(下)----------- 3.15基礎學習_樹、二叉樹、堆排序排序二叉樹
- 第三章:查詢與排序(下)----------- 3.20桶排序排序
- 第三章:查詢與排序(下)----------- 3.21基數排序排序
- 第三章:查詢與排序(下)----------- 3.19 計數排序排序
- 線性建堆法與堆排序排序
- 大根堆和堆排序的原理與實現排序
- 與堆和堆排序相關的問題排序
- 堆的基本操作及堆排序排序
- 第三章:查詢與排序(下)----------- 3.28 特殊排序(利用sort函式)排序函式
- PHP 實現堆, 堆排序以及索引堆PHP排序索引
- PHP面試:說下什麼是堆和堆排序?PHP面試排序
- 第三章:查詢與排序(下)----------- 3.14 逆序對個數排序
- 二叉堆及堆排序排序
- 《排序演算法》——堆排序(大頂堆,小頂堆,Java)排序演算法Java
- 第三章:查詢與排序(下)----------- 3.25 知其然知其所以然:小頂堆與topK的具體程式碼實現排序TopK
- 堆和堆的應用:堆排序和優先佇列排序佇列
- 第三章 :查詢與排序-------3.2你需要掌握的快速排序演算法排序演算法
- 第三章:查詢與排序(下)----------- 3.22 總結:10種排序演算法的對比分析排序演算法
- 第三章:查詢與排序(下)----------- 3.23 相關題解:排序陣列中找和的因子排序陣列
- 堆、堆排序和優先佇列的那些事排序佇列
- 第三章:查詢與排序(下)----------- 3.29 題解:判斷陣列的包含問題排序陣列
- 第三章:查詢與排序(下)----------- 3.27 用計數排序解決員工年齡問題排序
- 查詢與排序02,折半查詢排序
- 第三章:查詢與排序(下)----------- 3.12 實踐_最小可用id是多少排序
- 第三章 :查詢與排序-------3.7分治模式的完美詮釋_歸併排序排序模式
- 第三章:查詢與排序(下)----------- 3.11 趣味擴充_尋找發帖水王排序
- 白話經典演算法系列之七 堆與堆排序演算法排序
- 高階資料結構---堆樹和堆排序資料結構排序
- 查詢與排序05,氣泡排序排序
- 查詢與排序04,插入排序排序
- 查詢與排序03,選擇排序排序
- 第三章 :查詢與排序(下)-------3.1分治法介紹及關鍵點解析排序
- 第二章 :查詢與排序---------遞迴、查詢與排序補充排序遞迴
- 第三章 :查詢與排序-------3.6快排在工程實踐中的優化排序優化
- 第三章:查詢與排序(下)----------- 3.9 最快效率求出亂序陣列中第k小的數排序陣列