Skip to content

Commit c8a2529

Browse files
committed
完成 AVLTree
1 parent 783bab0 commit c8a2529

File tree

6 files changed

+303
-17
lines changed

6 files changed

+303
-17
lines changed

AVLTree/src/AVLMap.java

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
public class AVLMap<K extends Comparable<K>, V> implements Map<K, V> {
2+
private AVLTree<K, V> avl;
3+
4+
public AVLMap() {
5+
avl = new AVLTree<>();
6+
}
7+
8+
@Override
9+
public void add(K key, V value) {
10+
avl.add(key, value);
11+
}
12+
13+
@Override
14+
public boolean contains(K key) {
15+
return avl.contains(key);
16+
}
17+
18+
@Override
19+
public V get(K key) {
20+
return avl.get(key);
21+
}
22+
23+
@Override
24+
public void set(K key, V newValue) {
25+
avl.set(key, newValue);
26+
}
27+
28+
@Override
29+
public V remove(K key) {
30+
return avl.remove(key);
31+
}
32+
33+
@Override
34+
public int getSize() {
35+
return avl.getSize();
36+
}
37+
38+
@Override
39+
public boolean isEmpty() {
40+
return avl.isEmpty();
41+
}
42+
}

AVLTree/src/AVLSet.java

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
public class AVLSet<E extends Comparable<E>> implements Set<E> {
2+
3+
private AVLTree<E, Object> avl;
4+
5+
public AVLSet() {
6+
avl = new AVLTree<>();
7+
}
8+
9+
@Override
10+
public void add(E e) {
11+
avl.add(e, null);
12+
}
13+
14+
@Override
15+
public boolean contains(E e) {
16+
return avl.contains(e);
17+
}
18+
19+
@Override
20+
public void remove(E e) {
21+
avl.remove(e);
22+
}
23+
24+
@Override
25+
public int getSize() {
26+
return avl.getSize();
27+
}
28+
29+
@Override
30+
public boolean isEmpty() {
31+
return avl.isEmpty();
32+
}
33+
}

AVLTree/src/AVLTree.java

Lines changed: 151 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,44 @@ public boolean isEmpty() {
3333
return size == 0;
3434
}
3535

