樹狀數組學習筆記


約定:C是樹狀數組,A是原數組,下面以索引 i 為示例進行講解
 
設計目的:解決區間查詢、前綴求和中數組每項之間強依賴、降低數組中每項和其它項的關聯,查詢和修改時間復雜度達到O(logN)。
 
方法:采用lowbit來達到稀疏目的(這個說法不知道是否准確)。
 
lowbit定義:索引數值按照二進制展開,末尾零的個數的2次冪,比如1100末尾有2個零,則lowbit=2^2=4,0011末尾有0個零,則lowbit=2^0=1,可以看出,奇數末尾都是0個零,所以奇數lowbit都是1
 
lowbit意義:表征數組每個元素所在的索引求和所管轄覆蓋的范圍,比如lowbit(4)=4,則表示第4個元素的數組元素C(4)=A(4)+A(3)+A(2)+A(1),即包含本身總共是4個元素的和。lowbit(6)=2,則表示第6個元素的數組元素C(6)=A(6)+A(5),即包含本身總共是2個元素的和。如下圖所示(竊取船長專利圖):
每個元素所管轄的范圍是lowbit(i),數組索引區間范圍:[i-(lowbit(i)-1)i],即從本身位置往前移動(lowbit(i)-1)個元素,為何要減1?因為要排除本身啊,包含本身元素才有lowbit(i)個,那本身前面不就是少1個了。
每個元素上面最近的管轄自己的元素索引是:i+lowbit(i),為什么?
 
當前索引i我們按照奇偶性進行分析:
 
a、i是奇數
根據上面lowbit的定義,i是奇數時下一個元素一定是偶數,而偶數的lowbit一定>=2,這就說明下一個元素一定覆蓋i元素,所以下一個元素就是i+1,而奇數時lowbit(奇數)=1,所以下一個元素的索引 j=i+lowbit(i)
 
b、i是偶數
由於i是偶數,說明i后面的元素一定是奇數,而奇數的lowbit為1,不可能覆蓋i元素,所以后移一位不可行,那么要后移幾位才可以覆蓋到本元素呢?
我們從下面的示意圖可以看出來,i元素要能夠被后面的元素覆蓋,那么管轄范圍的值就必須比i所在的管轄范圍值大,那大多少呢?從下圖可以看出,實際就是大一倍,也就是直接上一層,那么現在問題就變成距離i最近的上層索引怎么計算得到。
 
從下圖還可以看出,lowbit越大,管轄范圍越大,所處層次越高,所以i后面的元素要能夠覆蓋i,則后面元素的lowbit必須比i的lowbit大,而lowbit的值的大小和值后面的零的個數是2的冪次方的關系,所以要比當前i的lowbit大,要保證零的個數比lowbit(i)多,那滿足最小條件的個數就是比原來多1個零,而這個操作可以通過左移一位lowbit(i)得到,而這個操作的結果就是i+lowbit(i)。
 
如果對這個公式還不理解,那再換另一種思路:我們從i后面一個元素一個元素查找滿足覆蓋i元素的條件的元素,我們發現從 i+1 到 i+(lowbit(i)-1) 這個范圍的結果都不滿足新索引值的lowbit值比i的lowbit值大,一直到 i+lowbit(i),由於i的最右部分就是lowbit(i),所以i+lowbit(i)相當於最右部分兩個lowbit(i)相加,那么兩個最高位1相加就產生進位,這時新值的最右部分的零就比原來lowbit(i)多一個了,也就滿足了覆蓋i元素的新索引值的要求。
 
實際上i是奇數和偶數都可以很好的用上述方式解釋,只是奇數方式的原理更容易懂。
 
現在還有一個問題:我們按照這種方式查找會不會遺漏?
 
因為使用路徑 i->i+lowbit(i)->i+lowbit(i)+lowbit(i+lowbit(i)) 查找,這種方式是有索引跨度的,會不會發生i上層的某層元素被遺漏了的情況?其實這個是不會的,為什么?因為樹狀數組就是樹形結構的簡單體,層次關系和樹形結構一致,不會發生某個元素的父元素的父元素不是自己祖先的情況,也不會遺漏,因為我們從子節點查找所有的父節點都是一層一層往上查找,不會跳過任何父節點。
 
可以參照如下示例理解:

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM