最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

完整B樹算法Java實現(xiàn)代碼

 更新時間:2016年09月14日 16:43:48   作者:tclxspy  
這篇文章主要為大家詳細介紹了完整的B樹算法Java實現(xiàn)代碼,具有一定的參考價值,感興趣的小伙伴們可以參考一下

定義

在計算機科學(xué)中,B樹(英語:B-tree)是一種自平衡的樹,能夠保持數(shù)據(jù)有序。這種數(shù)據(jù)結(jié)構(gòu)能夠讓查找數(shù)據(jù)、順序訪問、插入數(shù)據(jù)及刪除的動作,都在對數(shù)時間內(nèi)完成。

為什么要引入B樹?

首先,包括前面我們介紹的紅黑樹是將輸入存入內(nèi)存的一種內(nèi)部查找樹。

而B樹是前面平衡樹算法的擴展,它支持保存在磁盤或者網(wǎng)絡(luò)上的符號表進行外部查找,這些文件可能比我們以前考慮的輸入要大的多(難以存入內(nèi)存)。

既然內(nèi)容保存在磁盤中,那么自然會因為樹的深度過大而造成磁盤I/O讀寫過于頻繁(磁盤讀寫速率是有限制的),進而導(dǎo)致查詢效率低下。

那么降低樹的深度自然很重要了。因此,我們引入了B樹,多路查找樹。

特點

樹中每個結(jié)點最多含有m個孩子(m>=2);

除根結(jié)點和葉子結(jié)點外,其它每個結(jié)點至少有[ceil(m / 2)]個孩子(其中ceil(x)是一個取上限的函數(shù));

若根結(jié)點不是葉子結(jié)點,則至少有2個孩子(特殊情況:沒有孩子的根結(jié)點,即根結(jié)點為葉子結(jié)點,整棵樹只有一個根節(jié)點);

所有葉子結(jié)點都出現(xiàn)在同一層(最底層),葉子結(jié)點為外部結(jié)點,保存內(nèi)容,即key和value

其他結(jié)點為內(nèi)部結(jié)點,保存索引,即key和next。

內(nèi)部結(jié)點的關(guān)鍵字key:K[1], K[2], …, K[M-1];且K[i] < K[i+1];

內(nèi)容結(jié)點的指針next:P[1], P[2], …, P[M];其中P[1]指向關(guān)鍵字小于K[1]的子樹,P[M]指向關(guān)鍵字大于K[M-1]的子樹,其它P[i]指向關(guān)鍵字屬于(K[i-1], K[i])的子樹;

例如:(M=3)

查找和插入

為了方便這里用了一個特殊的哨兵鍵,它小于其他所有鍵,用*表示。

一開始B樹只含有一個根結(jié)點,而根結(jié)點在初始化時僅含有該哨兵鍵。

內(nèi)部結(jié)點中的每個鍵都與一個結(jié)點相關(guān)聯(lián),以此結(jié)點為根的子樹種,所有的鍵都大于等于與此結(jié)點關(guān)聯(lián)的鍵,但小于其他所有鍵。

這些約定在很大程度上能夠簡化代碼。

代碼

點擊下載。

該代碼實現(xiàn)引入了哨兵鍵,代碼輸出則剔除了它。

代碼里含有哨兵鍵的B樹(將圖片保存到本地查看,字會清晰些):

代碼輸出的B樹(將圖片保存到本地查看,字會清晰些):

public class BTree<Key extends Comparable<Key>, Value> 
{
  // max children per B-tree node = M-1
  // (must be even and greater than 2)
  private static final int M = 4;

  private Node root;    // root of the B-tree
  private int height;   // height of the B-tree
  private int n;      // number of key-value pairs in the B-tree

  // helper B-tree node data type
  private static final class Node 
  {
    private int m;               // number of children
    private Entry[] children = new Entry[M];  // the array of children

    // create a node with k children
    private Node(int k) 
    {
      m = k;
    }
  }

