欢迎大家关注我的微信公众号:
树的定义:
树是数据结构和算法分析与设计中的一种非常重要的结构,由N个结点组成的具有层次结构的模型。
其主要有以下几个特点:
1、有一个根结点,一般称为root结点
2、每一个元素都被称为node
3、除了root结点外,其余的结点都会被分为n个互不相交的集合(子树)
树形结构的基本术语:
结点:树形结构里面的元素
子树:当结点大于1时,其余的结点分为互不相交的集合称为子树
度:一个结点拥有的子树数量称为结点的度
叶子:度为0的结点
孩子:结点的子树的根称为孩子结点
双亲:和孩子结点对应
兄弟:同一个双亲结点
深度:结点的最大层次称为树的深度,计算时间复杂度用
森林:由N个互不相交的树称为森林
二叉树(BinaryTree):
一种特殊的树形结构,每个结点最多只有两个子树。
在二叉树的第N层上,最多有2^(N-1)个结点,
如:第2层最多有2个结点,第3层最多有4个结点。
满二叉树:
假设树的深度为M,则有2^M-1个结点的二叉树。
如:树的深度为3,满二叉树的结点数为2^3-1=7
二叉树的三种遍历(重点):
前序遍历:根结点 -> 左子树 -> 右子树
中序遍历:左子树 -> 根结点 -> 右子树
后序遍历:左子树 -> 右子树 -> 根结点
遍历都是从根结点开始,遇根结点输出。
我们以中序遍历为例子:
首先找到A,A有左子树,找到B。
把B当做子树,找B的左子树,没有返回B,输出B。
然后找B的右子树,找到C。
把C当做子树,找C的左子树,找到D。
D没有子树,所以输出D。
此时C的左子树结束,返回C,输出C。
此时A的左子树全部结束,返回A,输出A。
接下来开始遍历A的右子树。
跟上面步骤一样,不做赘述。
所以中序遍历得出:
B -> D -> C -> A -> E -> H -> G -> K -> F
因此三种遍历方式得出的结果是:
前序遍历:ABCDEFGHK
中序遍历:BDCAEHGKF
后序遍历:DCBHKGFEA
我们来看看代码如何实现:
package com.monkey.springdemo.utils.sort;
class Node{
private String data;
private Node leftNode;
private Node rightNode;
public Node(String data, Node leftNode, Node rightNode) {
this.data = data;
this.leftNode = leftNode;
this.rightNode = rightNode;
}
public String getData() {
return data;
}
public void setData(String data) {
this.data = data;
}
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 class BinaryTree {
public static void main(String[] args) {
Node D = new Node("D",null,null);
Node H = new Node("H",null,null);
Node K = new Node("K",null,null);
Node C = new Node("C",D,null);
Node B = new Node("B",null,C);
Node G = new Node("G",H,K);
Node F = new Node("F",G,null);
Node E = new Node("E",null,F);
Node A = new Node("A",B,E);//根结点
BinaryTree binaryTree = new BinaryTree();
System.out.print("前序遍历:");
binaryTree.pre(A);
System.out.println();
System.out.print("中序遍历:");
binaryTree.in(A);
System.out.println();
System.out.print("后序遍历:");
binaryTree.post(A);
}
public void print(Node node){
System.out.print(node.getData());
}
//前序遍历:根(输出)-> 左 -> 右
public void pre(Node root){
//遍历根结点
print(root);
//遍历左子树
if (root.getLeftNode() != null){
pre(root.getLeftNode());
}
//遍历右子树
if (root.getRightNode() != null){
pre(root.getRightNode());
}
}
//中序遍历: 左 -> 根(输出)-> 右
public void in(Node root){
//遍历左子树
if (root.getLeftNode() != null){
in(root.getLeftNode());
}
//遍历根结点
print(root);
//遍历右子树
if (root.getRightNode() != null){
in(root.getRightNode());
}
}
//后序遍历: 左 -> 右 -> 根(输出)
public void post(Node root){
//遍历左子树
if (root.getLeftNode() != null){
post(root.getLeftNode());
}
//遍历右子树
if (root.getRightNode() != null){
post(root.getRightNode());
}
//遍历根结点
print(root);
}
}
前、中、后的遍历方式,
主要区别在于结点与子树的遍历顺序。
大家搞懂了这个顺序,自然而然就理解了遍历方式。