日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

数据结构与算法--B树原理及实现

發(fā)布時間:2023/12/4 编程问答 45 豆豆
生活随笔 收集整理的這篇文章主要介紹了 数据结构与算法--B树原理及实现 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

B樹

  • 前幾篇文中討論的數(shù)據(jù)結(jié)構(gòu)我們都是假設(shè)所有的數(shù)據(jù)都存儲在計算機的主存中。可說總要那么海量的數(shù)據(jù)需要通過個中數(shù)據(jù)結(jié)構(gòu)去存儲,我們不可能有這么多內(nèi)存區(qū)存放這些數(shù)據(jù)。那么意味著我們需要將他們放磁盤。所以這個時候范問時間復雜度O決定了他是否能適合存儲磁盤,大O模型不適用于磁盤存儲。游戲規(guī)則變了。

  • 在磁盤中操作速度和CPU內(nèi)存計算速度相差甚遠。

    • 例如一臺機器每秒可以執(zhí)行5億條指令。
    • 磁盤讀寫操作依賴磁盤的機械運動,磁盤轉(zhuǎn)動,磁針移動,也許磁盤7200RPM的轉(zhuǎn)速,1轉(zhuǎn)大約1/120秒,約8.3ms,我們就估算是8.3
    • 每秒大概120次磁盤訪問
    • 但是1分鐘7200轉(zhuǎn)比起每秒5億簡直不是一個量級,比值相當于 40W:1
    • 方法是盡量減少磁盤的操作,寧愿大量計算
    • 對于樹來說,一個節(jié)點存在幾個子節(jié)點,我們在內(nèi)存中通過指針尋址,但是在磁盤中需要機械運動尋址
案例
  • 我們通過一個案例來結(jié)束典型查找樹的執(zhí)行方式:
    • 假設(shè)要訪問廣東市所有人的出行記錄。假設(shè)只有1kw項數(shù)據(jù)。每個關(guān)鍵字32字節(jié)(是這個人的名字+唯一id),而一個記錄存儲這N個信息是256個字節(jié)。假設(shè)這些1kw數(shù)據(jù)不能都存儲進主內(nèi)存
    • 更具如上計算,我們
解決方法
  • 不平衡的二叉查找樹解決如上問題完全不可取,最壞情況他有線性深度,從而可能需要1kw次磁盤的范問。平均的話一次成功的查找也需要1.38logN次范圍,由于log10000000 =24 ,1.38*24 = 32/6 = 5秒。AVL樹多少要好一點,1.44logN是最壞情況,平均訪問是logN,擇優(yōu)AVL計算平均25次磁盤查詢一個數(shù)據(jù),4秒左右

  • 要減少磁盤范問次數(shù),比如減到3,4。我們需要更加復雜的程序。因為機器指令相對機械操作相當于不耗時。以上分析我們知道二叉樹不可行,減少樹層級增加節(jié)點分支的方式來解決。

  • 31個節(jié)點的完美二叉樹有5層,31個節(jié)點的5叉樹只有3層

  • 一個完全二叉樹的高度大概是log2N,而一顆完全M叉樹的高度大概是LogMN

  • 我們建立與二叉樹類似的M叉查找樹,二叉樹中我們需要一個key來決定走左樹還是右樹,M叉樹我們需要M-1個key來決定

  • 同時避免M叉樹退化成鏈表,我們需要給一個平衡條件,限制M叉樹退化到二叉樹,那就是B樹如下性質(zhì)

  • 階為M的B樹是一顆具有下列特性的樹:

    • 數(shù)據(jù)項存儲在葉子節(jié)點上
    • 非葉子節(jié)點存儲直到M-1個關(guān)鍵字用來指示搜索方向;關(guān)鍵字i代表子樹i+1中最小關(guān)鍵字
    • 數(shù)的根節(jié)點如果不是葉子節(jié)點,那么他子節(jié)點個數(shù)必須在2~M之間
    • 除了根節(jié)點外,所有非葉子節(jié)點的子節(jié)點個數(shù)必須在M/2~M個之間
    • 所有葉子節(jié)點都在相同的深度上,并且有L/2和L個數(shù)據(jù)項目,L個數(shù)之后確認
  • 如下圖5階B樹的案例,所有非葉子節(jié)點的兒子樹都在3~5之間(5/2 ~ 5 取整 3-5),那么他們有2-4個關(guān)鍵字;根可能只有2個子節(jié)點。這里我們L=5,所有葉子節(jié)點的數(shù)據(jù)項則是(5/2 ~5 取整 3-5 之間)

    • 要求節(jié)點半滿保證B樹不退化到簡單二叉樹
B樹結(jié)構(gòu)分析
  • 我們根據(jù)所存儲的項的大小選擇M與L的大小,還是上面的案例,我們假設(shè)一個區(qū)塊的磁盤大小是8192Byte,
  • 每個關(guān)鍵字32Byte,在一顆M階B數(shù)中,有M-1個關(guān)鍵字那么總數(shù)是32(M-1),再加上M個分支(指針int型4Byte),總數(shù)則為32(M-1)+4M = 36M-32
  • 那么一個片區(qū)8192可以存儲的最大節(jié)點數(shù)據(jù)是8192= (36M-32) , M = 228階,也就是我們每一層有228個分支
  • 以上案例中條件說一個記錄256Byte,8192/256 = 32 ,一個片區(qū)可以存儲32個記錄,我們選擇L=32,這樣一個子節(jié)點中所有數(shù)據(jù)可以在同一個片區(qū)(盡量一次磁盤操作可以讀完)
  • 這樣我們保證了每個葉子節(jié)點有16~32個數(shù)據(jù)記錄以及每個內(nèi)部節(jié)點至少有228/2 = 114 中分支方式
  • 那么1kw個數(shù)據(jù)最多存儲的葉子節(jié)點個數(shù) 10000000/16 = 625000 個葉子節(jié)點中
  • 層級最少情況,每一層都是滿分支(228),625000/228 = 224 /228 = 1,最少的情況第二次就是葉子節(jié)點
  • 層級最多情況,每一層都是半分支(228/2=114),625000/114 = 5482.4/114=48/1154 = 1 ,最多情況第四層是葉子節(jié)點
  • 如上分析,最壞情況訪問次數(shù)近似log(m/2)N給出
