1. package com.zhangyong.DataStructures.Tree.BinaryTree;
    2. import com.zhangyong.DataStructures.Queue.ArrayQueue;
    3. import com.zhangyong.DataStructures.Queue.Queue;
    4. import com.zhangyong.DataStructures.Stack.ArrayStack;
    5. import com.zhangyong.DataStructures.Stack.Stack;
    6. /**
    7. * <p>ClassName: </p>
    8. * <p>Description: 二分搜索树 </p>
    9. * @author zhangyong
    10. * @version 1.0.0
    11. * @date 2018/9/11 8:06
    12. */
    13. public class BinarySearchTree<E extends Comparable<E>> {
    14. private class Node {
    15. public E e;
    16. public Node left, right;
    17. public Node(E e) {
    18. this.e = e;
    19. this.left = null;
    20. this.right = null;
    21. }
    22. //打印根节点及其儿子节点
    23. @Override
    24. public String toString() {
    25. return "Node{" +
    26. "e=" + e +
    27. ", node.left=" + left.e +
    28. ", right=" + right.e +
    29. '}';
    30. }
    31. }
    32. //BST根节点
    33. private Node root;
    34. //表示存储了多少元素;
    35. private int size;
    36. //无参构造器
    37. public BinarySearchTree() {
    38. root = null;
    39. size = 0;
    40. }
    41. public int size() {
    42. return size;
    43. }
    44. public boolean isEmpty() {
    45. return size == 0;
    46. }
    47. //向二分搜索树中添加元素
    48. public void add(E e) {
    49. root = add(root, e);
    50. }
    51. /*public void add(E e) {
    52. if (root == null) {
    53. root = new Node(e);
    54. ++size;
    55. } else {
    56. add(root, e);
    57. }
    58. }
    59. //(私有方法)向以node为根的二分搜索树中插入元素e,递归实现;
    60. private void add(Node node, E e) {
    61. //元素覆盖
    62. if (e.equals(node.e)) {
    63. return;
    64. } else if (e.compareTo(node.e) < 0 && node.left == null) {
    65. //左子树为空的话,直接插入;
    66. node.left = new Node(e);
    67. ++size;
    68. return;
    69. } else if (e.compareTo(node.e) > 0 && node.right == null) {
    70. node.right = new Node(e);
    71. ++size;
    72. return;
    73. }
    74. if (e.compareTo(node.e) < 0) {
    75. add(node.left, e);
    76. } else {
    77. add(node.right, e);
    78. }
    79. }*/
    80. //向以node为根的二分搜索树中插入元素e,递归实现;
    81. private Node add(Node node, E e) {
    82. //递归结束标识
    83. if (node == null) {
    84. ++size;
    85. return new Node(e);
    86. }
    87. if (e.compareTo(node.e) < 0) {
    88. node.left = add(node.left, e);
    89. } else {
    90. node.right = add(node.right, e);
    91. }
    92. return node;
    93. }
    94. //看二分搜索树中是否包含元素e
    95. public boolean contains(E e) {
    96. return contains(root, e);
    97. }
    98. //看以Node为根的二分搜索树中是否包含元素e,递归算法;
    99. private boolean contains(Node node, E e) {
    100. if (node == null) {
    101. return false;
    102. }
    103. if (e.compareTo(node.e) == 0) {
    104. return true;
    105. } else if (e.compareTo(node.e) < 0) {
    106. return contains(node.left, e);
    107. } else {
    108. return contains(node.right, e);
    109. }
    110. }
    111. //二分搜索树的前序遍历,递归算法实现
    112. public void preOrder() {
    113. preOrder(root);
    114. }
    115. //二分搜索树的前序遍历,非递归算法实现
    116. public void preOrderNR() {
    117. if (root == null) {
    118. return;
    119. }
    120. Stack<Node> stack = new ArrayStack<Node>();
    121. stack.push(root);
    122. while (!stack.isEmpty()) {
    123. Node node = stack.pop();
    124. System.out.print(node.e + " ");
    125. if (node.right != null) {
    126. stack.push(node.right);
    127. }
    128. if (node.left != null) {
    129. stack.push(node.left);
    130. }
    131. }
    132. }
    133. //前序遍历以node为根的二分搜索树,递归算法;
    134. //打印顺序: 根+左+右
    135. private void preOrder(Node node) {
    136. if (node == null) {
    137. return;
    138. }
    139. System.out.print(node.e + " ");
    140. preOrder(node.left);
    141. preOrder(node.right);
    142. }
    143. //中序遍历以node为根节点的二分搜索树,递归算法;
    144. //打印顺序: 左+根+右
    145. public void inOrder() {
    146. inOrder(root);
    147. }
    148. public void inOrder(Node node) {
    149. if (node == null) {
    150. return;
    151. }
    152. inOrder(node.left);
    153. System.out.print(node.e + " ");
    154. inOrder(node.right);
    155. }
    156. //中序遍历二分搜索树,非递归算法;
    157. //打印顺序: 左+根+右
    158. public void inOrderNR() {
    159. Stack<Node> stack = new ArrayStack<Node>();
    160. Node node = root;
    161. while (node != null || !stack.isEmpty()) {
    162. if (node != null) {
    163. stack.push(node);
    164. node = node.left;
    165. } else {
    166. node = stack.pop();
    167. System.out.print(node.e + " ");
    168. node = node.right;
    169. }
    170. }
    171. }
    172. //后序遍历以node为根节点的二分搜索树,递归算法
    173. //打印顺序: 左 + 右 + 根
    174. public void postOrder() {
    175. postOrder(root);
    176. }
    177. /**
    178. * 后序遍历:递归
    179. * @param node
    180. */
    181. public void postOrder(Node node) {
    182. if (node == null) {
    183. return;
    184. }
    185. postOrder(node.left);
    186. postOrder(node.right);
    187. System.out.print(node.e + " ");
    188. }
    189. //后序遍历以node为根节点的二分搜索树,非递归遍历
    190. //打印顺序: 左+右+根
    191. public void postOrderNR() {
    192. ArrayStack<Node> stack = new ArrayStack<Node>();
    193. Node node = root;
    194. while (node != null || !stack.isEmpty()) {
    195. }
    196. }
    197. //二分搜索树层序遍历(BFS,广度优先搜索遍历)
    198. public void levelOrder() {
    199. if (root == null) {
    200. return;
    201. }
    202. Queue<Node> queue = new ArrayQueue<>();
    203. queue.enqueue(root);
    204. while (!queue.isEmpty()) {
    205. Node node = queue.dequeue();
    206. System.out.println(node.e);
    207. if (node.left != null) {
    208. queue.enqueue(node.left);
    209. }
    210. if (node.right != null) {
    211. queue.enqueue(node.right);
    212. }
    213. }
    214. }
    215. //寻找二叉搜索树的最小值
    216. public E minimum() {
    217. if (size == 0) {
    218. throw new IllegalArgumentException("二叉树为空,无法获取最小值");
    219. }
    220. return minimum(root).e;
    221. }
    222. //返回以node为根的二分搜索树的最小值的根节点
    223. private Node minimum(Node node) {
    224. if (node.left == null) {
    225. return node;
    226. }
    227. return minimum(node.left);
    228. }
    229. //寻找二叉搜索树的最大值
    230. public E maximum() {
    231. if (size == 0) {
    232. throw new IllegalArgumentException("二叉树为空,无法查询最大值");
    233. }
    234. return maximum(root).e;
    235. }
    236. //返回以node为根的二分搜索树的最大值的根节点
    237. private Node maximum(Node node) {
    238. if (node.right == null) {
    239. return node;
    240. }
    241. return maximum(node.right);
    242. }
    243. //删除掉以Node为根的二分搜索树中的最小节点
    244. //返回删除节点后新的二分搜索树的根;
    245. private Node removeMin(Node node) {
    246. if (node.left == null) {
    247. //定义临时节点保存右子树
    248. Node rightNode = node.right;
    249. // help gc
    250. node.right = null;
    251. }
    252. node.left = removeMin(node.left);
    253. return node;
    254. }
    255. public E removeMin() {
    256. E minimum = minimum();
    257. root = removeMin(root);
    258. return minimum;
    259. }
    260. //删除掉以Node为根的二分搜索树中的最大值
    261. //返回删除节点后新的二分搜索树的根;
    262. private Node removeMax(Node node) {
    263. if (node.right == null) {
    264. Node leftNode = node.left;
    265. // help gc
    266. node.left = null;
    267. }
    268. node.right = removeMax(node.right);
    269. return node;
    270. }
    271. public E removeMax() {
    272. E maximum = maximum();
    273. root = removeMax(root);
    274. return maximum;
    275. }
    276. //从二分搜索树中删除元素为e的节点
    277. public void remove(E e) {
    278. root = remove(root, e);
    279. }
    280. public Node remove(Node node, E e) {
    281. if (node == null) {
    282. return null;
    283. }
    284. if (e.compareTo(node.e) < 0) {
    285. node.left = remove(node.left, e);
    286. return node;
    287. } else if (e.compareTo(node.e) > 0) {
    288. node.right = remove(node.right, e);
    289. return node;
    290. } else {
    291. if (node.left == null) {
    292. Node rightNode = node.right;
    293. node.right = null;
    294. size--;
    295. return rightNode;
    296. }
    297. if (node.right == null) {
    298. Node leftNode = node.left;
    299. node.left = null;
    300. size--;
    301. return leftNode;
    302. }
    303. //s为d的后继节点
    304. Node s = minimum(node.right);
    305. s.right = removeMin(node.right);
    306. s.left = node.left;
    307. return s;
    308. }
    309. }
    310. @Override
    311. public String toString() {
    312. StringBuilder sb = new StringBuilder();
    313. generateBSTString(root, 0, sb);
    314. return sb.toString();
    315. }
    316. //生成以node为根节点,深度为depth的描述二叉树的字符串;
    317. private void generateBSTString(Node node, int depth, StringBuilder res) {
    318. if (node == null) {
    319. res.append(generateDepthString(depth) + "null\n");
    320. return;
    321. }
    322. res.append(generateDepthString(depth) + node.e + "\n");
    323. generateBSTString(node.left, depth + 1, res);
    324. generateBSTString(node.right, depth + 1, res);
    325. }
    326. private String generateDepthString(int depth) {
    327. StringBuilder sb = new StringBuilder();
    328. for (int i = 0; i < depth; i++) {
    329. sb.append("--");
    330. }
    331. return sb.toString();
    332. }
    333. public static void main(String[] args) {
    334. BinarySearchTree<Integer> tree = new BinarySearchTree<>();
    335. int[] nums = new int[]{
    336. 5, 3, 6, 8, 4, 2, 7
    337. };
    338. /////////////////
    339. // 5 //
    340. // / \ //
    341. // 3 6 //
    342. // / \ \ //
    343. // 2 4 8
    344. // /
    345. // 7
    346. /////////////////
    347. for (int num : nums) {
    348. tree.add(num);
    349. }
    350. System.out.print("先序遍历二分搜索树:");
    351. tree.preOrder();
    352. System.out.println();
    353. System.out.println("先序遍历二分搜索树非递归实现:");
    354. tree.preOrderNR();
    355. System.out.println();
    356. System.out.println("中序遍历二分搜索树:");
    357. tree.inOrder();
    358. System.out.println();
    359. System.out.print("中序遍历二分搜索树非递归实现:");
    360. tree.inOrderNR();
    361. System.out.println();
    362. System.out.print("后序遍历二分搜索树:");
    363. tree.postOrder();
    364. System.out.println();
    365. System.out.println("后序遍历二分搜索树非递归实现");
    366. tree.postOrderNR();
    367. System.out.println();
    368. }
    369. }