線段樹入門

ehz_nehc發表於2019-07-21

線段樹的入門級總結

線段樹是一種二叉搜尋樹,與區間樹相似,它將一個區間劃分成一些單元區間,每個單元區間對應線段樹中的一個葉結點。

對於線段樹中的每一個非葉子節點[a,b],它的左兒子表示的區間為[a,(a+b)/2],右兒子表示的區間為[(a+b)/2+1,b]。因此線段樹是平衡二叉樹,最後的子節點數目為N,即整個線段區間的長度。

使用線段樹可以快速的查詢某一個節點在若干條線段中出現的次數,時間複雜度為O(logN)。而未優化的空間複雜度為2N,因此有時需要離散化讓空間壓縮。—-來自百度百科

【以下以 求區間最大值為例】
先看宣告:

【建立線段樹(初始化)】:

由於線段樹是用二叉樹結構儲存的,而且是近乎完全二叉樹的,所以在這裡我使用了陣列來代替連結串列上圖中區間上面的紅色數字表示了結構體陣列中對應的下標。

在完全二叉樹中假如一個結點的序號(陣列下標)為 I ,那麼 (二叉樹基本關係)

I 的父親為 I/2,

I 的另一個兄弟為 I/2*2 或 I/2*2+1

I 的兩個孩子為 I*2 (左)   I*2+1(右)

有了這樣的關係之後,我們便能很方便的寫出建立線段樹的程式碼了。

【單點更新線段樹】:

由於我事先用 father[ ] 陣列儲存過 每單個結點 對應的下標了,因此我只需要知道第幾個點,就能知道這個點在結構體中的位置(即下標)了,這樣的話,根據之前已知的基本關係,就只需要直接一路更新上去即可。

【查詢區間最大值】:
將一段區間按照建立的線段樹從上往下一直拆開,直到存在有完全重合的區間停止。對照圖例建立的樹,假如查詢區間為 [2,5]

紅色的區間為完全重合的區間,因為在這個具體問題中我們只需要比較這 三個區間的值 找出 最大值 即可。