大根堆的删除c语言,二叉堆(一)之 C语言详解
本文介紹二叉堆,二叉堆就是通常我們所說的數(shù)據(jù)結(jié)構(gòu)"堆"中的一種。和以往一樣,本文會先對二叉堆的理論知識進行簡單介紹,然后給出C語言的實現(xiàn)。后續(xù)再分別給出C++和Java版本的實現(xiàn);實現(xiàn)的語言雖不同,但是原理如出一轍,選擇其中之一進行了解即可。若文章有錯誤或不足的地方,請不吝指出!
堆和二叉堆的介紹
1. 堆的定義
堆(heap),這里所說的堆是數(shù)據(jù)結(jié)構(gòu)中的堆,而不是內(nèi)存模型中的堆。堆通常是一個可以被看做一棵樹,它滿足下列性質(zhì):
[性質(zhì)一] 堆中某個節(jié)點的值總是不大于或不小于其父節(jié)點的值;
[性質(zhì)二] 堆總是一棵完全樹。
將根節(jié)點最大的堆叫做最大堆或大根堆,根節(jié)點最小的堆叫做最小堆或小根堆。常見的堆有二叉堆、左傾堆、斜堆、斐波那契堆等等。
2. 二叉堆的定義
二叉堆是完全二元樹或者是近似完全二元樹,它分為兩種:最大堆和最小堆。示意圖如下:
最大堆:父結(jié)點的鍵值總是大于或等于任何一個子節(jié)點的鍵值;
最小堆:父結(jié)點的鍵值總是小于或等于任何一個子節(jié)點的鍵值。
二叉堆一般都通過"數(shù)組"來實現(xiàn)。數(shù)組實現(xiàn)的二叉堆,父節(jié)點和子節(jié)點的位置存在一定的關(guān)系。有時候,我們將"二叉堆的第一個元素"放在數(shù)組索引0的位置,有時候放在1的位置。當(dāng)然,它們的本質(zhì)一樣(都是二叉堆),知識實現(xiàn)上稍微有一丁點區(qū)別。
假設(shè)"第一個元素"在數(shù)組中的索引為 0 的話,則父節(jié)點和子節(jié)點的位置關(guān)系如下:
(01) 索引為i的左孩子的索引是 (2*i+1);
(02) 索引為i的左孩子的索引是 (2*i+2);
(03) 索引為i的父結(jié)點的索引是 floor((i-1)/2)。
假設(shè)"第一個元素"在數(shù)組中的索引為 1 的話,則父節(jié)點和子節(jié)點的位置關(guān)系如下:
(01) 索引為i的左孩子的索引是 (2*i);
(02) 索引為i的左孩子的索引是 (2*i+1);
(03) 索引為i的父結(jié)點的索引是 floor(i/2)。
注意:本文二叉堆的實現(xiàn)統(tǒng)統(tǒng)都是采用"二叉堆第一個元素在數(shù)組索引為0"的方式!
二叉堆的圖文解析
在前面,我們已經(jīng)了解到:"最大堆"和"最小堆"是對稱關(guān)系。這也意味著,了解其中之一即可。本文是以"最大堆"來進行介紹的。
二叉堆的核心是"添加節(jié)點"和"刪除節(jié)點",理解這兩個算法,二叉堆也就基本掌握了。下面對它們進行介紹。
1. 添加
假設(shè)在最大堆[90,80,70,60,40,30,20,10,50]種添加85,需要執(zhí)行的步驟如下:
如上圖所示,當(dāng)向最大堆中添加數(shù)據(jù)時:先將數(shù)據(jù)加入到最大堆的最后,然后盡可能把這個元素往上挪,直到挪不動為止!
將85添加到[90,80,70,60,40,30,20,10,50]中后,最大堆變成了[90,85,70,60,80,30,20,10,50,40]。
最大堆的插入代碼
/*
* 將data插入到二叉堆中
*
* 返回值:
* 0,表示成功
* -1,表示失敗
*/
int maxheap_insert(int data)
{
// 如果"堆"已滿,則返回
if(m_size == m_capacity)
return -1;
m_heap[m_size] = data; // 將"數(shù)組"插在表尾
maxheap_filterup(m_size); // 向上調(diào)整堆
m_size++; // 堆的實際容量+1
return 0;
}
maxheap_insert(data)的作用:將數(shù)據(jù)data添加到最大堆中。當(dāng)堆已滿的時候,添加失敗;否則data添加到最大堆的末尾。然后通過上調(diào)算法重新調(diào)整數(shù)組,使之重新成為最大堆。
2. 刪除
假設(shè)從最大堆[90,85,70,60,80,30,20,10,50,40]中刪除90,需要執(zhí)行的步驟如下:
從[90,85,70,60,80,30,20,10,50,40]刪除90之后,最大堆變成了[85,80,70,60,40,30,20,10,50]。
如上圖所示,當(dāng)從最大堆中刪除數(shù)據(jù)時:先刪除該數(shù)據(jù),然后用最大堆中最后一個的元素插入這個空位;接著,把這個“空位”盡量往上挪,直到剩余的數(shù)據(jù)變成一個最大堆。
注意:考慮從最大堆[90,85,70,60,80,30,20,10,50,40]中刪除70,執(zhí)行的步驟不能單純的用它的字節(jié)點來替換;而必須考慮到"替換后的樹仍然要是最大堆"!
最大堆的刪除代碼
/*
* 刪除最大堆中的data
*
* 返回值:
* 0,成功
* -1,失敗
*/
int maxheap_remove(int data)
{
int index;
// 如果"堆"已空,則返回-1
if(m_size == 0)
return -1;
// 獲取data在數(shù)組中的索引
index = get_index(data);
if (index==-1)
return -1;
m_heap[index] = m_heap[--m_size]; // 用最后元素填補
maxheap_filterdown(index, m_size-1); // 從index位置開始自上向下調(diào)整為最大堆
return 0;
}
maxheap_remove(data)的作用:從最大堆中刪除數(shù)據(jù)data。
當(dāng)堆已經(jīng)為空的時候,刪除失敗;否則查處data在最大堆數(shù)組中的位置。找到之后,先用最后的元素來替換被刪除元素;然后通過下調(diào)算法重新調(diào)整數(shù)組,使之重新成為最大堆。
二叉堆的實現(xiàn)源碼和測試包括
二叉堆的源碼包含了"最大堆"和"最小堆"。
PS. 二叉堆是"堆排序"的理論基石。后面的算法中會講解到"堆排序",理解了"二叉堆"之后,"堆排序"就很簡單了。
總結(jié)
以上是生活随笔為你收集整理的大根堆的删除c语言,二叉堆(一)之 C语言详解的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: c语言交错级数前10项和,怎么求一个交错
- 下一篇: 焕字开头的成语有哪些啊?