1. package com.zhangyong.DataStructures.Tree.AVL;
    2. import java.util.ArrayList;
    3. /**
    4. * <p>ClassName: </p>
    5. * <p>Description: 平衡二叉树 </p>
    6. * 在BST基础上添加 自平衡机制;
    7. *
    8. * @author zhangyong
    9. * @version 1.0.0
    10. * @date 2018/12/13 15:06
    11. */
    12. public class AVLTree<K extends Comparable<K>, V> {
    13. private class Node {
    14. public K key;
    15. public V value;
    16. public Node left, right;
    17. public int height;
    18. public Node(K key, V value) {
    19. this.key = key;
    20. this.value = value;
    21. left = null;
    22. right = null;
    23. height = 1;
    24. }
    25. }
    26. private Node root;
    27. private int size;
    28. public AVLTree() {
    29. root = null;
    30. size = 0;
    31. }
    32. public int getSize() {
    33. return size;
    34. }
    35. public boolean isEmpty() {
    36. return size == 0;
    37. }
    38. //判断二叉树是否是一颗二分搜索树
    39. private boolean isBST() {
    40. ArrayList<K> keys = new ArrayList<>();
    41. inOrder(root, keys);
    42. for (int i = 1; i < keys.size(); ++i) {
    43. if (keys.get(i - 1).compareTo(keys.get(i)) > 0) {
    44. return false;
    45. }
    46. }
    47. return true;
    48. }
    49. /**
    50. * 中序遍历
    51. *
    52. * @param node
    53. * @param keys
    54. */
    55. private void inOrder(Node node, ArrayList<K> keys) {
    56. if (node == null) {
    57. return;
    58. }
    59. inOrder(node.left, keys);
    60. keys.add(node.key);
    61. inOrder(node.right, keys);
    62. }
    63. //判断一颗二叉树是不是平衡二叉树
    64. public boolean isBalanced() {
    65. return isBalanced(root);
    66. }
    67. /**
    68. * 判断一颗二叉树是否是一颗平衡二叉树
    69. *
    70. * @param node
    71. * @return
    72. */
    73. private boolean isBalanced(Node node) {
    74. if (node == null) {
    75. return true;
    76. }
    77. int balanceFactor = getBalanceFactor(node);
    78. if (Math.abs(balanceFactor) > 1) {
    79. return false;
    80. }
    81. return isBalanced(node.left) && isBalanced(node.right);
    82. }
    83. // 向二分搜索树中添加新的元素(key, value)
    84. public void add(K key, V value) {
    85. root = add(root, key, value);
    86. }
    87. //获取高度;
    88. //叶子节点高度为0,非叶子节点高度为左右孩子节点最大+1
    89. private int getHeight(Node node) {
    90. if (node == null) {
    91. return 0;
    92. }
    93. return node.height;
    94. }
    95. // 向以node为根的二分搜索树中插入元素(key, value),递归算法
    96. // 返回插入新节点后二分搜索树的根
    97. private Node add(Node node, K key, V value) {
    98. if (node == null) {
    99. size++;
    100. return new Node(key, value);
    101. }
    102. if (key.compareTo(node.key) < 0) {
    103. node.left = add(node.left, key, value);
    104. } else if (key.compareTo(node.key) > 0) {
    105. node.right = add(node.right, key, value);
    106. } else if (key.compareTo(node.key) == 0) {
    107. node.value = value;
    108. }
    109. //添加节点之后 更新当前node的height
    110. node.height = Math.max(getHeight(node.left), getHeight(node.right)) + 1;
    111. //计算 平衡因子
    112. int balanceFactor = getBalanceFactor(node);
    113. if (Math.abs(balanceFactor) > 1) {
    114. System.out.println("This tree is unbalanced, the unbalanced coefficient is :" + balanceFactor);
    115. }
    116. //平衡维护
    117. //【1】LL
    118. /**
    119. * a b
    120. * / \ / \
    121. * b c ===> d a
    122. * / \ / / \
    123. * d e f e c
    124. * /
    125. * f
    126. */
    127. if (balanceFactor > 1 && getBalanceFactor(node.left) >= 0) {
    128. return rightRotate(node);
    129. }
    130. //【2】RR
    131. /**
    132. * a c
    133. * / \ / \
    134. * b c ===> a e
    135. * / \ / \ \
    136. * d e b d f
    137. * \
    138. * f
    139. */
    140. if (balanceFactor < -1 && getBalanceFactor(node.right) <= 0) {
    141. return leftRotate(node);
    142. }
    143. //【3】LR
    144. /**
    145. * a a e
    146. * / \ / \ / \
    147. * b c ===> e c ===> b a
    148. * / \ / \ / \ / \
    149. * d e b h d g h c
    150. * / \ / \
    151. * g h d g
    152. */
    153. if (balanceFactor > 1 && getBalanceFactor(node.left) < 0) {
    154. node.left = leftRotate(node.left);
    155. return rightRotate(node.left);
    156. }
    157. // 【4】 RL
    158. if (balanceFactor < -1 && getBalanceFactor(node.right) > 0) {
    159. node.right = rightRotate(node.right);
    160. return leftRotate(node.right);
    161. }
    162. return node;
    163. }
    164. /**
    165. * 右旋转
    166. * // 对节点y进行向右旋转操作,返回旋转后新的根节点x
    167. * // y x
    168. * // / \ / \
    169. * // x T4 向右旋转 (y) z y
    170. * // / \ - - - - - - - -> / \ / \
    171. * // z T3 T1 T2 T3 T4
    172. * // / \
    173. * // T1 T2
    174. * 节点 y 即为开始不平衡的点;
    175. *
    176. * @param y
    177. * @return
    178. */
    179. private Node rightRotate(Node y) {
    180. Node x = y.left;
    181. Node T3 = x.right;
    182. //向右旋转过程;
    183. x.right = y;
    184. y.left = T3;
    185. y.height = Math.max(getHeight(y.left), getHeight(y.right)) + 1;
    186. x.height = Math.max(getHeight(x.left), getHeight(x.right)) + 1;
    187. return x;
    188. }
    189. /**
    190. * 左旋转
    191. * // 对节点y进行向右旋转操作,返回旋转后新的根节点x
    192. * // y x
    193. * // / \ / \
    194. * // T4 x 向左旋转 (y) y z
    195. * // / \ / \ / \
    196. * // T3 z T4 T3 T2 T1
    197. * // / \
    198. * // T2 T1
    199. * 节点 y 即为开始不平衡的点;
    200. *
    201. * @param y
    202. * @return
    203. */
    204. private Node leftRotate(Node y) {
    205. Node x = y.right;
    206. Node T3 = x.left;
    207. x.left = y;
    208. y.right = T3;
    209. y.height = Math.max(getHeight(y.left), getHeight(y.right)) + 1;
    210. x.height = Math.max(getHeight(x.left), getHeight(x.right)) + 1;
    211. return x;
    212. }
    213. //获取一个节点的平衡因子
    214. private int getBalanceFactor(Node node) {
    215. if (node == null)
    216. return 0;
    217. return getHeight(node.left) - getHeight(node.right);
    218. }
    219. // 返回以node为根节点的二分搜索树中,key所在的节点
    220. private Node getNode(Node node, K key) {
    221. if (node==null) {
    222. return null;
    223. }
    224. if (key.equals(node.key))
    225. return node;
    226. else if (key.compareTo(node.key) < 0)
    227. return getNode(node.left, key);
    228. else // if(key.compareTo(node.key) > 0)
    229. return getNode(node.right, key);
    230. }
    231. public boolean contains(K key) {
    232. return getNode(root, key) != null;
    233. }
    234. public V get(K key) {
    235. Node node = getNode(root, key);
    236. if (node == null) {
    237. return null;
    238. }
    239. return node.value;
    240. }
    241. public void set(K key, V newValue) {
    242. Node node = getNode(root, key);
    243. if (node == null)
    244. throw new IllegalArgumentException(key + " doesn't exist!");
    245. node.value = newValue;
    246. }
    247. // 返回以node为根的二分搜索树的最小值所在的节点
    248. private Node minimum(Node node) {
    249. if (node.left == null)
    250. return node;
    251. return minimum(node.left);
    252. }
    253. // 删除掉以node为根的二分搜索树中的最小节点
    254. // 返回删除节点后新的二分搜索树的根
    255. private Node removeMin(Node node) {
    256. if (node.left == null) {
    257. Node rightNode = node.right;
    258. node.right = null;
    259. size--;
    260. return rightNode;
    261. }
    262. node.left = removeMin(node.left);
    263. return node;
    264. }
    265. // 从二分搜索树中删除键为key的节点
    266. public V remove(K key) {
    267. Node node = getNode(root, key);
    268. if (node != null) {
    269. root = remove(root, key);
    270. return node.value;
    271. }
    272. return null;
    273. }
    274. private Node remove(Node node, K key) {
    275. if (node == null)
    276. return null;
    277. if (key.compareTo(node.key) < 0) {
    278. node.left = remove(node.left, key);
    279. return node;
    280. } else if (key.compareTo(node.key) > 0) {
    281. node.right = remove(node.right, key);
    282. return node;
    283. } else { // key.compareTo(node.key) == 0
    284. // 待删除节点左子树为空的情况
    285. if (node.left == null) {
    286. Node rightNode = node.right;
    287. node.right = null;
    288. size--;
    289. return rightNode;
    290. }
    291. // 待删除节点右子树为空的情况
    292. if (node.right == null) {
    293. Node leftNode = node.left;
    294. node.left = null;
    295. size--;
    296. return leftNode;
    297. }
    298. // 待删除节点左右子树均不为空的情况
    299. // 找到比待删除节点大的最小节点, 即待删除节点右子树的最小节点
    300. // 用这个节点顶替待删除节点的位置
    301. Node successor = minimum(node.right);
    302. successor.right = removeMin(node.right);
    303. successor.left = node.left;
    304. node.left = node.right = null;
    305. return successor;
    306. }
    307. }
    308. public static void main(String[] args) {
    309. System.out.println("Pride and Prejudice");
    310. ArrayList<String> words = new ArrayList<>();
    311. if (FileOperation.readFile("pride-and-prejudice.txt", words)) {
    312. System.out.println("Total words: " + words.size());
    313. AVLTree<String, Integer> map = new AVLTree<>();
    314. for (String word : words) {
    315. if (map.contains(word))
    316. map.set(word, map.get(word) + 1);
    317. else
    318. map.add(word, 1);
    319. }
    320. System.out.println("Total different words: " + map.getSize());
    321. System.out.println("Frequency of PRIDE: " + map.get("pride"));
    322. System.out.println("Frequency of PREJUDICE: " + map.get("prejudice"));
    323. System.out.println("is BST :" + map.isBST());
    324. }
    325. System.out.println();
    326. }
    327. }