Every nod.e has at most m children.
Every non-leaf node (except root) has at least [m/2] children
The root has at least two children if it is not a leaf node.
A non-leaf node with k children contains k-1 keys.
All leaves appear in the same level, and internal vertices carry no information.
template
class BTreeNode{
public:
BTreeNode();
BTreeNode(const T&);
private:
bool leaf;
int keyTally;
T keys[M-1];
BTreeNode *pointers[M];
friend BTree;
}
Searching in a B-tree
BTreeNode *BTreeSearch(keyType K,BTreeNode *node){
if(node != 0){
for(i=1;ikeyTally && node->keys[i-1]node->node->keyTally||node->keys[i-1]>K)
return BTreeSearch(K,node->pointers[i-1]);
else
return node;
}
else
return 0;
}
Insertion in a B-tree
B树特点:所有叶子节点在B树的最后一层,所以插入和删除并不简单。
===》》树自底向上建立。》》根节点处于不断变化中(until 所有插入完全后才能确定)
3种插入情况
BTreeInsert(K)
找到一个叶节点node来插入k
while(true)
在数组keys中为k找到一个合适的位置;
if node 不满
插入K并递增keyTally;
return;
else
将node分解为node1(=node)与node2(新节点);
在node1和node2之间平均分配键值和指针,并正确地初始化他们的keyTally;
k=中间键值
if node 是根节点
穿件一个心的根节点,作为node1和node2的父节点
将K及指针node1和node2的指针妨碍根节点中,并将根节点的keyTally设为1;
return;
else
node = 其父节点。//处理父节点
BTreeDelete(K)
node = BTreeSearch(K,root)
if(node!=null)
if node 不是叶节点
寻找一个带有最接近K的后继S的叶节点;
把S赋值到K所在的node中;
node = 包含S的叶节点;
从node中删除S;
else 从node 中删除K
while(1)
if node没有下溢
return;
else if node 有同级节点,且同级节点有足够多的键值
在node和同级节点之间重新分配键值;
return;
else if node的父节点是根节点
if 父节点只有一个键值
合并node、它的同级节点以及父节点,形成一个心的根节点;
else
合并node和它的同级节点;
return;
else 合并node和它的同级节点;
node = 它的父节点;
/*************************************************************************
* Compilation: javac BTree.java
* Execution: java BTree
*
* B-tree.
*
* Limitations
* -----------
* - Assumes M is even and M >= 4
* - should b be an array of children or list (it would help with
* casting to make it a list)
*
*************************************************************************/
public class BTree, Value> {
private static final int M = 4; // max children per B-tree node = M-1
private Node root; // root of the B-tree
private int HT; // 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
private Node(int k) { m = k; } // create a node with k children
}
// internal nodes: only use key and next
// external nodes: only use key and value
private static class Entry {
private Comparable key;
private Object value;
private Node next; // helper field to iterate over array entries
public Entry(Comparable key, Object value, Node next) {
this.key = key;
this.value = value;
this.next = next;
}
}
// constructor
public BTree() { root = new Node(0); }
// return number of key-value pairs in the B-tree
public int size() { return N; }
// return height of B-tree
public int height() { return HT; }
// search for given key, return associated value; return null if no such key
public Value get(Key key) { return search(root, key, HT); }
private Value search(Node x, Key key, int ht) {
Entry[] children = x.children;
// external node
if (ht == 0) {
for (int j = 0; j < x.m; j++) {
if (eq(key, children[j].key)) return (Value) children[j].value;
}
}
// internal node
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;
}
// insert key-value pair
// add code to check for duplicate keys
public void put(Key key, Value value) {
Node u = insert(root, key, value, HT);
N++;
if (u == null) return;
// need to split 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;
HT++;
}
private Node insert(Node h, Key key, Value value, int ht) {
int j;
Entry t = new Entry(key, value, null);
// external node
if (ht == 0) {
for (j = 0; j < h.m; j++) {
if (less(key, h.children[j].key)) break;
}
}
// internal node
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, value, 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 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;
}
// for debugging
public String toString() {
return toString(root, HT, "") + "\n";
}
private String toString(Node h, int ht, String indent) {
String s = "";
Entry[] children = h.children;
if (ht == 0) {
for (int j = 0; j < h.m; j++) {
s += indent + children[j].key + " " + children[j].value + "\n";
}
}
else {
for (int j = 0; j < h.m; j++) {
if (j > 0) s += indent + "(" + children[j].key + ")\n";
s += toString(children[j].next, ht-1, indent + " ");
}
}
return s;
}
// 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;
}
/*************************************************************************
* test client
*************************************************************************/
public static void main(String[] args) {
BTree st = new BTree();
// 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");
StdOut.println("cs.princeton.edu: " + st.get("www.cs.princeton.edu"));
StdOut.println("hardvardsucks.com: " + st.get("www.harvardsucks.com"));
StdOut.println("simpsons.com: " + st.get("www.simpsons.com"));
StdOut.println("apple.com: " + st.get("www.apple.com"));
StdOut.println("ebay.com: " + st.get("www.ebay.com"));
StdOut.println("dell.com: " + st.get("www.dell.com"));
StdOut.println();
StdOut.println("size: " + st.size());
StdOut.println("height: " + st.height());
StdOut.println(st);
StdOut.println();
}
}