二叉堆有兩種形式,分別為大根堆和小根堆。
大根堆有兩個性質:
1.根節點點權為所有節點點權中的最大值;
2.任意節點的點權都大於它的子節點.
同樣地,小根堆也具有兩個性質,並且與大根堆相反:
1.根節點點權為所有點權中的最小值;
2.任意節點的點權都小於它的子節點.
在此僅展示小根堆的實現方法,大根堆與其同理,稍作修改即可。
題目描述
如題,初始小根堆為空,我們需要支援以下3種操作:
操作1: 1 x 表示將x插入到堆中
操作2: 2 輸出該小根堆內的最小數
操作3: 3 刪除該小根堆內的最小數
輸入輸出格式
輸入格式:
第一行包含乙個整數n,表示操作的個數
接下來n行,每行包含1個或2個正整數,表示三種操作,格式如下:
操作1: 1 x
操作2: 2
操作3: 3
輸出格式:
包含若干行正整數,每行依次對應乙個操作2的結果。
輸入輸出樣例
輸入樣例#1:
5 1 2
1 5
2 3
2 輸出樣例#1:
2 5
說明
時空限制:1000ms,128m
資料規模:
對於30%的資料:n<=15
對於70%的資料:n<=10000
對於100%的資料:n<=1000000
思路
1.建立小根堆
首先,如圖所示,由於二叉堆的性質,左兒子的編號一定是其父節點編號的2倍,右兒子的編號一定是其父節點編號的2倍再加1,所以我們可以利用這個性質來建立乙個小根堆。
2.對於小根堆的維護
由於**和注釋都已經寫的很清楚了,這裡就不再詳述。
a.插入元素(insert)
由於小根堆的性質,我們要對新插入的元素位置進行調整,使插入後的堆仍為乙個小根堆。
b.刪除元素(del)
首先要記住乙個問題:c++中delete為固定的操作符(本身帶有),所以函式的命名不能用delete(delete大概是可以的)。
對於堆中最小值,即根節點的刪除操作,我們可以通過縮小堆的空間來實現。將根節點的值與堆中編號最大的值交換,再把堆的空間減1即可。但是還要注意的是,由於小根堆的性質,刪除前堆中編號最大的節點的值一定是大於原根節點中的子節點的,所以我們需要對其進行維護。
**實現
#include
#include
#include
#include
#include
#include
#include
using
namespace
std;
int n,m,y,ans,t;
int tree[2000003];
void change(int a,int b)
void insert(int x)
else f=1;//新節點大於根節點則不發生改變
x=x/2;//繼續查詢下乙個根節點(大概是爺爺節點吧(霧)是否小於該新節點,不是則繼續查詢,直到下乙個根節點值小於該新節點
}}void del(int x)//將tree[n]放在tree[1]不滿足小根堆的性質,所以要進行調整
if(tree[x]>tree[x*2+1]&&tree[x*2+1]2]&&x*2+1
<=t)
if(x!=d)
else f=1;
} }int main()
if(m==2)
if(m==3)
}return
0;}
Luogu P1334 瑞瑞的木板(手寫堆)
其實這個題完全不需要用手寫堆,只需要一遍遍sort就行了 但是!為了練習手寫堆,還是用手寫堆做了。在做本題之前,如果你沒有什麼思路的話,建議先做luogu的合併果子。好,假設你已經做過了合併果子了。那麼正式開始本題 ac include include include include include...
C 堆的實現
堆是乙個完全二叉樹。堆根據元素的排列方式,可以分為最大堆 max heap 和最小堆 min heap 其中 堆並不歸屬於stl庫容器元件,而是作為優先佇列 priority queue 的底層實現。堆是一種完全二叉樹,整棵二叉樹除了最底層的葉子節點之外是填滿的,而最底層的葉子節點由左至右是沒有空隙...
左傾堆的C 實現
在下小白乙個 如有錯誤請指正 上 using system 資料結構 namespace datastructure public leftistnoderightnode public t key public int npl public leftistnode leftistnodeleftn...