JAVA数据结构与算法 11(1).树
前景问题:为什么需要树这种数据结构?
回答:对于数组存储方式而言,通过下标方式访问元素,速度快,但若需要插入或删除某一个值时,效率很低;对于链式存储方式而言,插入删除数据时,只需要将结点插入或删除,速度很快,但进行检索时,效率很低;有没有一个数据结构可以同时增加数据的存储和读取的效率?树型结构能提高数据存储和读取的效率,比如利用二叉排序树,即可以保证数据检索的速度,同时也可以保证数据的插入,删除,修改的速度。
1 二叉树
1.1 二叉树的概念
-
树有很多种,每个节点最多只能有两个子节点的一种形式称为二叉树;
-
二叉树的子节点分为左节点和右节点;
-
如果该二叉树的所有叶子节点都在最后一层,并且结点的总数=2^n-1,n为层数,则我们称为满二叉树;
- 如果该二叉树的所有叶子节点都在最后一层或倒数第二层,而且最后一层的叶子节点在左边连续,倒数第二层的叶子节点在右边连续,我们称为完全二叉树。
1.2 二叉树的遍历
二叉树的遍历分为前序、中序和后序遍历(看输出父节点的顺序来区分),各个遍历的特点:
-
前序遍历:先输出父节点,在遍历左子树和右子树
-
中序遍历:先遍历左子树,在输出父节点,再遍历右子树
-
后序遍历:先遍历左子树,再遍历右子树,最后输出父节点
实现思路分析:
- 创建一颗二叉树;
- 前序遍历:
- 先输出当前节点(初始的时候是root节点)
- 如果左子树不为空,则递归前序遍历左子树
- 如果右子树不为空,则递归前序遍历右子树
- 中序遍历:
- 如果当前节点的左子树不为空,则递归中序遍历左子树
- 输出当前节点
- 如果当前节点的左子树不为空,则递归中序遍历右子树
- 后序遍历
- 如果当前节点的左子树不为空,则递归后序遍历左子树
- 如果当前节点的左子树不为空,则递归后序遍历右子树
- 最后输出当前节点
代码实现:
public class BinaryTreeDemo {
public static void main(String args[]){
//构建一颗二叉树
BinaryTree binaryTree = new BinaryTree();
Node a = new Node(1, "A");
Node b = new Node(2,"B");
Node c = new Node(3,"C");
Node d = new Node(4,"D");
binaryTree.setRoot(a);
a.left = b;
a.right = c;
c.right = d;
//遍历
binaryTree.preOrder(); //前序遍历:Node{id=1, name='A'}=>Node{id=2, name='B'}=>Node{id=3, name='C'}=>Node{id=4, name='D'}=>
binaryTree.inOrder(); //中序遍历:Node{id=2, name='B'}=>Node{id=1, name='A'}=>Node{id=3, name='C'}=>Node{id=4, name='D'}=>
binaryTree.posOrder(); //后序遍历:Node{id=2, name='B'}=>Node{id=4, name='D'}=>Node{id=3, name='C'}=>Node{id=1, name='A'}=>
}
}
class BinaryTree{
public Node root;
public void setRoot(Node root) {
this.root = root;
}
//前序遍历
public void preOrder(){
if(root != null){
System.out.print("前序遍历:");
this.root.pre();
System.out.println();
}else {
System.out.println("树为空");
}
}
//中序遍历
public void inOrder(){
if(root != null){
System.out.print("中序遍历:");
this.root.in();
System.out.println();
}else {
System.out.println("树为空");
}
}
//后序遍历
public void posOrder(){
if(root != null){
System.out.<