二叉树
什么是二叉树
二叉树(Binary tree)是树形结构的一个重要类型。许多实际问题抽象出来的数据结构往往是二叉树形式,即使是一般的树也能简单地转换为二叉树,而且二叉树的存储结构及其算法都较为简单,因此二叉树显得特别重要。二叉树特点是每个结点最多只能有两棵子树,且有左右之分,说白了就是二叉树最多有两个子节点。
我们来举个例子
我们通过上述的图片可以得知没有子节点个数大于两个的,所以是二叉树。
我们举个反例
完全二叉树
一个二叉树的节点按照从上往下,从左至右的顺序,那么这个二叉树叫做完全二叉树
举个例子
举个反例
因为二叉树要按照从上到下的顺序,从左至右的顺序进行排列,目前我们从上往下是满足的,但是从左至右不满足,因为缺少两个节点,如下所示
满二叉树
二叉树的所有叶子节点都在最后一层,而且节点个数满足2^n-1,n就是树的高度
举个例子
对上述图,作以下修改
树的叶子节点都在最后一层,一共有7个结点 2^3-1 = 7,所以满足满二叉树
树的几个概念
树的各个节点
节点的权
节点1存储的值是1,那么节点1所存储的数值大小就叫做节点1的权
节点的度
一个节点有多少个子节点,节点的度就是多少
叶子节点
节点的度为0的节点,就叫做叶子节点
树的高度
树有几层,数的高度就是几,上述树的高度为3
开发准备
新建工程
工程大体结构如下
初始化工程
// BinaryTree
public class BinaryTree {
private Node rootNode;//根节点
public Node getRootNode() {
return rootNode;
}
public void setRootNode(Node rootNode) {
this.rootNode = rootNode;
}
@Override
public String toString() {
return "BinaryTree [rootNode=" + rootNode + "]";
}
public BinaryTree() {
}
public static class Node{
private int value;//节点的权
private Node leftNode;//左子节点
private Node rightNode;//右子节点
public int getValue() {
return value;
}
public void setValue(int value) {
this.value = value;
}
public Node getLeftNode() {
return leftNode;
}
public void setLeftNode(Node leftNode) {
this.leftNode = leftNode;
}
public Node getRightNode() {
return rightNode;
}
public void setRightNode(Node rightNode) {
this.rightNode = rightNode;
}
public Node(int value) {
this.value = value;
}
@Override
public String toString() {
return "Node [value=" + value + "]";
}
}
}
添加节点
普通二叉树添加节点
我们首先按照普通的二叉树来,对于普通的二叉树,我们想要添加节点,我们只需要找到父节点,直接对父节点进行操作即可
画图来解释一下
@Test
void testAddNode() {
BinaryTree tree = new BinaryTree();
Node rootNode = new BinaryTree.Node(1);
tree.setRootNode(rootNode);
System.out.println("树的根节点为" + tree.getRootNode());
//找到父节点
Node parentNode = tree.getRootNode();
//给父节点添加
parentNode.setLeftNode(new BinaryTree.Node(2));
parentNode.setRightNode(new BinaryTree.Node(3));
System.out.println("根节点的左子节点为" + parentNode.getLeftNode());
System.out.println("根节点的右子节点为" + parentNode.getRightNode());
}
结果
完全二叉树添加节点
我们知道完全二叉树是按照从上到下,从左到右的规则排列节点的,那么我们添加addNode()的方法
public void addNode(Node node)
{
if(this.rootNode == null)
{
this.rootNode = node;
return;
}
//找到父节点
LinkedList<Node> list = new LinkedList<>();
list.offer(this.rootNode);
while(list.isEmpty())
{
Node currNode = list.poll();
if(currNode.getLeftNode() !=null) list.offer(currNode.getLeftNode());
if(currNode.getRightNode() !=null) list.offer(currNode.getRightNode());
if(currNode.getLeftNode() == null)
{
currNode.setLeftNode(node);
return;
}
if(currNode.getRightNode() == null)
{
currNode.setRightNode(node);
return;
}
}
}
测试
@Test
void testAddNode1(){
BinaryTree tree = new BinaryTree();
Node rootNode = new BinaryTree.Node(1);
Node leftNode = new BinaryTree.Node(2);
Node rightNode = new BinaryTree.Node(3);
Node node4 = new BinaryTree.Node(4);
tree.addNode(rootNode);
tree.addNode(leftNode);
tree.addNode(rightNode);
tree.addNode(node4);
System.out.println("根节点:" + tree.getRootNode());
System.out.println("根节点的左子节点:" + tree.getRootNode().getLeftNode());
System.out.println("根节点的右子节点:" + tree.getRootNode().getRightNode());
System.out.println("根节点的左子节点的左子节点:" + tree.getRootNode().getLeftNode().getLeftNode());
System.out.println("根节点的左子节点的右子节点:" + tree.getRootNode().getLeftNode().getRightNode());
System.out.println("根节点的右子节点的左子节点:" + tree.getRootNode().getRightNode().getLeftNode());
System.out.println("根节点的右子节点的右子节点:" + tree.getRootNode().getRightNode().getRightNode());
}
结果
遍历
前序遍历
//BinaryTree
public String frontQueryAll() {
if(this.rootNode == null) return "{}";
StringBuilder sBuilder = new StringBuilder(20);
sBuilder.append("{");
this.rootNode.frontHelp(sBuilder);
sBuilder.deleteCharAt(1);
sBuilder.append("}");
return sBuilder.toString();
}
//Node
public void frontHelp(StringBuilder sBuilder) {
if(this != null)
{
sBuilder.append(',');
sBuilder.append(this.getValue());
}
if(this.getLeftNode() != null) this.getLeftNode().frontHelp(sBuilder);
if(this.getRightNode() != null) this.getRightNode().frontHelp(sBuilder);
}
测试
@Test
void testFront() {
BinaryTree tree = new BinaryTree();
Node rootNode = new BinaryTree.Node(1);
Node leftNode = new BinaryTree.Node(2);
Node rightNode = new BinaryTree.Node(3);
Node node4 = new BinaryTree.Node(4);
Node node5 = new BinaryTree.Node(5);
Node node6 = new BinaryTree.Node(6);
Node node7 = new BinaryTree.Node(7);
tree.addNode(rootNode);
tree.addNode(leftNode);
tree.addNode(rightNode);
tree.addNode(node4);
tree.addNode(node5);
tree.addNode(node6);
tree.addNode(node7);
System.out.println(tree.frontQueryAll());
}
结果
层次遍历
//BinaryTree
public String queryAll() {
if(this.rootNode == null) return "{}";
StringBuilder sBuilder = new StringBuilder(20);
sBuilder.append("{");
query(sBuilder);
sBuilder.deleteCharAt(1);
sBuilder.append("}");
return sBuilder.toString();
}
//BinaryTree
private void query(StringBuilder sBuilder) {
LinkedList<Node> list = new LinkedList<>();
list.offer(this.rootNode);
while(!list.isEmpty())
{
Node currNode = list.poll();
sBuilder.append(',');
sBuilder.append(currNode.getValue());
if(currNode.getLeftNode() !=null) list.offer(currNode.getLeftNode());
if(currNode.getRightNode() !=null) list.offer(currNode.getRightNode());
}
}
测试
@Test
void testquerytAll() {
BinaryTree tree = new BinaryTree();
Node rootNode = new BinaryTree.Node(1);
Node leftNode = new BinaryTree.Node(2);
Node rightNode = new BinaryTree.Node(3);
Node node4 = new BinaryTree.Node(4);
Node node5 = new BinaryTree.Node(5);
Node node6 = new BinaryTree.Node(6);
Node node7 = new BinaryTree.Node(7);
tree.addNode(rootNode);
tree.addNode(leftNode);
tree.addNode(rightNode);
tree.addNode(node4);
tree.addNode(node5);
tree.addNode(node6);
tree.addNode(node7);
System.out.println(tree.queryAll());
}
结果
中序遍历
//BinaryTree
public String centerQueryAll() {
if(this.rootNode == null) return "{}";
StringBuilder sBuilder = new StringBuilder(20);
sBuilder.append("{");
this.rootNode.centerHelp(sBuilder);
sBuilder.deleteCharAt(1);
sBuilder.append("}");
return sBuilder.toString();
}
//Node
public void centerHelp(StringBuilder sBuilder) {
if(this.getLeftNode() != null) this.getLeftNode().centerHelp(sBuilder);
if(this != null)
{
sBuilder.append(',');
sBuilder.append(this.getValue());
}
if(this.getRightNode() != null) this.getRightNode().centerHelp(sBuilder);
}
测试
@Test
void testCenter() {
BinaryTree tree = new BinaryTree();
Node rootNode = new BinaryTree.Node(1);
Node leftNode = new BinaryTree.Node(2);
Node rightNode = new BinaryTree.Node(3);
Node node4 = new BinaryTree.Node(4);
Node node5 = new BinaryTree.Node(5);
Node node6 = new BinaryTree.Node(6);
Node node7 = new BinaryTree.Node(7);
tree.addNode(rootNode);
tree.addNode(leftNode);
tree.addNode(rightNode);
tree.addNode(node4);
tree.addNode(node5);
tree.addNode(node6);
tree.addNode(node7);
System.out.println(tree.centerQueryAll());
}
结果
后序遍历
//BinaryTree
public String lastQueryAll() {
if(this.rootNode == null) return "{}";
StringBuilder sBuilder = new StringBuilder(20);
sBuilder.append("{");
this.rootNode.lastHelp(sBuilder);
sBuilder.deleteCharAt(1);
sBuilder.append("}");
return sBuilder.toString();
}
//Node
public void lastHelp(StringBuilder sBuilder) {
if(this.getLeftNode() != null) this.getLeftNode().lastHelp(sBuilder);
if(this.getRightNode() != null) this.getRightNode().lastHelp(sBuilder);
if(this != null)
{
sBuilder.append(',');
sBuilder.append(this.getValue());
}
}
测试
@Test
void testLast() {
BinaryTree tree = new BinaryTree();
Node rootNode = new BinaryTree.Node(1);
Node leftNode = new BinaryTree.Node(2);
Node rightNode = new BinaryTree.Node(3);
Node node4 = new BinaryTree.Node(4);
Node node5 = new BinaryTree.Node(5);
Node node6 = new BinaryTree.Node(6);
Node node7 = new BinaryTree.Node(7);
tree.addNode(rootNode);
tree.addNode(leftNode);
tree.addNode(rightNode);
tree.addNode(node4);
tree.addNode(node5);
tree.addNode(node6);
tree.addNode(node7);
System.out.println(tree.lastQueryAll());
}
结果