構(gòu)造B樹–添加節(jié)點,刪除節(jié)點
插入節(jié)點
  • 我們按照上面圖片中的案例,需要將57 插入到圖中的B樹,沿著樹向下查找他不在樹中,我們把它作為第五項數(shù)據(jù)添加到第對應(yīng)的葉子節(jié)點中如下圖:
方法一
  • 如上更新數(shù)據(jù)分為三步:
    • 第一遍歷B樹,找到插入數(shù)據(jù)的對應(yīng)位置
    • 讀取樹葉節(jié)點中數(shù)據(jù)并且重排樹葉節(jié)點中數(shù)據(jù)
    • 將重排的數(shù)據(jù)寫入樹葉節(jié)點
  • 與磁盤的操作相比,這些邏輯排列時間幾乎可以忽略不計,以上是簡單的模式,因為改樹葉節(jié)點并沒有被裝滿,現(xiàn)在我們在插入55 到上圖中。
    • 55要插入的那個葉子節(jié)點已經(jīng)滿,有L+1項數(shù)據(jù),我們需要將他分成兩個葉子節(jié)點,這兩葉子節(jié)點能保證所有需要的記錄的最小個數(shù),每一個葉子節(jié)點3個項(需要兩次磁盤范問)
    • 接著我們需要更新父節(jié)點,將最小的值添加到父節(jié)點中(需要一次寫入的磁盤操作),這種方式是更具上面L/2的規(guī)則執(zhí)行
    • 雖然分離節(jié)點是耗時的,至少需要2次磁盤操作,但是很少發(fā)生,比如我們上面L=32 時候每次節(jié)點分裂時候都有16 或者17 項數(shù)據(jù)的兩片葉子節(jié)點,那么我們需要之后的17次添加操作才會有一次分裂

  • 如上圖情況,當一個非葉子節(jié)點分裂,父節(jié)點得到一個新的子節(jié)點,父節(jié)點也需要增加一個項,如果父節(jié)點此時也達到分裂閥值,則需要繼續(xù)向上分裂直到達到根節(jié)點。如果分裂根就得到兩個根,這顯然不現(xiàn)實,我們則創(chuàng)建一個新根,這個根以分裂得到的兩個新根為子節(jié)點,所以我們的根節(jié)點的子節(jié)點的個數(shù)設(shè)置在2~M個是有這個原因的。
  • 這種方式也是B樹增加高度的唯一方式
方法二
  • 在相鄰節(jié)點有空間時候,將一個子節(jié)點交給鄰節(jié)點,例如將上圖中29 節(jié)點插入到B樹中,我們可以把32移到 下一片樹葉而騰出一個空間來,這種方法要求對父節(jié)點進行修改,因為這些關(guān)鍵字也會受影響,他趨向于是的節(jié)點達到滿節(jié)點,更加節(jié)省空間。
刪除節(jié)點
  • 通過查找到要刪除的項并在找到后刪除他來執(zhí)行刪除操作,問題在于,如果被刪元素的總元素個數(shù)已經(jīng)低于最小值(L/2),那么刪除后他的項目就不符合B樹的要求,我們可以通過在鄰節(jié)點借一個節(jié)點來矯正這種情況,如果鄰節(jié)點也達到最小值(L/2),那么我們就合并這兩個葉子節(jié)點結(jié)合成一個新的滿葉節(jié)點。
  • 這種操作意味著父節(jié)點是去一個兒子,如果失去兒子節(jié)點后又引發(fā)兒子節(jié)點數(shù)低于下限,我們繼續(xù)使用相同的策略,一直到根節(jié)點,如果這個過程使得根只剩下一個子節(jié)點,那么刪除這個根節(jié)點,讓原兒子節(jié)點當現(xiàn)在B樹的新根節(jié)點。
  • 這種方式是B樹降低高度的唯一方式。
  • 如下案例,我們還是依照上圖中的B數(shù),刪除99 項的節(jié)點,由于葉子節(jié)點只有兩個,而其鄰節(jié)點以及是最小值3 個了,因此,我們將這兩個葉子節(jié)點合并成有5項數(shù)據(jù)的一片新的葉子節(jié)點。結(jié)果他的父節(jié)點只有兩個子節(jié)點,此時父節(jié)點繼續(xù)上一個步驟,從鄰節(jié)點領(lǐng)養(yǎng),鄰節(jié)點有4個子節(jié)點,最終使用雙方都得到3個子節(jié)點,如下圖:

上一篇:數(shù)據(jù)結(jié)構(gòu)與算法–AVL樹原理及實現(xiàn)
下一篇:數(shù)據(jù)結(jié)構(gòu)與算法–圖論,最短路算法,拓撲排序算法

總結(jié)

以上是生活随笔為你收集整理的数据结构与算法--B树原理及实现的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。