理论指导实践 二叉树用left(左子树) 和 right(右子树) 在删除的时候会遇到找parent的问题,如果引入parent节点会简单很多

    • 查找节点
      • 三种遍历方式找数据
    • 插入节点
      • 找到比较插入谁就可以了,找到对应节点的左子树和右子树,并作为他们的左子和右子
    • 遍历树
    • 删除节点
      • 删除叶子
      • 删除中间节点
      • 删除root(特殊的中间节点)

        删除是这里最为复杂的

        • 删除叶子节点,找到parent节点,将其parent节点指向null即可
        • 删除中间节点,找到左子树中最大的节点 或者 是右子树中最小的节点,然后该节点的数据修改为中间节点的数据,并将叶子节点删除。
        • root节点同上
    1. package io.github.chenshun00.web.tree;
    2. /**
    3. * <ul>
    4. * <li>查找节点</li>
    5. * <li>插入节点</li>
    6. * <li>遍历树</li>
    7. * <li>查找最大值和最小值</li>
    8. * <li>删除节点
    9. * <ul>
    10. * <li>叶子节点</li>
    11. * <li>删除有一个子节点的节点</li>
    12. * <li>删除有两个子节点的节点</li>
    13. * </ul>
    14. * </li>
    15. * <li>二叉树的效率</li>
    16. * </ul>
    17. *
    18. * @author chenshun00@gmail.com
    19. * @since 2021/7/25 1:46 下午
    20. */
    21. public class BinaryTree {
    22. /**
    23. * binaryTree.insertNode(10);
    24. * binaryTree.insertNode(9);
    25. * binaryTree.insertNode(8);
    26. * binaryTree.insertNode(9);
    27. * binaryTree.insertNode(11);
    28. * binaryTree.insertNode(12);
    29. * binaryTree.insertNode(13);
    30. * binaryTree.insertNode(231);
    31. * binaryTree.insertNode(22);
    32. *
    33. * @param args
    34. */
    35. public static void main(String[] args) {
    36. BinaryTree binaryTree = new BinaryTree();
    37. binaryTree.insertNode(22);
    38. binaryTree.insertNode(1);
    39. binaryTree.insertNode(4);
    40. binaryTree.insertNode(3);
    41. binaryTree.insertNode(10);
    42. binaryTree.insertNode(9);
    43. binaryTree.insertNode(9);
    44. binaryTree.insertNode(8);
    45. binaryTree.insertNode(190);
    46. binaryTree.insertNode(11);
    47. binaryTree.insertNode(12);
    48. binaryTree.insertNode(13);
    49. binaryTree.insertNode(231);
    50. binaryTree.insertNode(22);
    51. binaryTree.traverse();
    52. System.out.println("删除节点:===>" + binaryTree.deleteNode(9));
    53. binaryTree.traverse();
    54. System.out.println("删除节点:===>" + binaryTree.deleteNode(13));
    55. binaryTree.traverse();
    56. System.out.println("删除节点:===>" + binaryTree.deleteNode(22));
    57. binaryTree.traverse();
    58. System.out.println("删除节点:===>" + binaryTree.deleteNode(22));
    59. binaryTree.traverse();
    60. //1 3 4 8 9 9 10 11 12 13 22 22 190 231
    61. //删除节点:===>true
    62. //1 3 4 8 ? 9 10 11 12 13 22 22 190 231
    63. //删除节点:===>true
    64. //1 3 4 8 ? 9 10 11 12 ? 22 22 190 231
    65. //删除节点:===>true
    66. //1 3 4 8 ? 9 10 11 12 ? ? 22 190 231
    67. //删除节点:===>true
    68. //1 3 4 8 ? 9 10 11 12 ? ? ? 190 231
    69. }
    70. private Node root;
    71. public boolean isLeaf(Node node) {
    72. return node.leftChild == null && node.rightChild == null;
    73. }
    74. public Node findNext(Node node) {
    75. if (node.leftChild != null) {
    76. return doFindMaxNode(node.leftChild);
    77. }
    78. return doFindMinNode(node.rightChild);
    79. }
    80. public void replace(Node node) {
    81. //找到左子树中最大的节点 或者 是右子树中最小的节点
    82. final Node next = findNext(node);
    83. //找到这个节点的parent节点
    84. NodeContext nodeContext = findParent(next);
    85. if (nodeContext == null) {
    86. return;
    87. }
    88. Node parent = nodeContext.node;
    89. if (parent == null) {
    90. parent = node;
    91. }
    92. if (parent.leftChild == next) {
    93. parent.leftChild = null;
    94. } else if (parent.rightChild == next) {
    95. parent.rightChild = null;
    96. }
    97. node.data = next.data;
    98. }
    99. public boolean deleteNode(Integer data) {
    100. if (root == null) {
    101. return false;
    102. }
    103. //找到当前节点
    104. final Node node = doFindNode(data);
    105. //找不到节点的情况
    106. if (node == null) {
    107. return false;
    108. }
    109. //如果节点是根节点
    110. if (node == root) {
    111. //如果根节点是叶子节点
    112. if (isLeaf(root)) {
    113. root = null;
    114. } else {
    115. replace(root);
    116. }
    117. return true;
    118. }
    119. //被移除的是不是叶子节点
    120. if (isLeaf(node)) {
    121. //找到叶子节点的parent节点,并且说明当前节点是左(left)子树还是右子树(right)
    122. final NodeContext nodeContext = findParent(node);
    123. final Node parentNode = nodeContext.node;
    124. if (nodeContext.left) {
    125. parentNode.leftChild = null;
    126. } else {
    127. parentNode.rightChild = null;
    128. }
    129. } else {
    130. replace(node);
    131. }
    132. return true;
    133. }
    134. public NodeContext findParent(Node node) {
    135. if (node == null || node == root) {
    136. return null;
    137. }
    138. return doFind(root, node);
    139. }
    140. private NodeContext doFind(Node root, Node node) {
    141. if (root == null) {
    142. return null;
    143. }
    144. return node.data >= root.data ? doFindParentRight(root, node) : doFindParentLeft(root, node);
    145. }
    146. private Node doFindMaxNode(Node node) {
    147. if (node.rightChild == null) {
    148. return node;
    149. } else {
    150. return doFindMaxNode(node.rightChild);
    151. }
    152. }
    153. private Node doFindMinNode(Node node) {
    154. if (node.leftChild == null) {
    155. return node;
    156. } else {
    157. return doFindMinNode(node.leftChild);
    158. }
    159. }
    160. /**
    161. * 左
    162. */
    163. private NodeContext doFindParentLeft(Node root, Node node) {
    164. if (root == null) {
    165. return null;
    166. }
    167. if (root.leftChild != null) {
    168. if (root.leftChild.data.equals(node.data)) {
    169. return new NodeContext(root, true);
    170. }
    171. }
    172. if (root.rightChild != null) {
    173. if (root.rightChild.data.equals(node.data)) {
    174. return new NodeContext(root, false);
    175. }
    176. }
    177. return doFind(root.leftChild, node);
    178. }
    179. /**
    180. * 右
    181. */
    182. private NodeContext doFindParentRight(Node root, Node node) {
    183. if (root == null) {
    184. return null;
    185. }
    186. if (root.leftChild != null) {
    187. if (root.leftChild.data.equals(node.data)) {
    188. return new NodeContext(root, true);
    189. }
    190. }
    191. if (root.rightChild != null) {
    192. if (root.rightChild.data.equals(node.data)) {
    193. return new NodeContext(root, false);
    194. }
    195. }
    196. return doFind(root.rightChild, node);
    197. }
    198. public void insertNode(Integer data) {
    199. if (root == null) {
    200. root = new Node();
    201. root.data = data;
    202. } else {
    203. handleData(root, data);
    204. }
    205. }
    206. public void traverse() {
    207. doTraverse(root);
    208. System.out.println();
    209. }
    210. public Integer findNode(Integer data) {
    211. return root == null ? null : doFindNode(data).data;
    212. }
    213. public Integer findMax() {
    214. return root == null ? null : doFindMax(root);
    215. }
    216. public Integer findMin() {
    217. return root == null ? null : doFindMin(root);
    218. }
    219. private void handleData(Node root, Integer data) {
    220. if (data >= root.data) {
    221. handleRight(root, root.rightChild, data);
    222. } else {
    223. handleLeft(root, root.leftChild, data);
    224. }
    225. }
    226. //处理右子树
    227. private void handleRight(Node root, Node right, Integer data) {
    228. if (right == null) {
    229. right = new Node();
    230. right.data = data;
    231. root.rightChild = right;
    232. } else {
    233. handleData(right, data);
    234. }
    235. }
    236. //处理左子树
    237. private void handleLeft(Node root, Node left, Integer data) {
    238. if (left == null) {
    239. left = new Node();
    240. left.data = data;
    241. root.leftChild = left;
    242. } else {
    243. handleData(left, data);
    244. }
    245. }
    246. private void doTraverse(Node node) {
    247. if (node == null) {
    248. System.out.println("么数据");
    249. return;
    250. }
    251. if (node.leftChild != null) {
    252. doTraverse(node.leftChild);
    253. }
    254. System.out.print(node.data + "\t");
    255. if (node.rightChild != null) {
    256. doTraverse(node.rightChild);
    257. }
    258. }
    259. private Integer doFindMax(Node node) {
    260. if (node.rightChild == null) {
    261. return node.data;
    262. } else {
    263. return doFindMax(node.rightChild);
    264. }
    265. }
    266. private Integer doFindMin(Node node) {
    267. if (node.leftChild == null) {
    268. return node.data;
    269. } else {
    270. return doFindMin(node.leftChild);
    271. }
    272. }
    273. private Node doFindNode(Integer data) {
    274. return data >= root.data ? findRight(root, data) : findLeft(root, data);
    275. }
    276. /**
    277. * 找到右
    278. *
    279. * @param root 根
    280. * @param data 数据
    281. * @return {@link Node}
    282. */
    283. private Node findRight(Node root, Integer data) {
    284. if (root == null) {
    285. return null;
    286. }
    287. if (root.data.equals(data)) {
    288. return root;
    289. }
    290. if (data >= root.data) {
    291. //右子树
    292. return findRight(root.rightChild, data);
    293. } else {
    294. //左子树
    295. return findLeft(root.leftChild, data);
    296. }
    297. }
    298. /**
    299. * 发现左
    300. *
    301. * @param root 根
    302. * @param data 数据
    303. * @return {@link Node}
    304. */
    305. private Node findLeft(Node root, Integer data) {
    306. if (root == null) {
    307. return null;
    308. }
    309. if (root.data.equals(data)) {
    310. return root;
    311. }
    312. if (data >= root.data) {
    313. //右子树
    314. return findRight(root.rightChild, data);
    315. } else {
    316. //左子树
    317. return findLeft(root.leftChild, data);
    318. }
    319. }
    320. private static class Node {
    321. /**
    322. * 左子
    323. */
    324. public Node leftChild;
    325. /**
    326. * 数据
    327. */
    328. private Integer data;
    329. /**
    330. * 右子
    331. */
    332. public Node rightChild;
    333. }
    334. private static class NodeContext {
    335. public Node node;
    336. public boolean left;
    337. public NodeContext(Node node, boolean left) {
    338. this.node = node;
    339. this.left = left;
    340. }
    341. }
    342. }