基于堆的基本操作的介紹
我們期望的數(shù)據(jù)結(jié)構(gòu)能支持插入操作,并能方便地從中取出具有最小或最大關(guān)鍵碼的記錄,這樣的數(shù)據(jù)結(jié)構(gòu)即為優(yōu)先級(jí)隊(duì)列。在優(yōu)先級(jí)隊(duì)列的各種實(shí)現(xiàn)中,堆是最高效的一種數(shù)據(jù)結(jié)構(gòu)。
最小堆:任一結(jié)點(diǎn)的關(guān)鍵碼均小于或等于它的左右子女的關(guān)鍵碼,位于堆頂?shù)慕Y(jié)點(diǎn)的關(guān)鍵碼是整個(gè)元素集合的最小的,所以稱它為最小堆。最大堆類似定義。
創(chuàng)建堆:采用從下向上逐步調(diào)整形成堆得方法來創(chuàng)建堆。為下面的分支結(jié)點(diǎn)調(diào)用下調(diào)算法siftDown,將以它們?yōu)楦淖訕湔{(diào)整為最小堆。從局部到整體,將最小堆逐步擴(kuò)大,直到將整個(gè)樹調(diào)整為最小堆。
插入一個(gè)元素:最小堆的插入算法調(diào)用了另一種堆得調(diào)整方法siftUp,實(shí)現(xiàn)自下而上的上滑調(diào)整。因?yàn)槊看涡陆Y(jié)點(diǎn)總是插在已經(jīng)建成的最小堆后面,這時(shí)必須遵守與sift相反的比較路徑,從下向上,與父結(jié)點(diǎn)的關(guān)鍵碼進(jìn)行比較,對(duì)調(diào)。
刪除一個(gè)元素:從最小堆刪除具有最小關(guān)鍵碼記錄的操作時(shí)將最小堆的堆頂元素,即其完全二叉樹的順序表示的第0號(hào)元素刪去,去把這個(gè)元素取走后,一般以堆得最后一個(gè)結(jié)點(diǎn)填補(bǔ)取走的堆頂元素,并將堆的實(shí)際元素個(gè)數(shù)減1.但是用最后一個(gè)元素取代堆頂元素將破壞堆,需要調(diào)用siftDown算法進(jìn)行調(diào)整堆。
本文代碼均以最小堆的實(shí)現(xiàn)為例。
#include<iostream>
#include<assert.h>
usingnamespace std;
constint maxheapsize=100;
staticint currentsize=0;
//從上到下調(diào)整堆
void siftDown(int* heap,int currentPos,int m)
{
int i=currentPos;
int j=currentPos*2+1;//i's leftChild
int temp=heap[i];
while(j<=m)
{
if(j<m&&heap[j]>heap[j+1]) j++;// j points to minChild
if(temp<=heap[j]) break;
else
{
heap[i]=heap[j];
i=j;
j=2*i+1;
}
}
heap[i]=temp;
}
//從下向上調(diào)整堆
void siftUp(int* heap, int start)
{
int i=start,j=(i-1)/2;
int temp=heap[i];
while(i>0)
{
if(heap[j]>temp)
{
heap[i]=heap[j];
i=j;
j=(i-1)/2;
}
elsebreak;
}
heap[i]=temp;
}
//構(gòu)建堆
int* Heap(int*arr, int size)
{
int i;
currentsize=size;
int* heap =newint[maxheapsize];
assert(heap!=NULL);
for(i=0;i<currentsize;i++) heap[i]=arr[i];
int currentPos=(currentsize-2)/2;
while(currentPos>=0)
{
siftDown(heap,currentPos,currentsize-1);
currentPos--;
}
return heap;
}
//增加一個(gè)元素
void insert(int* heap,int value)
{
if(currentsize>=maxheapsize)
{
cout<<"Heap is full!"<<endl;
return ;
}
heap[currentsize]=value;
siftUp(heap,currentsize);
currentsize++;
}
//刪除一個(gè)元素,并返回刪除前的堆頂元素
int removemin(int* heap)
{
assert(currentsize>=0);
int removeValue=heap[0];
heap[0]=heap[currentsize-1];
currentsize--;
siftDown(heap,0,currentsize-1);
return removeValue;
}
int main()
{
constint size=10;
int arr[size]={2,1,3,0,8,1,6,9,7,10};
int* heap=Heap(arr,size);
//堆排序
for(int i=0;i<size;i++)
{
arr[i]=removemin(heap);
cout<<arr[i]<<endl;
}
delete []heap;
return0;
}
相關(guān)文章
C語言中數(shù)組的一些基本知識(shí)小結(jié)
這篇文章主要介紹了C語言中數(shù)組的一些基本知識(shí)小結(jié),其中重點(diǎn)是對(duì)于數(shù)組的內(nèi)存分配相關(guān)方面的知識(shí)整理,需要的朋友可以參考下2016-04-04C++如何比較兩個(gè)字符串或string是否相等strcmp()和compare()
這篇文章主要介紹了C++如何比較兩個(gè)字符串或string是否相等strcmp()和compare()問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-11-11c++ rtti判斷基類指針指向的真實(shí)對(duì)象類型
這篇文章主要為大家介紹了c++ 判斷基類指針指向的真實(shí)對(duì)象類型示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-08-08求32位機(jī)器上unsigned int的最大值及int的最大值的解決方法
本篇文章是對(duì)求32位機(jī)器上unsigned int的最大值及int的最大值的解決方法進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下2013-05-05Qt編寫地圖實(shí)現(xiàn)閃爍點(diǎn)圖的示例代碼
閃爍點(diǎn)圖的核心有三個(gè)要素,城市的名稱、城市的經(jīng)緯度、對(duì)應(yīng)值的大小,當(dāng)值越大閃爍點(diǎn)也就越大,本文就來實(shí)現(xiàn)一下地圖閃爍點(diǎn)圖,具有一定的參考價(jià)值,感興趣的可以了解一下2021-12-12利用簡潔的C語言代碼解決跳臺(tái)階問題與約瑟夫環(huán)問題
這篇文章主要介紹了利用簡潔的C語言代碼解決跳臺(tái)階問題與約瑟夫環(huán)問題的方法,跳臺(tái)階問題與約瑟夫環(huán)問題是常見的基礎(chǔ)算法題目,需要的朋友可以參考下2016-02-02