C語言實現(xiàn)大頂堆的示例代碼
堆的實現(xiàn)
1.堆結(jié)構(gòu)
邏輯結(jié)構(gòu)上類似于 一棵 “樹”
2.堆的種類
大頂堆結(jié)構(gòu): 一種特殊的樹:其每個子節(jié)點均比母節(jié)點要小
小頂堆結(jié)構(gòu): 同理:其每個子節(jié)點均比母節(jié)點要大
結(jié)構(gòu)圖示:
3.大頂堆代碼實現(xiàn)
這里實現(xiàn)堆 用循序表的方式
①初始化:
typedef int Heaptype; typedef struct Heap { Heaptype* head; int size; //記錄堆總?cè)萘? int capacity; //記錄當前數(shù)據(jù)總個數(shù) }Heap; //堆的初始化 void Heap_Init(Heap* pphead) { assert(pphead); pphead->head = NULL; pphead->size = 0; pphead->capacity = 0; }
②插入數(shù)據(jù):
實現(xiàn)細節(jié):數(shù)據(jù)在插入的同時,要進行數(shù)據(jù)結(jié)構(gòu)的調(diào)整,使樹頂始終保持最大數(shù)
如果新插入節(jié)點比母節(jié)點大的話,要進行交換 ,因此將這個調(diào)整結(jié)構(gòu)的環(huán)節(jié)獨立出來
即:“向上調(diào)整”。
向上調(diào)整:因為插入數(shù)據(jù)時:新數(shù)據(jù)默認儲存在順序表尾,因此其邏輯上是在堆的底部,
所以,當新數(shù)據(jù)比母節(jié)點大時,它將與邏輯上處于其上方的母節(jié)點交換,稱為
向上調(diào)整。
注:向上調(diào)整有時不止調(diào)整一次 ,還有可能調(diào)整多次,直到每個節(jié)點都在其相應(yīng)位置 。
流程圖解:
大頂堆插入流程
細節(jié)點:因為數(shù)據(jù)是以順序表的方式儲存,所以子節(jié)點的下標與母節(jié)點的下標符合
公式:parent = (child - 1)/2 ;(按照此公式帶入計算就理解了)
//向上調(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]));//進行交換 child = parent; parent = (child - 1) / 2; } } //插入數(shù)據(jù) void Heap_push(Heap* pphead, Heaptype data) { assert(pphead); //判斷是否滿容量并擴容 Heap_realloc(pphead); pphead->head[pphead->capacity] = data; //向上調(diào)整 adjust_up(pphead); pphead->capacity++; }
③刪除數(shù)據(jù):為了避免因為直接刪除頭部數(shù)據(jù)導(dǎo)致整個堆的結(jié)構(gòu)打亂,
這里先將頭部數(shù)據(jù)與尾數(shù)據(jù)交換,然后將尾部數(shù)據(jù)刪除,接著使用“向下調(diào)整”,即:將換上來的頂部數(shù)據(jù)向下與其子節(jié)點比較調(diào)整,直至符合大頂堆結(jié)構(gòu)為止。
注:1.大頂堆向下調(diào)整時,母節(jié)點要與兩個子節(jié)點中較大的一個交換 ,因此要比較一下。
2.這里下標的計算公式為:左孩子:child = (parent * 2) + 1
右孩子:child = (parent * 2) + 2
3.計算孩子下標時要避免越界,避免將母節(jié)點與不屬于堆中的數(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) { //默認用左孩紙與母節(jié)點比較,如果右孩紙比左孩紙大且不越界則交換 if (a[child] > a[child + 1] && child + 1 <= size) child = child + 1; //比較孩紙和母節(jié)點 if (a[child] < a[parent]) { int temp = a[child]; a[child] = a[parent]; a[parent] = temp; } //向下繼續(xù)比較 parent = child; } }
④擴容 || 判空 || 取頂數(shù)據(jù) || 銷毀堆
//判斷是否擴容 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語言實現(xiàn)大頂堆的示例代碼的詳細內(nèi)容,更多關(guān)于C語言大頂堆的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
C++ WideCharToMultiByte()函數(shù)案例詳解
這篇文章主要介紹了C++ WideCharToMultiByte()函數(shù)案例詳解,本篇文章通過簡要的案例,講解了該項技術(shù)的了解與使用,以下就是詳細內(nèi)容,需要的朋友可以參考下2021-08-08解析c中stdout與stderr容易忽視的一些細節(jié)
本篇文章是對在c語言中stdout與stderr容易忽視的一些細節(jié)進行了詳細的分析介紹,需要的朋友參考下2013-05-05VSCode與Keil聯(lián)合開發(fā)STM32的流程
這篇文章主要介紹了VSCode與Keil聯(lián)合開發(fā)STM32的流程,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-02-02