1,二叉树基本概念
- 树分为很多种,其中每一个节点最多有两个节点的树形式称之为二叉树
- 二叉树的子节点分为左节点和父节点;对于一个父节点来说,可以单独存在左子节点或者右子节点,也可以同时存在左右子节点
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/2604a954cc93c0fb870280c3986606ef.png)
- 如果二叉树的所有叶子节点都在最后一层,并且
节点总数 = 2 ^ n - 1
,n为最大层数,则该二叉树可以称之为满二叉树
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/97bc8e281757fc89a8f29275fabb01c4.png)
- 如果二叉树的所有叶子节点都在最后一层或者倒数第二层,且最后一层的叶子节点在左边连续,倒数第二层的叶子节点在右边连续,则称之为完全二叉树
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/82185b4670d3a938c6c78e40a4bbfe83.png)
2,二叉树遍历
2.1,前序遍历
- 先输出当前节点(初始为叶子节点)
- 如果左子节点不为空,再递归前序遍历输出左子节点
- 如果右子节点不为空,最后递归前序遍历输出右子节点
2.2,中序遍历
- 如果左子节点不为空,先递归中序遍历输出左子节点
- 再输出当前节点
- 如果右子节点不为空,最后递归中序遍历输出右子节点
2.3,后续遍历
- 如果左子节点不为空,先递归后序遍历输出左子节点
- 如果右子节点不为空,再递归后序遍历输出右子节点
- 最后输出当前节点
2.4,遍历代码汇总
package com.self.datastructure.tree;
import lombok.Data;
import lombok.ToString;
import java.util.ArrayList;
import java.util.List;
public class BinaryTree {
public static void main(String[] args) {
MyBinaryTree binaryTree = new MyBinaryTree();
binaryTree.addNode(5);
binaryTree.addNode(1);
binaryTree.addNode(4);
binaryTree.addNode(6);
binaryTree.addNode(3);
binaryTree.addNode(2);
binaryTree.addNode(7);
binaryTree.addNode(8);
binaryTree.addNode(8);
binaryTree.postShowDetails(binaryTree.getNode());
}
static class MyBinaryTree {
private Node node;
public void addNode(Integer data) {
if (null == node) {
node = new Node(data);
} else {
addNode(data, node);
}
}
private void addNode(Integer data, Node node) {
if (null == node) {
throw new RuntimeException("Node 节点为空");
}
if (data > node.getData()) {
Node rightNode = node.getRightNode();
if (null == rightNode) {
Node newNode = new Node(data);
node.setRightNode(newNode);
newNode.setParentNode(node);
} else {
addNode(data, node.getRightNode());
}
} else if (data < node.getData()) {
Node leftNode = node.getLeftNode();
if (null == leftNode) {
Node newNode = new Node(data);
node.setLeftNode(newNode);
newNode.setParentNode(node);
} else {
addNode(data, node.getLeftNode());
}
} else {
System.out.println("数据节点已经存在");
}
}
public Node getNode() {
return node;
}
public void preShowDetails() {
doPreShowDetails(node);
}
private void doPreShowDetails(Node node) {
if (null == node) {
return;
}
System.out.println("Node: " + node.getData());
if (null != node.getLeftNode()) {
doPreShowDetails(node.getLeftNode());
}
if (null != node.getRightNode()) {
doPreShowDetails(node.getRightNode());
}
}
public void middleShowDetails() {
doMiddleShowDetails(node);
}
public void doMiddleShowDetails(Node node) {
if (null == node) {
return;
}
if (null != node.getLeftNode()) {
doMiddleShowDetails(node.getLeftNode());
}
System.out.println("Node: " + node.getData());
if (null != node.getRightNode()) {
doMiddleShowDetails(node.getRightNode());
}
}
public void postShowDetails() {
doPostShowDetails(node);
}
public void doPostShowDetails(Node node) {
if (null == node) {
return;
}
if (null != node.getLeftNode()) {
doPostShowDetails(node.getLeftNode());
}
if (null != node.getRightNode()) {
doPostShowDetails(node.getRightNode());
}
System.out.println("Node: " + node.getData());
}
}
@Data
@ToString
static class Node {
private Integer data;
private Node leftNode;
private Node rightNode;
private Node parentNode;
public Node() {}
public Node(Integer data) {
this(data, null, null);
}
public Node(Integer data, Node leftNode, Node rightNode) {
this.data = data;
this.leftNode = leftNode;
this.rightNode = rightNode;
}
}
}
3,二叉树查找
3.1,前序查找
- 先比较当前节点,当前节点匹配到直接返回
- 再匹配左侧节点,并递归前序查找进行匹配,匹配到直接返回
- 最后匹配右侧节点,并递归前序查找进行匹配,匹配到直接返回
- 以上几步没有匹配到,则返回null,表示没有匹配到
3.2,中序查找
- 先匹配左侧节点,并递归中序查找进行匹配,匹配到直接返回
- 再比较当前节点,当前节点匹配到直接返回
- 最后匹配右侧节点,并递归中序查找进行匹配,匹配到直接返回
- 以上几步没有匹配到,则返回null,表示没有匹配到
3.3,后续查找
- 先匹配左侧节点,并递归后序查找进行匹配,匹配到直接返回
- 再匹配右侧节点,并递归后序查找进行匹配,匹配到直接返回
- 再比较当前节点,当前节点匹配到直接返回
- 以上几步没有匹配到,则返回null,表示没有匹配到
3.4,查找代码汇总
package com.self.datastructure.tree;
import lombok.Data;
import lombok.ToString;
import java.util.ArrayList;
import java.util.List;
public class BinaryTree {
public static void main(String[] args) {
MyBinaryTree binaryTree = new MyBinaryTree();
binaryTree.addNode(5);
binaryTree.addNode(1);
binaryTree.addNode(4);
binaryTree.addNode(6);
binaryTree.addNode(3);
binaryTree.addNode(2);
binaryTree.addNode(7);
binaryTree.addNode(8);
System.out.println(binaryTree.preFindNode(50));
}
static class MyBinaryTree {
private Node node;
public void addNode(Integer data) {
if (null == node) {
node = new Node(data);
} else {
addNode(data, node);
}
}
private void addNode(Integer data, Node node) {
if (null == node) {
throw new RuntimeException("Node 节点为空");
}
if (data > node.getData()) {
Node rightNode = node.getRightNode();
if (null == rightNode) {
Node newNode = new Node(data);
node.setRightNode(newNode);
newNode.setParentNode(node);
} else {
addNode(data, node.getRightNode());
}
} else if (data < node.getData()) {
Node leftNode = node.getLeftNode();
if (null == leftNode) {
Node newNode = new Node(data);
node.setLeftNode(newNode);
newNode.setParentNode(node);
} else {
addNode(data, node.getLeftNode());
}
} else {
System.out.println("数据节点已经存在");
}
}
public Integer preFindNode(Integer targetData) {
return doPreFindNode(targetData, node);
}
public Integer doPreFindNode(Integer targetData, Node node) {
if (null == node) {
return null;
}
if (targetData == node.getData()) {
return node.getData();
} else if (targetData < node.getData()) {
return doPreFindNode(targetData, node.getLeftNode());
} else if (targetData > node.getData()) {
return doPreFindNode(targetData, node.getRightNode());
}
return null;
}
public Integer middleFindNode(Integer targetData) {
return doMiddleFindNode(targetData, node);
}
public Integer doMiddleFindNode(Integer targetData, Node node) {
if (null == node) {
return null;
}
if (targetData < node.getData()) {
return doMiddleFindNode(targetData, node.getLeftNode());
} else if (targetData == node.getData()) {
return node.getData();
} else if (targetData > node.getData()) {
return doMiddleFindNode(targetData, node.getRightNode());
}
return null;
}
public Integer postFindNode(Integer targetData) {
return doPostFindNode(targetData, node);
}
public Integer doPostFindNode(Integer targetData, Node node) {
if (null == node) {
return null;
}
if (targetData < node.getData()) {
return doPostFindNode(targetData, node.getLeftNode());
} else if (targetData > node.getData()) {
return doPostFindNode(targetData, node.getRightNode());
} else if (targetData == node.getData()) {
return node.getData();
}
return null;
}
@Data
@ToString
static class Node {
private Integer data;
private Node leftNode;
private Node rightNode;
private Node parentNode;
public Node() {}
public Node(Integer data) {
this(data, null, null);
}
public Node(Integer data, Node leftNode, Node rightNode) {
this.data = data;
this.leftNode = leftNode;
this.rightNode = rightNode;
}
}
}
4,二叉树删除
4.1,删除步骤
- 如果删除的节点是叶子节点,则直接删除
- 如果删除的是非叶子节点,则需要对删除节点的子节点进行处理
- 用右侧最左节点代替该节点,并删除右侧最左节点
4.2,删除代码实现
package com.self.datastructure.tree;
import lombok.Data;
import lombok.ToString;
import java.util.ArrayList;
import java.util.List;
public class BinaryTree {
public static void main(String[] args) {
MyBinaryTree binaryTree = new MyBinaryTree();
binaryTree.addNode(5);
binaryTree.addNode(2);
binaryTree.addNode(1);
binaryTree.addNode(4);
binaryTree.addNode(3);
binaryTree.addNode(8);
binaryTree.addNode(6);
binaryTree.addNode(9);
binaryTree.addNode(10);
binaryTree.middleShowDetails();
System.out.println(binaryTree.delNode(1));;
binaryTree.middleShowDetails();
}
static class MyBinaryTree {
private Node node;
public void addNode(Integer data) {
if (null == node) {
node = new Node(data);
} else {
addNode(data, node);
}
}
private void addNode(Integer data, Node node) {
if (null == node) {
throw new RuntimeException("Node 节点为空");
}
if (data > node.getData()) {
Node rightNode = node.getRightNode();
if (null == rightNode) {
node.setRightNode(new Node(data));
} else {
addNode(data, node.getRightNode());
}
} else if (data < node.getData()) {
Node leftNode = node.getLeftNode();
if (null == leftNode) {
node.setLeftNode(new Node(data));
} else {
addNode(data, node.getLeftNode());
}
} else {
System.out.println("数据节点已经存在");
}
}
public boolean delNode(Integer targetData) {
if (null == node) {
return false;
}
return doDelNode(targetData, node);
}
private boolean doDelNode(Integer targetData, Node node) {
if (null == node) {
return false;
}
if (targetData > node.getData()) {
return doDelNode(targetData, node.getRightNode());
} else if (targetData < node.getData()) {
return doDelNode(targetData, node.getLeftNode());
} else {
Node nextNode = findNextNode(node);
if (null == nextNode) {
if (this.node == node) {
this.node = node.getLeftNode();
this.node.setParentNode(null);
} else {
if (node == node.getParentNode().getLeftNode()) {
node.getParentNode().setLeftNode(node.getLeftNode());
} else if (node == node.getParentNode().getRightNode()) {
node.getParentNode().setRightNode(node.getLeftNode());
}
if (null != node.getLeftNode()) {
node.getLeftNode().setParentNode(node.getParentNode());
}
}
} else {
node.setData(nextNode.getData());
if (nextNode == nextNode.getParentNode().getLeftNode()) {
nextNode.getParentNode().setLeftNode(nextNode.getRightNode());
} else if (nextNode == nextNode.getParentNode().getRightNode()) {
nextNode.getParentNode().setRightNode(nextNode.getRightNode());
}
if (null != nextNode.getRightNode()) {
nextNode.getRightNode().setParentNode(nextNode.getParentNode());
}
}
return true;
}
}
private Node findNextNode(Node node) {
Node nextNode = node.getRightNode();
if (null == nextNode) {
return nextNode;
}
while (null != nextNode.getLeftNode()) {
nextNode = nextNode.getLeftNode();
}
return nextNode;
}
public void middleShowDetails() {
doMiddleShowDetails(node);
}
public void doMiddleShowDetails(Node node) {
if (null == node) {
return;
}
if (null != node.getLeftNode()) {
doMiddleShowDetails(node.getLeftNode());
}
System.out.println("Node: " + node.getData());
if (null != node.getRightNode()) {
doMiddleShowDetails(node.getRightNode());
}
}
}
@Data
@ToString
static class Node {
private Integer data;
private Node leftNode;
private Node rightNode;
public Node() {}
public Node(Integer data) {
this(data, null, null);
}
public Node(Integer data, Node leftNode, Node rightNode) {
this.data = data;
this.leftNode = leftNode;
this.rightNode = rightNode;
}
}
}