36+
// 判断该二叉树是否是一棵二分搜索树
37+
public boolean isBST() {
38+
ArrayList<K> keys = new ArrayList<>();
39+
inOrder(root, keys);
40+
for (int i = 1; i < keys.size(); i++) {
41+
if (keys.get(i - 1).compareTo(keys.get(i)) > 0) {
42+
return false;
43+
}
44+
}
45+
return true;
46+
}
47+
48+
private void inOrder(Node node, ArrayList<K> keys) {
49+
if (node == null) {
50+
return;
51+
}
52+
inOrder(node.left, keys);
53+
keys.add(node.key);
54+
inOrder(node.right, keys);
55+
}
56+
57+
// 判断该二叉树是否是一棵平衡二叉树
58+
public boolean isBalanced() {
59+
return isBalanced(root);
60+
}
61+
62+
// 判断以Node节点为根的二叉树是否是一棵平衡二叉树,递归算法
63+
private boolean isBalanced(Node node) {
64+
if (node == null) {
65+
return true;
66+
}
67+
int balanceFactor = getBalanceFactor(node);
68+
if (Math.abs(balanceFactor) > 1) {
69+
return false;
70+
}
71+
return isBalanced(node.left) && isBalanced(node.right);
72+
}
73+
3674
private int getHeight(Node node) {
3775
if (node == null)
3876
return 0;
@@ -47,6 +85,38 @@ private int getBalanceFactor(Node node) {
4785
return getHeight(node.left) - getHeight(node.right);
4886
}
4987

88+
// 对节点y进行向右旋转操作,返回旋转后新的根节点x
89+
private Node rightRotate(Node y) {
90+
Node x = y.left;
91+
Node T3 = x.right;
92+
93+
// 向右旋转过程
94+
x.right = y;
95+
y.left = T3;
96+
97+
// 更新 height (只需要更新 y和x, 先y后x)
98+
y.height = Math.max(getHeight(y.left), getHeight(y.right)) + 1;
99+
x.height = Math.max(getHeight(x.left), getHeight(x.right)) + 1;
100+
101+
return x;
102+
}
103+
104+
// 对节点y进行向左旋转操作,返回旋转后新的根节点x
105+
private Node leftRotate(Node y) {
106+
Node x = y.right;
107+
Node T2 = x.left;
108+
109+
// 向左旋转过程
110+
x.left = y;
111+
y.right = T2;
112+
113+
// 更新 height (只需要更新 y和x, 先y后x)
114+
y.height = Math.max(getHeight(y.left), getHeight(y.right)) + 1;
115+
x.height = Math.max(getHeight(x.left), getHeight(x.right)) + 1;
116+
117+
return x;
118+
}
119+
50120
// 向二分搜索树中添加新的元素(key, value)
51121
public void add(K key, V value) {
52122
root = add(root, key, value);
@@ -73,8 +143,28 @@ else if (key.compareTo(node.key) > 0)
73143

74144
// 计算平衡因子
75145
int balanceFactor = getBalanceFactor(node);
76-
if (Math.abs(balanceFactor) > 1) {
77-
System.out.println("unbabalanced : " + balanceFactor);
146+
// if (Math.abs(balanceFactor) > 1) {
147+
// System.out.println("unbabalanced : " + balanceFactor);
148+
// }
149+
150+
// 平衡维护
151+
// LL
152+
if (balanceFactor > 1 && getBalanceFactor(node.left) >= 0) {
153+
return rightRotate(node);
154+
}
155+
// RR
156+
if (balanceFactor < -1 && getBalanceFactor(node.right) <= 0) {
157+
return leftRotate(node);
158+
}
159+
// LR
160+
if (balanceFactor > 1 && getBalanceFactor(node.left) < 0) {
161+
node.left = leftRotate(node.left); // 转化成LL
162+
return rightRotate(node);
163+
}
164+
// RL
165+
if (balanceFactor < -1 && getBalanceFactor(node.right) > 0) {
166+
node.right = rightRotate(node.right);// 转化成RR
167+
return leftRotate(node);
78168
}
79169

80170
return node;
@@ -150,50 +240,85 @@ private Node remove(Node node, K key) {
150240
if (node == null)
151241
return null;
152242

243+
Node retNode;
153244
if (key.compareTo(node.key) < 0) {
154245
node.left = remove(node.left, key);
155-
return node;
246+
retNode = node;
156247
} else if (key.compareTo(node.key) > 0) {
157248
node.right = remove(node.right, key);
158-
return node;
249+
retNode = node;
159250
} else { // key.compareTo(node.key) == 0
160251

161252
// 待删除节点左子树为空的情况
162253
if (node.left == null) {
163254
Node rightNode = node.right;
164255
node.right = null;
165256
size--;
166-
return rightNode;
257+
retNode = rightNode;
167258
}
168259

169260
// 待删除节点右子树为空的情况
170-
if (node.right == null) {
261+
else if (node.right == null) {
171262
Node leftNode = node.left;
172263
node.left = null;
173264
size--;
174-
return leftNode;
175-
}
265+
retNode = leftNode;
266+
} else { // 待删除节点左右子树均不为空的情况
176267

177-
// 待删除节点左右子树均不为空的情况
268+
// 找到比待删除节点大的最小节点, 即待删除节点右子树的最小节点
269+
// 用这个节点顶替待删除节点的位置
270+
Node successor = minimum(node.right);
271+
// successor.right = removeMin(node.right); // 注意平衡
272+
successor.right = remove(node.right, successor.key); // 注意平衡
273+
successor.left = node.left;
274+
275+
node.left = node.right = null;
276+
277+
retNode = successor;
278+
}
178279

179-
// 找到比待删除节点大的最小节点, 即待删除节点右子树的最小节点
180-
// 用这个节点顶替待删除节点的位置
181-
Node successor = minimum(node.right);
182-
successor.right = removeMin(node.right);
183-
successor.left = node.left;
280+
}
281+
if (retNode == null) // 注意空处理
282+
return null;
184283

185-
node.left = node.right = null;
284+
// 更新 height
285+
retNode.height = 1 + Math.max(getHeight(retNode.left), getHeight(retNode.right));
186286

187-
return successor;
287+
// 计算平衡因子
288+
int balanceFactor = getBalanceFactor(retNode);
289+
// if (Math.abs(balanceFactor) > 1) {
290+
// System.out.println("unbabalanced : " + balanceFactor);
291+
// }
292+
293+
// 平衡维护
294+
// LL
295+
if (balanceFactor > 1 && getBalanceFactor(retNode.left) >= 0) {
296+
return rightRotate(retNode);
297+
}
298+
// RR
299+
if (balanceFactor < -1 && getBalanceFactor(retNode.right) <= 0) {
300+
return leftRotate(retNode);
301+
}
302+
// LR
303+
if (balanceFactor > 1 && getBalanceFactor(retNode.left) < 0) {
304+
retNode.left = leftRotate(retNode.left); // 转化成LL
305+
return rightRotate(retNode);
188306
}
307+
// RL
308+
if (balanceFactor < -1 && getBalanceFactor(retNode.right) > 0) {
309+
retNode.right = rightRotate(retNode.right);// 转化成RR
310+
return leftRotate(retNode);
311+
}
312+
313+
return retNode;
189314
}
190315

191316
public static void main(String[] args) {
192317

193318
System.out.println("Pride and Prejudice");
194319

195320
ArrayList<String> words = new ArrayList<>();
196-
if (FileOperation.readFile("pride-and-prejudice.txt", words)) {
321+
if (FileOperation.readFile("AVLTree/pride-and-prejudice.txt", words)) {
197322
System.out.println("Total words: " + words.size());
198323

199324
AVLTree<String, Integer> map = new AVLTree<>();
@@ -207,6 +332,15 @@ public static void main(String[] args) {
207332
System.out.println("Total different words: " + map.getSize());
208333
System.out.println("Frequency of PRIDE: " + map.get("pride"));
209334
System.out.println("Frequency of PREJUDICE: " + map.get("prejudice"));
335+
336+
System.out.println("is BST : " + map.isBST());
337+
System.out.println("is isBalanced : " + map.isBalanced());
338+
339+
for (String word : words) {
340+
map.remove(word);
341+
if (!map.isBST() || !map.isBalanced())
342+
throw new RuntimeException("Error");
343+
}
210344
}
211345

212346
System.out.println();

AVLTree/src/Main.java

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
import java.util.ArrayList;
2+
import java.util.Collections;
3+
4+
public class Main {
5+
6+
public static void main(String[] args) {
7+
System.out.println("Pride and Prejudice");
8+
long startTIme;
9+
long endTIme;
10+
ArrayList<String> words = new ArrayList<>();
11+
if (FileOperation.readFile("AVLTree/pride-and-prejudice.txt", words)) {
12+
13+
Collections.sort(words);// 对于BST 来说
14+
15+
// Test BST
16+
startTIme = System.nanoTime();
17+
18+
BST<String, Integer> bst = new BST<>();
19+
for (String word : words) {
20+
if (bst.contains(word))
21+
bst.set(word, bst.get(word) + 1);
22+
else
23+
bst.add(word, 1);
24+
}
25+
26+
// 查询操作
27+
for (String word : words) {
28+
bst.contains(word);
29+
}
30+
31+
endTIme = System.nanoTime();
32+
33+
double time = (endTIme - startTIme) / 1000000000.0;
34+
System.out.println("BST: " + time + " s");
35+
36+
37+
// Test AVL Tree
38+
startTIme = System.nanoTime();
39+
40+
AVLTree<String, Integer> avl = new AVLTree<>();
41+
for (String word : words) {
42+
if (avl.contains(word))
43+
avl.set(word, avl.get(word) + 1);
44+
else
45+
avl.add(word, 1);
46+
}
47+
48+
// 查询操作
49+
for (String word : words) {
50+
avl.contains(word);
51+
}
52+
53+
endTIme = System.nanoTime();
54+
55+
time = (endTIme - startTIme) / 1000000000.0;
56+
System.out.println("AVLTree: " + time + " s");
57+
}
58+
}
59+
}

AVLTree/src/Map.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
public interface Map<K, V> {
2+
3+
void add(K key, V value);
4+
boolean contains(K key);
5+
V get(K key);
6+
void set(K key, V newValue);
7+
V remove(K key);
8+
int getSize();
9+
boolean isEmpty();
10+
}

AVLTree/src/Set.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
public interface Set<E> {
2+
3+
void add(E e);
4+
boolean contains(E e);
5+
void remove(E e);
6+
int getSize();
7+
boolean isEmpty();
8+
}

0 commit comments

Comments
 (0)