數據結構與算法之美學習筆記:第四十八講


一、解決問題的前提是定義清楚問題

通過對一些模糊需求進行假設,來限定要解決問題的范圍

根據某個值查找數據,比如 select * from use where id=1234;
根據區間值來查詢某些數據比如 select * from use where id > 1234 and id < 2345

性能方面的需求,我們主要考察時間和空間兩方面,也就是執行效率和存儲空間

執行效率:我么你希望通過索引,查詢數據的效率盡可能的高;
存儲空間方面我們希望索引不需要消耗太多的內存空間

二、嘗試用學過的數據結構解決這個問題

支持快速查詢、插入等操作的動態數據結構,我們已經學過散列表、平衡二叉樹、跳表

這樣看來,跳表是可以解決這個問題,實際上,數據庫索引所用到的數據結構跟跳表非常相似,叫做B+樹
它是通過跳表演化雇來的,而非跳表

三、改造二叉查找樹來解決這個問題

1、實現代碼

/**
 * 這是 B+ 樹非葉子節點的定義。
 *
 * 假設 keywords=[3, 5, 8, 10]
 * 4 個鍵值將數據分為 5 個區間:(-INF,3), [3,5), [5,8), [8,10), [10,INF)
 * 5 個區間分別對應:children[0]...children[4]
 *
 * m 值是事先計算得到的,計算的依據是讓所有信息的大小正好等於頁的大小:
 * PAGE_SIZE = (m-1)*4[keywordss 大小]+m*8[children 大小]
 */
public class BPlusTreeNode {
  public static int m = 5; // 5 叉樹
  public int[] keywords = new int[m-1]; // 鍵值,用來划分數據區間
  public BPlusTreeNode[] children = new BPlusTreeNode[m];// 保存子節點指針
}

/**
 * 這是 B+ 樹中葉子節點的定義。
 *
 * B+ 樹中的葉子節點跟內部結點是不一樣的,
 * 葉子節點存儲的是值,而非區間。
 * 這個定義里,每個葉子節點存儲 3 個數據行的鍵值及地址信息。
 *
 * k 值是事先計算得到的,計算的依據是讓所有信息的大小正好等於頁的大小:
 * PAGE_SIZE = k*4[keyw.. 大小]+k*8[dataAd.. 大小]+8[prev 大小]+8[next 大小]
 */
public class BPlusTreeLeafNode {
  public static int k = 3;
  public int[] keywords = new int[k]; // 數據的鍵值
  public long[] dataAddress = new long[k]; // 數據地址

  public BPlusTreeLeafNode prev; // 這個結點在鏈表中的前驅結點
  public BPlusTreeLeafNode next; // 這個結點在鏈表中的后繼結點
}

2、實現步驟

3、實現思路

分裂合並

4、刪除操作的例子

四、總結引申

1、每個節點中子節點的個數不能超過m,也不能小於m/2
2、根節點的子節點個數不可超過m/2,這是一個例外
3、M叉樹只存儲索引,並不真正存儲數據,這個有點類似跳表
4、通過鏈表將葉子階段串聯在一次,這樣可以方便區間查詢
5、一般情況下,根節點會被存儲在內存中,其他節點存儲在磁盤中


免責聲明!

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



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