C語言實(shí)現(xiàn)大頂堆的示例代碼
堆的實(shí)現(xiàn)
1.堆結(jié)構(gòu)
邏輯結(jié)構(gòu)上類似于 一棵 “樹”


2.堆的種類
大頂堆結(jié)構(gòu): 一種特殊的樹:其每個子節(jié)點(diǎn)均比母節(jié)點(diǎn)要小
小頂堆結(jié)構(gòu): 同理:其每個子節(jié)點(diǎn)均比母節(jié)點(diǎn)要大
結(jié)構(gòu)圖示:

3.大頂堆代碼實(shí)現(xiàn)
這里實(shí)現(xiàn)堆 用循序表的方式
①初始化:
typedef int Heaptype;
typedef struct Heap
{
Heaptype* head;
int size; //記錄堆總?cè)萘?
int capacity; //記錄當(dāng)前數(shù)據(jù)總個數(shù)
}Heap;
//堆的初始化
void Heap_Init(Heap* pphead)
{
assert(pphead);
pphead->head = NULL;
pphead->size = 0;
pphead->capacity = 0;
}
②插入數(shù)據(jù):
實(shí)現(xiàn)細(xì)節(jié):數(shù)據(jù)在插入的同時(shí),要進(jìn)行數(shù)據(jù)結(jié)構(gòu)的調(diào)整,使樹頂始終保持最大數(shù)
如果新插入節(jié)點(diǎn)比母節(jié)點(diǎn)大的話,要進(jìn)行交換 ,因此將這個調(diào)整結(jié)構(gòu)的環(huán)節(jié)獨(dú)立出來
即:“向上調(diào)整”。
向上調(diào)整:因?yàn)椴迦霐?shù)據(jù)時(shí):新數(shù)據(jù)默認(rèn)儲存在順序表尾,因此其邏輯上是在堆的底部,
所以,當(dāng)新數(shù)據(jù)比母節(jié)點(diǎn)大時(shí),它將與邏輯上處于其上方的母節(jié)點(diǎn)交換,稱為
向上調(diào)整。
注:向上調(diào)整有時(shí)不止調(diào)整一次 ,還有可能調(diào)整多次,直到每個節(jié)點(diǎn)都在其相應(yīng)位置 。
流程圖解:

