理论指导实践 二叉树用left(左子树) 和 right(右子树) 在删除的时候会遇到找parent的问题,如果引入parent节点会简单很多
- 查找节点
- 三种遍历方式找数据
- 插入节点
- 找到比较插入谁就可以了,找到对应节点的左子树和右子树,并作为他们的左子和右子
- 遍历树
- 删除节点
- 删除叶子
- 删除中间节点
- 删除root(特殊的中间节点)
删除是这里最为复杂的
- 删除叶子节点,找到parent节点,将其parent节点指向null即可
- 删除中间节点,找到左子树中最大的节点 或者 是右子树中最小的节点,然后该节点的数据修改为中间节点的数据,并将叶子节点删除。
- root节点同上
package io.github.chenshun00.web.tree;/*** <ul>* <li>查找节点</li>* <li>插入节点</li>* <li>遍历树</li>* <li>查找最大值和最小值</li>* <li>删除节点* <ul>* <li>叶子节点</li>* <li>删除有一个子节点的节点</li>* <li>删除有两个子节点的节点</li>* </ul>* </li>* <li>二叉树的效率</li>* </ul>** @author chenshun00@gmail.com* @since 2021/7/25 1:46 下午*/public class BinaryTree {/*** binaryTree.insertNode(10);* binaryTree.insertNode(9);* binaryTree.insertNode(8);* binaryTree.insertNode(9);* binaryTree.insertNode(11);* binaryTree.insertNode(12);* binaryTree.insertNode(13);* binaryTree.insertNode(231);* binaryTree.insertNode(22);** @param args*/public static void main(String[] args) {BinaryTree binaryTree = new BinaryTree();binaryTree.insertNode(22);binaryTree.insertNode(1);binaryTree.insertNode(4);binaryTree.insertNode(3);binaryTree.insertNode(10);binaryTree.insertNode(9);binaryTree.insertNode(9);binaryTree.insertNode(8);binaryTree.insertNode(190);binaryTree.insertNode(11);binaryTree.insertNode(12);binaryTree.insertNode(13);binaryTree.insertNode(231);binaryTree.insertNode(22);binaryTree.traverse();System.out.println("删除节点:===>" + binaryTree.deleteNode(9));binaryTree.traverse();System.out.println("删除节点:===>" + binaryTree.deleteNode(13));binaryTree.traverse();System.out.println("删除节点:===>" + binaryTree.deleteNode(22));binaryTree.traverse();System.out.println("删除节点:===>" + binaryTree.deleteNode(22));binaryTree.traverse();//1 3 4 8 9 9 10 11 12 13 22 22 190 231//删除节点:===>true//1 3 4 8 ? 9 10 11 12 13 22 22 190 231//删除节点:===>true//1 3 4 8 ? 9 10 11 12 ? 22 22 190 231//删除节点:===>true//1 3 4 8 ? 9 10 11 12 ? ? 22 190 231//删除节点:===>true//1 3 4 8 ? 9 10 11 12 ? ? ? 190 231}private Node root;public boolean isLeaf(Node node) {return node.leftChild == null && node.rightChild == null;}public Node findNext(Node node) {if (node.leftChild != null) {return doFindMaxNode(node.leftChild);}return doFindMinNode(node.rightChild);}public void replace(Node node) {//找到左子树中最大的节点 或者 是右子树中最小的节点final Node next = findNext(node);//找到这个节点的parent节点NodeContext nodeContext = findParent(next);if (nodeContext == null) {return;}Node parent = nodeContext.node;if (parent == null) {parent = node;}if (parent.leftChild == next) {parent.leftChild = null;} else if (parent.rightChild == next) {parent.rightChild = null;}node.data = next.data;}public boolean deleteNode(Integer data) {if (root == null) {return false;}//找到当前节点final Node node = doFindNode(data);//找不到节点的情况if (node == null) {return false;}//如果节点是根节点if (node == root) {//如果根节点是叶子节点if (isLeaf(root)) {root = null;} else {replace(root);}return true;}//被移除的是不是叶子节点if (isLeaf(node)) {//找到叶子节点的parent节点,并且说明当前节点是左(left)子树还是右子树(right)final NodeContext nodeContext = findParent(node);final Node parentNode = nodeContext.node;if (nodeContext.left) {parentNode.leftChild = null;} else {parentNode.rightChild = null;}} else {replace(node);}return true;}public NodeContext findParent(Node node) {if (node == null || node == root) {return null;}return doFind(root, node);}private NodeContext doFind(Node root, Node node) {if (root == null) {return null;}return node.data >= root.data ? doFindParentRight(root, node) : doFindParentLeft(root, node);}private Node doFindMaxNode(Node node) {if (node.rightChild == null) {return node;} else {return doFindMaxNode(node.rightChild);}}private Node doFindMinNode(Node node) {if (node.leftChild == null) {return node;} else {return doFindMinNode(node.leftChild);}}/*** 左*/private NodeContext doFindParentLeft(Node root, Node node) {if (root == null) {return null;}if (root.leftChild != null) {if (root.leftChild.data.equals(node.data)) {return new NodeContext(root, true);}}if (root.rightChild != null) {if (root.rightChild.data.equals(node.data)) {return new NodeContext(root, false);}}return doFind(root.leftChild, node);}/*** 右*/private NodeContext doFindParentRight(Node root, Node node) {if (root == null) {return null;}if (root.leftChild != null) {if (root.leftChild.data.equals(node.data)) {return new NodeContext(root, true);}}if (root.rightChild != null) {if (root.rightChild.data.equals(node.data)) {return new NodeContext(root, false);}}return doFind(root.rightChild, node);}public void insertNode(Integer data) {if (root == null) {root = new Node();root.data = data;} else {handleData(root, data);}}public void traverse() {doTraverse(root);System.out.println();}public Integer findNode(Integer data) {return root == null ? null : doFindNode(data).data;}public Integer findMax() {return root == null ? null : doFindMax(root);}public Integer findMin() {return root == null ? null : doFindMin(root);}private void handleData(Node root, Integer data) {if (data >= root.data) {handleRight(root, root.rightChild, data);} else {handleLeft(root, root.leftChild, data);}}//处理右子树private void handleRight(Node root, Node right, Integer data) {if (right == null) {right = new Node();right.data = data;root.rightChild = right;} else {handleData(right, data);}}//处理左子树private void handleLeft(Node root, Node left, Integer data) {if (left == null) {left = new Node();left.data = data;root.leftChild = left;} else {handleData(left, data);}}private void doTraverse(Node node) {if (node == null) {System.out.println("么数据");return;}if (node.leftChild != null) {doTraverse(node.leftChild);}System.out.print(node.data + "\t");if (node.rightChild != null) {doTraverse(node.rightChild);}}private Integer doFindMax(Node node) {if (node.rightChild == null) {return node.data;} else {return doFindMax(node.rightChild);}}private Integer doFindMin(Node node) {if (node.leftChild == null) {return node.data;} else {return doFindMin(node.leftChild);}}private Node doFindNode(Integer data) {return data >= root.data ? findRight(root, data) : findLeft(root, data);}/*** 找到右** @param root 根* @param data 数据* @return {@link Node}*/private Node findRight(Node root, Integer data) {if (root == null) {return null;}if (root.data.equals(data)) {return root;}if (data >= root.data) {//右子树return findRight(root.rightChild, data);} else {//左子树return findLeft(root.leftChild, data);}}/*** 发现左** @param root 根* @param data 数据* @return {@link Node}*/private Node findLeft(Node root, Integer data) {if (root == null) {return null;}if (root.data.equals(data)) {return root;}if (data >= root.data) {//右子树return findRight(root.rightChild, data);} else {//左子树return findLeft(root.leftChild, data);}}private static class Node {/*** 左子*/public Node leftChild;/*** 数据*/private Integer data;/*** 右子*/public Node rightChild;}private static class NodeContext {public Node node;public boolean left;public NodeContext(Node node, boolean left) {this.node = node;this.left = left;}}}