  // internal nodes: only use key and next
  // external nodes: only use key and value
  private static class Entry 
  {
    private Comparable key;
    private Object val;
    private Node next;   // helper field to iterate over array entries
    public Entry(Comparable key, Object val, Node next) 
    {
      this.key = key;
      this.val = val;
      this.next = next;
    }
  }

  /**
   * Initializes an empty B-tree.
   */
  public BTree() 
  {
    root = new Node(0);
  }

  /**
   * Returns true if this symbol table is empty.
   * @return {@code true} if this symbol table is empty; {@code false} otherwise
   */
  public boolean isEmpty() 
  {
    return size() == 0;
  }

  /**
   * Returns the number of key-value pairs in this symbol table.
   * @return the number of key-value pairs in this symbol table
   */
  public int size() 
  {
    return n;
  }

  /**
   * Returns the height of this B-tree (for debugging).
   *
   * @return the height of this B-tree
   */
  public int height() 
  {
    return height;
  }


  /**
   * Returns the value associated with the given key.
   *
   * @param key the key
   * @return the value associated with the given key if the key is in the symbol table
   *     and {@code null} if the key is not in the symbol table
   * @throws NullPointerException if {@code key} is {@code null}
   */
  public Value get(Key key) 
  {
    if (key == null) 
    {
      throw new NullPointerException("key must not be null");
    }
    return search(root, key, height);
  }

  @SuppressWarnings("unchecked")
  private Value search(Node x, Key key, int ht) 
  {
    Entry[] children = x.children;

    // external node到最底層葉子結(jié)點,遍歷
    if (ht == 0) 
    {
      for (int j = 0; j < x.m; j++)       
      {
        if (eq(key, children[j].key)) 
        {
          return (Value) children[j].val;
        }
      }
    }

    // internal node遞歸查找next地址
    else 
    {
      for (int j = 0; j < x.m; j++) 
      {
        if (j+1 == x.m || less(key, children[j+1].key))
        {
          return search(children[j].next, key, ht-1);
        }
      }
    }
    return null;
  }


  /**
   * Inserts the key-value pair into the symbol table, overwriting the old value
   * with the new value if the key is already in the symbol table.
   * If the value is {@code null}, this effectively deletes the key from the symbol table.
   *
   * @param key the key
   * @param val the value
   * @throws NullPointerException if {@code key} is {@code null}
   */
  public void put(Key key, Value val) 
  {
    if (key == null) 
    {
      throw new NullPointerException("key must not be null");
    }
    Node u = insert(root, key, val, height); //分裂后生成的右結(jié)點
    n++;
    if (u == null) 
    {
      return;
    }

    // need to split root重組root
    Node t = new Node(2);
    t.children[0] = new Entry(root.children[0].key, null, root);
    t.children[1] = new Entry(u.children[0].key, null, u);
    root = t;
    height++;
  }

  private Node insert(Node h, Key key, Value val, int ht) 
  {
    int j;
    Entry t = new Entry(key, val, null);

    // external node外部結(jié)點,也是葉子結(jié)點,在樹的最底層,存的是內(nèi)容value
    if (ht == 0) 
    {
      for (j = 0; j < h.m; j++) 
      {
        if (less(key, h.children[j].key)) 
        {
          break;
        }
      }
    }

    // internal node內(nèi)部結(jié)點,存的是next地址
    else 
    {
      for (j = 0; j < h.m; j++) 
      {
        if ((j+1 == h.m) || less(key, h.children[j+1].key)) 
        {
          Node u = insert(h.children[j++].next, key, val, ht-1);
          if (u == null) 
          {
            return null;
          }
          t.key = u.children[0].key;
          t.next = u;
          break;
        }
      }
    }

    for (int i = h.m; i > j; i--)
    {
      h.children[i] = h.children[i-1];
    }
    h.children[j] = t;
    h.m++;
    if (h.m < M) 
    {
      return null;
    }
    else     
    {  //分裂結(jié)點
      return split(h);
    }
  }