大頂堆插入流程
細(xì)節(jié)點(diǎn):因?yàn)閿?shù)據(jù)是以順序表的方式儲存,所以子節(jié)點(diǎn)的下標(biāo)與母節(jié)點(diǎn)的下標(biāo)符合
公式:parent = (child - 1)/2 ;(按照此公式帶入計(jì)算就理解了)
//向上調(diào)整
void adjust_up(Heap* pphead)
{
int child = pphead->capacity;
int parent = (child - 1) / 2;
for (; pphead->head[parent] < pphead->head[child];)//判斷是否符合大頂堆
{
swap(&(pphead->head[parent]),&(pphead->head[child]));//進(jìn)行交換
child = parent;
parent = (child - 1) / 2;
}
}
//插入數(shù)據(jù)
void Heap_push(Heap* pphead, Heaptype data)
{
assert(pphead);
//判斷是否滿容量并擴(kuò)容
Heap_realloc(pphead);
pphead->head[pphead->capacity] = data;
//向上調(diào)整
adjust_up(pphead);
pphead->capacity++;
}
③刪除數(shù)據(jù):為了避免因?yàn)橹苯觿h除頭部數(shù)據(jù)導(dǎo)致整個堆的結(jié)構(gòu)打亂,
這里先將頭部數(shù)據(jù)與尾數(shù)據(jù)交換,然后將尾部數(shù)據(jù)刪除,接著使用“向下調(diào)整”,即:將換上來的頂部數(shù)據(jù)向下與其子節(jié)點(diǎn)比較調(diào)整,直至符合大頂堆結(jié)構(gòu)為止。
注:1.大頂堆向下調(diào)整時(shí),母節(jié)點(diǎn)要與兩個子節(jié)點(diǎn)中較大的一個交換 ,因此要比較一下。
2.這里下標(biāo)的計(jì)算公式為:左孩子:child = (parent * 2) + 1
右孩子:child = (parent * 2) + 2
3.計(jì)算孩子下標(biāo)時(shí)要避免越界,避免將母節(jié)點(diǎn)與不屬于堆中的數(shù)據(jù)比較。
//刪除數(shù)據(jù)
void Heap_pop(Heap* pphead)
{
assert(pphead);
assert(pphead->capacity > 0); //防止堆為空
//將頂部數(shù)據(jù)與尾部數(shù)據(jù)交換
swap(&(pphead->head[0]),&( pphead->head[pphead->capacity-1]));
pphead->capacity--;
//向下調(diào)整
adjust_down(pphead,0);
}
//向下調(diào)整
void Adjust_down(int* a, int size, int parent)
{
assert(a);
for (int child = parent * 2 + 1; child <= size; child = parent * 2 + 1)
{
//默認(rèn)用左孩紙與母節(jié)點(diǎn)比較,如果右孩紙比左孩紙大且不越界則交換
if (a[child] > a[child + 1] && child + 1 <= size)
child = child + 1;
//比較孩紙和母節(jié)點(diǎn)
if (a[child] < a[parent])
{
int temp = a[child];
a[child] = a[parent];
a[parent] = temp;
}
//向下繼續(xù)比較
parent = child;
}
}
④擴(kuò)容 || 判空 || 取頂數(shù)據(jù) || 銷毀堆
//判斷是否擴(kuò)容
void Heap_realloc(Heap* pphead)
{
assert(pphead);
if (pphead->size == pphead->capacity)
{
Heaptype Newsize = (pphead->size == 0) ? 4 : (pphead->size * 2);
Heaptype* Newhead = (Heaptype*)realloc(pphead->head,sizeof(Heaptype) * Newsize);
if (Newhead == NULL)
{
perror("realloc");
exit(-1);
}
pphead->head = Newhead;
pphead->size = Newsize;
}
}
//判斷堆是否為空
bool Heap_Empty(Heap* pphead)
{
if (pphead->capacity)
return false;
return true;
}
//取對頂數(shù)據(jù)
Heaptype Heap_top(Heap* pphead)
{
return pphead->head[0];
}
//銷毀堆
void Heap_Destory(Heap* pphead)
{
assert(pphead);
free(pphead->head);
pphead->head = NULL;
pphead->size = 0;
pphead->capacity = 0;
}以上就是C語言實(shí)現(xiàn)大頂堆的示例代碼的詳細(xì)內(nèi)容,更多關(guān)于C語言大頂堆的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
c語言根據(jù)用戶輸入的出生年份并計(jì)算出當(dāng)前年齡
這篇文章主要介紹了c語言根據(jù)用戶輸入的出生年份并計(jì)算出當(dāng)前年齡,需要的朋友可以參考下2023-03-03
Qt數(shù)據(jù)庫應(yīng)用之實(shí)現(xiàn)csv文件轉(zhuǎn)xls
這篇文章主要為大家詳細(xì)介紹了如何利用Qt實(shí)現(xiàn)csv文件轉(zhuǎn)xls功能,文中的示例代碼講解詳細(xì),對我們學(xué)習(xí)或工作有一定參考價(jià)值,需要的可以了解一下2022-06-06
vs2022?qt環(huán)境搭建調(diào)試的方法步驟
最近net6和vs2022發(fā)布,本文就詳細(xì)的介紹一下vs2022?qt環(huán)境搭建調(diào)試的方法步驟,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-12-12
C語言與java語言中關(guān)于二維數(shù)組的區(qū)別
這篇文章主要介紹了C語言與java語言中關(guān)于二維數(shù)組的區(qū)別,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-08-08
斐波那契數(shù)列 優(yōu)化矩陣求法實(shí)例
斐波那契數(shù)列 優(yōu)化矩陣求法實(shí)例,需要的朋友可以參考一下2013-03-03
PyQt5實(shí)現(xiàn)滑動開關(guān)的示例詳解
這篇文章主要為大家詳細(xì)介紹了如何使用PyQt5實(shí)現(xiàn)滑動開關(guān)的效果,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2024-12-12
C++右值引用與移動構(gòu)造函數(shù)基礎(chǔ)與應(yīng)用詳解
左值和右值都是針對表達(dá)式,左值是指表達(dá)式結(jié)束后依然存在的持久對象,右值是指表達(dá)式結(jié)束時(shí)就不再存在的臨時(shí)對象,下面這篇文章主要給大家介紹了關(guān)于C++11右值引用和移動語義的相關(guān)資料,需要的朋友可以參考下2023-02-02

