有關堆的知識

2021-09-26 07:01:53 字數 1962 閱讀 3977

堆分為最大堆和最小堆。最大堆定義:乙個二叉樹,每個節點的值大於其子節點。最小堆相反。

一般用陣列來表示堆,當然,用樹,鍊錶都可以,想怎麼來怎麼來。

陣列d,有n個節點,其中一些下標定義:

1)d[k]的子節點為d[2*k+1]和d[2*k+2],當然這裡的2*k+1和2*k+2都得小於n

2)最後乙個父節點的位置:d[n/2-1]

3)d[k]節點的父節點的位置d[(k-1)/2]

有了如上的座標索引,就能有定義一些堆的操作。下面的例子都以最大堆為例。

乙個陣列初始化為堆,需要分為從下至上,然後從上至下。

從下至上指的是,從最下面乙個父節點開始,遍歷節點到根節點。回顧最大堆的性質:每乙個節點,都比其子節點要大,也就是說,每一棵子樹的最大節點是根節點。那麼從最後一層開始,一直調整到最頂層,就保證了每棵子樹都是最大堆。

那如何調整某棵子樹?我們從上至下調整。

特殊的,我們先定義,如果一棵樹只含有乙個節點,那麼這棵樹也為最大堆。

我們假設當前節點為d[k]處在第i層,由於我們是從下至上遍歷的子樹,所以當前節點的左右子樹已經滿足最大堆的條件。

如果滿足d[k] > d[2*k+1]且d[k] > d[2*k+2],即可以保證d[k]為根節點的堆也是最大堆。

所以,我們取d[2*k+1]和d[2*k+2]的更大者,和d[k]交換,這樣就能保證上面的不等式。比如d[2*k+1] > d[2*k+2],那麼交換d[k]和d[2*k+1],然後令k = 2*k+1,也就是向下遞迴這個過程,直到遇到葉子節點位置。

**如下:

void top_down(vector&nums, int k)

}void buildheap(vector&nums)

}

建立好了堆,需要往堆裡插入資料,思路和構建堆是一樣的。在陣列末尾插入了乙個元素,也要想辦法把當前的陣列調整為最大堆。末尾插入元素後,最後乙個父節點構成的子樹就不一定是最大堆了,所以需要從最後乙個父節點開始進行調整。把新插入的元素一直往上和父節點交換位置,直到父節點大於新插入的值為止,這樣就能保證堆被調整為最大堆。

證明:假設新插入元素為d[n-1]。葉子節點就是最大堆。

假設新插入的元素替換到第k層的時候,由新插入的元素構成的子樹為最大堆。此時新插入的元素位置為d[m]

那麼到k-1層的時候,d[(m-1)/2]為d[m]的父節點,假設d[q]為d[m]的兄弟節點,那麼必然有d[(m-1)/2] > d[q]。

如果d[(m-1)/2] < d[m],交換d[m]和d[(m-1)/2],則d[(m-1)/2]根節點的子樹為最大堆。如果d[(m-1)/2] > d[m],不交換,則已經是最大堆。數學歸納法知得證。

**:

void heapinsert(vector&nums, int x)

}

刪除堆頂操作為:把堆頂元素和最後乙個元素互換,然後彈出最後乙個元素。再把當前堆調整為最大堆。

由於堆頂此時變成了最後乙個元素,不一定是最大值,所以從第乙個元素開始,進行從上到下的調整。

void heapdelete(vector&nums)
由於從堆中可以o(1)的時間找到最大值或者最小值,這個特性能夠解決很多問題。比如k個有序鍊錶的合併,排序演算法等等。

下面舉堆排序為例:

1)輸入乙個亂序陣列,先調整為堆

2)把堆頂彈出,相當於刪除堆頂,和陣列末尾元素交換,這時待處理的陣列長度減1

3)從第乙個元素進行top_down操作調整堆

4)迴圈2-3,待處理的子陣列長度為0時候,原陣列變為有序。

時間複雜度o(nlog(n))(每次調整堆o(logn),調整n次)

void fixdown(vector&nums, int k, int n)

}void buildheap(vector&nums)

}void heapsort(vector&nums)

}

vue有關的知識

1.vue開發時使用mounted獲取後台資料還是使用created 這個沒有明確的答案。一般寫在created 裡面就可以了,如果涉及到dom操作的話就需要放在mounted created 元件例項完成,dom還沒有渲染是觸發 mounted 頁面渲染完成之後,載入mounted 裡面的函式 2...

有關inode的知識

懷著對檔名是什麼編碼的好奇,從網上得知了乙個 inode 的概念。簡單來說,系統是用inode號來標識檔案的,對檔案的操作不一定是非要通過檔名,可以通過其inode號進行。關於inode的詳情可見此文 1.如何得知檔案a的inode號?ls i a 2.如何獲得檔案a的inode詳細資訊?stat ...

血有關知識

1.血小板自動機採裝置為什麼在離心的時候採血管不轉動 採血管離心機主要是為血液分離而設計的 採血管離心機 採用直流無刷電機驅動,微電腦控制轉速和離心時間,鍵盤設定工作引數,高亮度 長壽命led數字顯示離心時間 轉速和離心力。該機採用提籃式試管介面卡,採血管離心機可與多種試管匹配,拿取方便。該機廣泛應...