相關鏈結
參考對於有一類問題,我們關心的是線段(或者區間):
最經典的線段樹問題:區間染色:
操作:
另一類經典問題:區間查詢:
實質:基於區間的統計查詢,區間中的資料是會動態更新的,日常中常見的場景:
如果我們使用陣列來解決該問題,時間複雜度為:
實際需求中,我們需要效能更好的實現;
使用線段樹實現,時間複雜度為:
線段樹解決的問題:
給定的區間的長度一般是固定的;
對於乙個線段樹,每乙個節點儲存的是乙個區間中相應的統計值
統計區間中資料的和為例:
線段樹(segment tree)是一種二叉樹形資料結構,1977 年由 jon louis bentley 發明,用以儲存區間或線段,並且允許快速查詢結構內包含某一點的所有區間。
乙個包含 n 個區間的線段樹,空間複雜度為 o(n),查詢的時間複雜度則為o(logn + k),其中 k 是符合條件的區間數量。
線段樹是乙個平衡的二叉樹,所有葉子到根的距離最多隻相差1。令整個區間的長度為n,則其有n個葉節點,每個葉節點代表乙個單位區間,每個內部結點代表的區間為其兩個兒子代表區間的聯集。
線段樹不是完全二叉樹;線段樹是平衡二叉樹;堆也是平衡二叉樹。
建立線段樹:
線段樹儲存結構:
滿二叉樹的特性:
如果有n個元素的線段樹,使用陣列儲存所需的空間:
建立線段樹實現:
線段樹的查詢:
例:在以treeindex為根的線段樹中,在其區間為[l…r]的範圍裡,搜尋區間[queryl…queryr]的值,如果:
查詢區間只在右子樹,只往右子樹查詢;
查詢區間只在左子樹,只往左子樹查詢;
查詢區間部分在左子樹、部分在右子樹,分別往左、右子樹查詢,並求和
線段樹更新乙個位置:
index所在節點在右子樹,更新右子樹;
index所在節點在左子樹,更新左子樹;
更新完孩子節點,返回值後更新父節點的值;
線段樹更新乙個區間:
懶惰更新:為提高效能,採用lazy陣列記錄未更新的內容,到下次查詢區間時,查詢到具體葉子節點時,先檢查lazy陣列中是否存在未更新的葉子節點,如果存在,同新更新葉子節點;
使用線段樹:
使用陣列實現線段樹
使用二叉樹實現線段樹
線段樹區間修改使用lazy優化
leetcode 303. range sum query - immutable
leetcode 307. range sum query - mutable
segmenttree
public int getsize() 獲取線段樹元素數量
public e get(int index) 獲取線段樹某一位置的元素
public e query(int queryl, int queryr) 返回區間[queryl, queryr]的值
public void set(int index, e e) 將index位置的值,更新為e
com.chen.data.struct.segment.segmenttree1
com.chen.data.struct.segment.segmenttree2
com.chen.data.struct.segment.segmenttree3
給定乙個整數陣列 nums,求出陣列從索引 i 到 j(i ≤ j)範圍內元素的總和,包含 i、j 兩點。
實現 numarray 類:
com.chen.data.struct.segment.leetcode303numarray
給你乙個陣列 nums ,請你完成兩類查詢,其中一類查詢要求更新陣列下標對應的值,另一類查詢要求返回陣列中某個範圍內元素的總和。
實現 numarray 類:
com.chen.data.struct.segment.leetcode307numarray
wiki 百科 : 線段樹 & 線段樹 (區間查詢)
劉宇波《玩轉資料結構》課程
資料結構之線段樹
線段樹也叫區間樹,顧名思義,線段樹是一種基於區間的樹,每個節點表示乙個 線段 或 區間 樹的根節點表示是 整體 的區間,左右子樹分別表示這個區間的左半邊和右半邊。function 以節點v為根建樹 v對應區間為 l,r 線段樹的關鍵在於如何定義樹節點,以及如果構建 插入 樹節點。1.樹節點的定義 p...
資料結構之線段樹
一 引例 有m個數排成一列,做n次操作,每次操作包括 1 詢問指定區間的最大值 最小值 2 將指定區間的每個數加上乙個值 如果按照最樸素的做法,乙個個的遍歷,時間複雜度 o mn 那麼如何解決乙個區間求和 最大值,最小值 的問題呢?那麼就要用到線段樹啦。二 定義 線段樹是一種二叉搜尋樹,與區間樹相似...
資料結構之線段樹
線段樹是一種二叉查詢樹,它將乙個區間劃分為1個個單元,樹的每個節點都是1個單元。如下圖的樹就是一顆區間樹。性質 對於線段樹中的每乙個非葉子節點 a,b 它的左節點為 a,a b 2 右節點為 a b 2 1,b 線段數是平衡二叉樹,子節點的個數等於整個區間的長度。建樹 在這裡,我們使用陣列來實現簡單...