  // split node in half
  private Node split(Node h) 
  {
    Node t = new Node(M/2);
    h.m = M/2;
    for (int j = 0; j < M/2; j++)
    {
      t.children[j] = h.children[M/2+j];     
    }
    return t;  
  }

  /**
   * Returns a string representation of this B-tree (for debugging).
   *
   * @return a string representation of this B-tree.
   */
  public String toString() 
  {
    return toString(root, height, "") + "\n";
  }

  private String toString(Node h, int ht, String indent) 
  {
    StringBuilder s = new StringBuilder();
    Entry[] children = h.children;

    if (ht == 0) 
    {
      for (int j = 0; j < h.m; j++) 
      {
        s.append(indent + children[j].key + " " + children[j].val + "\n");
      }
    }
    else 
    {
      for (int j = 0; j < h.m; j++) 
      {
        if (j > 0) 
        {
          s.append(indent + "(" + children[j].key + ")\n");
        }
        s.append(toString(children[j].next, ht-1, indent + "   "));
      }
    }
    return s.toString();
  }


  // comparison functions - make Comparable instead of Key to avoid casts
  private boolean less(Comparable k1, Comparable k2) 
  {
    return k1.compareTo(k2) < 0;
  }

  private boolean eq(Comparable k1, Comparable k2) 
  {
    return k1.compareTo(k2) == 0;
  }


  /**
   * Unit tests the {@code BTree} data type.
   *
   * @param args the command-line arguments
   */
  public static void main(String[] args) 
  {
    BTree<String, String> st = new BTree<String, String>();

    st.put("www.cs.princeton.edu", "128.112.136.12");
    st.put("www.cs.princeton.edu", "128.112.136.11");
    st.put("www.princeton.edu",  "128.112.128.15");
    st.put("www.yale.edu",     "130.132.143.21");
    st.put("www.simpsons.com",   "209.052.165.60");
    st.put("www.apple.com",    "17.112.152.32");
    st.put("www.amazon.com",    "207.171.182.16");
    st.put("www.ebay.com",     "66.135.192.87");
    st.put("www.cnn.com",     "64.236.16.20");
    st.put("www.google.com",    "216.239.41.99");
    st.put("www.nytimes.com",   "199.239.136.200");
    st.put("www.microsoft.com",  "207.126.99.140");
    st.put("www.dell.com",     "143.166.224.230");
    st.put("www.slashdot.org",   "66.35.250.151");
    st.put("www.espn.com",     "199.181.135.201");
    st.put("www.weather.com",   "63.111.66.11");
    st.put("www.yahoo.com",    "216.109.118.65");


    System.out.println("cs.princeton.edu: " + st.get("www.cs.princeton.edu"));
    System.out.println("hardvardsucks.com: " + st.get("www.harvardsucks.com"));
    System.out.println("simpsons.com:   " + st.get("www.simpsons.com"));
    System.out.println("apple.com:     " + st.get("www.apple.com"));
    System.out.println("ebay.com:     " + st.get("www.ebay.com"));
    System.out.println("dell.com:     " + st.get("www.dell.com"));
    System.out.println();

    System.out.println("size:  " + st.size());
    System.out.println("height: " + st.height());
    System.out.println(st);
    System.out.println();
  }
}

輸出:
cs.princeton.edu:  128.112.136.12
hardvardsucks.com: null
simpsons.com:      209.052.165.60
apple.com:         17.112.152.32
ebay.com:          66.135.192.87
dell.com:          143.166.224.230

size:    17
height:  2
          www.amazon.com 207.171.182.16
          www.apple.com 17.112.152.32
          www.cnn.com 64.236.16.20
     (www.cs.princeton.edu)
          www.cs.princeton.edu 128.112.136.12
          www.cs.princeton.edu 128.112.136.11
          www.dell.com 143.166.224.230
(www.ebay.com)
          www.ebay.com 66.135.192.87
          www.espn.com 199.181.135.201
          www.google.com 216.239.41.99
     (www.microsoft.com)
          www.microsoft.com 207.126.99.140
          www.nytimes.com 199.239.136.200
