理论指导实践 二叉树用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;
}
}
}