關於堆的基本定義和操作的個人理解

2021-09-04 04:38:05 字數 1472 閱讀 3411

堆說白了也並不是什麼高大上的東西,其本質建立在完全二叉樹的基礎之上。對於堆來說,最主要的一點就是對於任何乙個子樹來說,其對應的根節點必大於該子樹的任何子節點。總而我們可以在堆的基礎上進行各種建堆和排序操作,例如堆排序。

堆的基本資料結構採用陣列來儲存,且為一維陣列,所有的操作都建立在一維陣列之上;

const int maxn=100;

int heap[maxn];

建立heap陣列;

對於進行初始建堆的時候,並不是進行有序建堆的。由於堆是乙個完全二叉樹,所以建堆的時候要根據層序遍歷來進行相應的建堆。建立堆完成之後,才會對該堆進行相應的調整;調整函式是對乙個節點和其直屬的左右子節點進行調整,從而使得三個節點有序。具體操作為:判斷根節點是否大於左節點,如果大於,則不動;如果小於,將左子節點和根節點進行置換,右子節點同理;

對於初始化建堆的調整,我們必須要從向上調整,原因為:如果從上至下進行堆調整的話,我們並不能保證調整上來的節點會大於底部節點。所以,我們通常會從葉子節點的父節點開始逐層向上調整,由於堆的基礎資料結構由陣列維護,再加上完全二叉樹的節點標號有序,可以很好的進行下標判定調整;

void downadjust(int low,int high)

if(heap[j]>heap[i])else

}}

這裡書上給出的downadjust函式可以按照給出的節點一直向下調整,本來不用必須向上遍歷。但是從底部向上遍歷可以減少時間複雜度。

所以建堆的時候會根據下標來建。對於完全二叉樹序列中的n個元素,葉子節點個數為[n/2],所以陣列下標[1,n/2]都是非葉子節點,所以從[n/2]開始向上開始遍歷;

void createheap()

}

對於刪除操作,我們的操作是直接直接把最後乙個元素覆蓋到第一位,然後從第乙個位置直接向下調整,但是長度n-1;

void deletetop()
對於新增操作,我們也可以將新元素新增在序列底部,之後直接向上進行調整;和downadjust函式類似,也是按照完全二叉樹的性質來進行向上的比較調整;對於upadjust函式來說,high引數是需要進行調整的新加入節點;

void upadjust(int low,int high)
堆排序就是根據堆的結構來進行排序操作,可以設定為遞增排序和遞減排序兩種,這裡介紹遞增排序;

主要的操作流程是這樣的:

由於正常的堆序列根節點總為最大的元素,所以先取首個元素,也就是從堆中刪除這個元素;

隨後將最後乙個元素替換至堆頂,之後再進行從堆頂元素向下的調整;

經過這些操作之後,就可以將heap序列完整的變成乙個遞增的序列,這個方法巧妙在無需其他陣列,通過不斷地減少索引,省去了不必要的空間;

最後重複這兩個步驟,直到堆中只有最後乙個元素。

void heapsort()

}

堆的定義與基本操作

堆是一顆完全二叉樹,樹中每個結點的值都不小於 或不大於 其左右孩子結點的值,其中,如果父親結點的值大於或等於孩子結點的值,那麼稱這樣的堆為大頂堆,這時每個結點的值都是以它為根結點的子樹的最大值 如果父親結點的值小於或等於孩子結點的值,那麼稱這樣的堆為小頂堆,這時每個節點的值都是以它為根結點的子樹的最...

關於Java nofity wait的個人理解

首先notify,wait的經典場景是生產者,消費者模型 importorg.slf4j.logger created by wcl on 17 9 17.public classconsumerimplementsrunnable public voidrun 消費 1,當前數量 name,con...

L2 012 關於堆的判斷 基本的堆操作

輸出樣例 ft ft就是字串處理很繁瑣別的還好。找到自己的父親的方式,先找到自己的位置,哪乙個i的heap i x,i 1對應的值就是父親的值 includeusing namespace std const int n 1000 5 int heap n 2 n void push int x c...