(www.princeton.edu)
          www.princeton.edu 128.112.128.15
          www.simpsons.com 209.052.165.60
     (www.slashdot.org)
          www.slashdot.org 66.35.250.151
          www.weather.com 63.111.66.11
     (www.yahoo.com)
          www.yahoo.com 216.109.118.65
          www.yale.edu 130.132.143.21

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • Java 并發(fā)編程之線程掛起、恢復(fù)與終止

    Java 并發(fā)編程之線程掛起、恢復(fù)與終止

    這篇文章主要介紹了Java 并發(fā)編程之線程掛起、恢復(fù)與終止的相關(guān)資料,需要的朋友可以參考下
    2017-05-05
  • Intellij IDEA全局替換快捷鍵整理

    Intellij IDEA全局替換快捷鍵整理

    這篇文章主要給大家介紹了關(guān)于Intellij IDEA全局替換快捷鍵整理的相關(guān)資料,文中通過圖文介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-02-02
  • 基于SpringBoot bootstrap.yml配置未生效的解決

    基于SpringBoot bootstrap.yml配置未生效的解決

    這篇文章主要介紹了基于SpringBoot bootstrap.yml配置未生效的解決方式,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-10-10
  • Java中的JSONObject使用解讀

    Java中的JSONObject使用解讀

    本文詳細介紹了Java中處理JSON數(shù)據(jù)的JSONObject類,包括創(chuàng)建、基本操作、高級特性和錯誤處理,通過示例代碼和解釋,讀者可以掌握JSONObject的基本用法和處理技巧
    2025-01-01
  • Java類的繼承實例詳解(動力節(jié)點Java學(xué)院整理)

    Java類的繼承實例詳解(動力節(jié)點Java學(xué)院整理)

    在Java開發(fā)中,我們常常用到繼承這一概念,可以說繼承是Java這類面向?qū)ο缶幊陶Z言的基石,今天小編一起和大家一起學(xué)習(xí)java類的繼承
    2017-04-04
  • 使用JDBC工具類實現(xiàn)簡單的登錄管理系統(tǒng)

    使用JDBC工具類實現(xiàn)簡單的登錄管理系統(tǒng)

    這篇文章主要為大家詳細介紹了使用JDBC工具類實現(xiàn)簡單的登錄管理系統(tǒng),文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-02-02
  • java中繼承測試代碼分析

    java中繼承測試代碼分析

    這篇文章主要介紹了java中繼承測試代碼分析,具有一定借鑒價值,需要的朋友可以參考下。
    2017-12-12
  • JAVA JDK8 List獲取屬性列表

    JAVA JDK8 List獲取屬性列表

    今天小編就為大家分享一篇關(guān)于JAVA JDK8 List獲取屬性列表,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧
    2018-12-12
  • 關(guān)于PreparedStatement的setObject作用及說明

    關(guān)于PreparedStatement的setObject作用及說明

    這篇文章主要介紹了關(guān)于PreparedStatement的setObject作用及說明,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-03-03
  • Java 線程的優(yōu)先級(setPriority)案例詳解

    Java 線程的優(yōu)先級(setPriority)案例詳解

    這篇文章主要介紹了Java 線程的優(yōu)先級(setPriority)案例詳解,本篇文章通過簡要的案例,講解了該項技術(shù)的了解與使用,以下就是詳細內(nèi)容,需要的朋友可以參考下
    2021-08-08

最新評論

新绛县| 莱西市| 普格县| 祁东县| 江门市| 阜新| 绍兴市| 梅河口市| 灵武市| 永嘉县| 伊通| 东辽县| 东阳市| 德惠市| 宁陕县| 巴林右旗| 塔河县| 嘉定区| 镇远县| 濉溪县| 甘肃省| 介休市| 上犹县| 崇义县| 广水市| 墨竹工卡县| 津南区| 宁波市| 兴宁市| 乌恰县| 高雄市| 呼伦贝尔市| 贵南县| 湄潭县| 读书| 壶关县| 彰武县| 汶川县| 曲沃县| 射阳县| 高密市|