Skip to content

Commit 9141ff6

Browse files
committed
添加BTree实现
1 parent 68df125 commit 9141ff6

File tree

2 files changed

+255
-0
lines changed

2 files changed

+255
-0
lines changed

tree/src/main/java/com/mistray/BST.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,14 @@ else if (compare < 0) {
138138
return x;
139139
}
140140
}
141+
public static void main(String[] args) {
142+
BST<Integer, Integer> bst = new BST<Integer, Integer>();
143+
bst.put(1, 2);
144+
bst.put(2, 1);
145+
bst.put(3, 2);
146+
bst.put(4, 2);
147+
System.out.println(bst);
141148

149+
}
142150

143151
}
Lines changed: 247 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,247 @@
1+
package com.mistray;
2+
3+
/**
4+
* @author ZJY(MistRay)
5+
* @Project algorithm-study
6+
* @Package com.mistray
7+
* @create 2019年10月17日 14:59
8+
* @Desc B Tree 实现
9+
*/
10+
public class BTree<Key extends Comparable<Key>, Value> {
11+
12+
// 每个节点最多有几个子节点
13+
private static final int M = 4;
14+
// 根节点
15+
private Node root;
16+
// 树高
17+
private int height;
18+
// 当前节点的子节点的number
19+
private int n;
20+
21+
private static final class Node {
22+
private int m;
23+
// 子节点数组
24+
private Entry[] children = new Entry[M];
25+
26+
private Node(int k) {
27+
this.m = k;
28+
}
29+
}
30+
31+
private static class Entry {
32+
private Comparable key;
33+
private Object val;
34+
// 下一个节点
35+
private Node next;
36+
37+
public Entry(Comparable key, Object val, Node next) {
38+
this.key = key;
39+
this.val = val;
40+
this.next = next;
41+
}
42+
}
43+
44+
public BTree() {
45+
root = new Node(0);
46+
}
47+
48+
public boolean isEmpty() {
49+
return size() == 0;
50+
}
51+
52+
// 获取子节点数
53+
public int size() {
54+
return n;
55+
}
56+
57+
// 获取树高
58+
public int height() {
59+
return height;
60+
}
61+
62+
public Value get(Key key) {
63+
// 查询key
64+
if (null == key) {
65+
throw new RuntimeException("key为nul");
66+
}
67+
int h = height;
68+
return search(root, key, h);
69+
}
70+
71+
@SuppressWarnings("unchecked")
72+
private Value search(Node node, Key key, int height) {
73+
Entry[] children = node.children;
74+
// 说明树为最底层,遍历root节点的所有子节点即可
75+
if (height == 0) {
76+
for (int i = 0; i < node.m; i++) {
77+
if (eq(children[i].key, key)) {
78+
return (Value) children[i].val;
79+
}
80+
}
81+
} else {
82+
for (int i = 0; i < node.m; i++) {
83+
// 如果当前node中key比输入的key小的话,则递归,查找下一个
84+
if (i + 1 == node.m || less(key, children[i + 1].key)) {
85+
// 递归调用查找下一个node
86+
search(children[i].next, key, height - 1);
87+
}
88+
}
89+
}
90+
return null;
91+
}
92+
93+
public void put(Key key, Value value) {
94+
95+
if (key == null) {
96+
throw new NullPointerException("key must not be null");
97+
}
98+
Node u = insert(root, key, value, height); //分裂后生成的右结点
99+
n++;
100+
if (u == null) {
101+
return;
102+
}
103+
// need to split root重组root
104+
Node t = new Node(2);
105+
t.children[0] = new Entry(root.children[0].key, null, root);
106+
t.children[1] = new Entry(u.children[0].key, null, u);
107+
root = t;
108+
height++;
109+
}
110+
111+
private Node insert(Node node, Key key, Value value, int height) {
112+
int j;
113+
Entry entry = new Entry(key, value, null);
114+
// external node外部结点,也是叶子结点,在树的最底层,存的是内容value
115+
if (height == 0) {
116+
for (j = 0; j < node.m; j++) {
117+
if (less(key, node.children[j].key)) {
118+
break;
119+
}
120+
}
121+
}
122+
// internal node内部结点,存的是next地址
123+
else {
124+
for (j = 0; j < node.m; j++) {
125+
// 如果当前node.Entry[i + 1]的key比输入的key小的话
126+
if ((j + 1 == node.m) || less(key, node.children[j + 1].key)) {
127+
Node u = insert(node.children[j++].next, key, value, height - 1);
128+
if (u == null) {
129+
return null;
130+
}
131+
// 获取到数据内容.
132+
entry.key = u.children[0].key;
133+
entry.next = u;
134+
break;
135+
}
136+
}
137+
}
138+
// 把j后面的元素右移
139+
for (int i = node.m; i > j; i--) {
140+
node.children[i] = node.children[i - 1];
141+
}
142+
// 把新元素添加到children[j]上
143+
node.children[j] = entry;
144+
// 元素数量+1
145+
node.m++;
146+
// 判断node内节点数是否超出约束节点个数
147+
if (node.m < M) {
148+
return null;
149+
} else {
150+
// 分裂节点
151+
return split(node);
152+
}
153+
}
154+
155+
156+
// split node in half
157+
private Node split(Node h) {
158+
Node t = new Node(M / 2);
159+
h.m = M / 2;
160+
for (int j = 0; j < M / 2; j++) {
161+
t.children[j] = h.children[M / 2 + j];
162+
}
163+
return t;
164+
}
165+
166+
167+
/**
168+
* Returns a string representation of this B-tree (for debugging).
169+
*
170+
* @return a string representation of this B-tree.
171+
*/
172+
@Override
173+
public String toString() {
174+
return toString(root, height, "") + "\n";
175+
}
176+
177+
private String toString(Node h, int ht, String indent) {
178+
StringBuilder s = new StringBuilder();
179+
Entry[] children = h.children;
180+
181+
if (ht == 0) {
182+
for (int j = 0; j < h.m; j++) {
183+
s.append(indent + children[j].key + " " + children[j].val + "\n");
184+
}
185+
} else {
186+
for (int j = 0; j < h.m; j++) {
187+
if (j > 0) {
188+
s.append(indent + "(" + children[j].key + ")\n");
189+
}
190+
s.append(toString(children[j].next, ht - 1, indent + " "));
191+
}
192+
}
193+
return s.toString();
194+
}
195+
196+
/**
197+
* Unit tests the {@code BTree} data type.
198+
*
199+
* @param args the command-line arguments
200+
*/
201+
public static void main(String[] args) {
202+
BTree<String, String> st = new BTree<String, String>();
203+
204+
st.put("www.cs.princeton.edu", "128.112.136.12");
205+
st.put("www.cs.princeton.edu", "128.112.136.11");
206+
st.put("www.princeton.edu", "128.112.128.15");
207+
st.put("www.yale.edu", "130.132.143.21");
208+
st.put("www.simpsons.com", "209.052.165.60");
209+
st.put("www.apple.com", "17.112.152.32");
210+
st.put("www.amazon.com", "207.171.182.16");
211+
st.put("www.ebay.com", "66.135.192.87");
212+
st.put("www.cnn.com", "64.236.16.20");
213+
st.put("www.google.com", "216.239.41.99");
214+
st.put("www.nytimes.com", "199.239.136.200");
215+
st.put("www.microsoft.com", "207.126.99.140");
216+
st.put("www.dell.com", "143.166.224.230");
217+
st.put("www.slashdot.org", "66.35.250.151");
218+
st.put("www.espn.com", "199.181.135.201");
219+
st.put("www.weather.com", "63.111.66.11");
220+
st.put("www.yahoo.com", "216.109.118.65");
221+
222+
223+
System.out.println("cs.princeton.edu: " + st.get("www.cs.princeton.edu"));
224+
System.out.println("hardvardsucks.com: " + st.get("www.harvardsucks.com"));
225+
System.out.println("simpsons.com: " + st.get("www.simpsons.com"));
226+
System.out.println("apple.com: " + st.get("www.apple.com"));
227+
System.out.println("ebay.com: " + st.get("www.ebay.com"));
228+
System.out.println("dell.com: " + st.get("www.dell.com"));
229+
System.out.println();
230+
231+
System.out.println("size: " + st.size());
232+
System.out.println("height: " + st.height());
233+
System.out.println(st);
234+
System.out.println();
235+
}
236+
237+
238+
@SuppressWarnings("unchecked")
239+
private boolean less(Comparable k1, Comparable k2) {
240+
return k1.compareTo(k2) < 0;
241+
}
242+
243+
@SuppressWarnings("unchecked")
244+
private boolean eq(Comparable k1, Comparable k2) {
245+
return k1.compareTo(k2) == 0;
246+
}
247+
}

0 commit comments

Comments
 (0)