【Java数据结构】二叉树

【Java数据结构】二叉树

一、二叉树的逻辑结构

1、二叉树的定义

image-20211115194424193

2、特殊的二叉树

①满二叉树

  • 如果一颗二叉树中,所有分支结点都存在左子树和右子树,并且所有叶子都在同一层上,则这样的二叉树称为满二叉树。
    • 叶子只能出现在最下一层
    • 只有度为0和度为2的结点

image-20211115194823712

②完全二叉树

  • 如果一颗二叉树中,除了最底层结点可能没有填满之外,其余每层结点树都打到最大值,并且最下面一层的结点都集中在该层最左边的若干位置

image-20211115195527240

  • 堆就是一颗完全二叉树,同时保证父子结点的顺序关系。

算法基础三:分治算法---基于二叉堆的优先队列 - DarkerG - 博客园 (cnblogs.com)

③二叉搜索树BST

Binary Search Tree

  • 二叉搜索树是由数值的数,二叉搜索树是一个有序树。
    • 若它的左子树不为空,则左子树上所有结点的值均小于它的根节点的值。
    • 若它的右子树不为空,则右子树上所有结点的值均大于它的根节点的值。
    • 它的左、右子树也分别是二叉排序树。

image-20211115200005617

④平衡二叉搜索树AVL

  • AVL(Adelson-Velsky and Landis)树
    • 它是一棵空树或者它的左右两个子树的高度差的绝对值不超过1,并且左右两个子树都是一颗平衡二叉树。

image-20211115200213354

⑤霍夫曼树

⑥红黑树R-B Tree

⑦B-Tree(B-树或者B树)

⑧B+ Tree(B+树)

二、二叉树的遍历操作定义

1、遍历的种类

image-20211118111137335

  • 前中后序遍历的操作

image-20211118111242574

  • 层序遍历:
    • 从二叉树的根节点开始,从上至下逐层遍历,同一层按照从左到右的顺序对结点逐个访问。

2、遍历操作举例

image-20211118111916135

  • 前序遍历:ABDGCEF
  • 中序遍历:DGBAECF
  • 后序遍历:GDBEFCA
  • 层序遍历:ABCDEFG

确定一颗二叉树,任何遍历操作都是唯一的。但是根据任一遍历操作却不能确定一棵二叉树

  • 可以通过前序遍历和中序遍历可以唯一确定这棵二叉树
  • 可以通过后序遍历和中序遍历可以唯一确定一棵二叉树

三、二叉树的存储结构及实现

1、二叉树的Java接口定义

public interface BinaryTreeInterface<T>{
    public void preOrder();			//前序
    public void inOrder();
    public void postOrder();
    public void levelOrder();
    //根据前序遍历序列构建二叉树
    public void createBiTree(SequentialList<T> treeElemnt);
}

2、顺序存储结构

image-20211118113033201

image-20211118113138215

图示

image-20211118113210849

代码

public class SequentialTree<T> implements BinaryTreeInterface{
    protected T[] seqTree;	//二叉树顺序存储数组
    private final static int TREE_MAX_SIZE=100;//存储容量
    //成员函数实现二叉树接口函数
}

特点

  • 浪费存储空间,最坏的情况就是右斜树,一棵深度为k的右斜树只有k个结点,却需要分配2^k-1个存储单元。事实上,二叉树的顺序存储结构一般仅适合存储完全二叉树。

3、二叉链表

image-20211118114052917

public class BiNode<T>{
    private T data;		//定义结点泛型数据域
    private BiNode<T> lChild,rChild;	//定义结点左、右孩子引用域
    public BiNode(T element){//构造数据域为element值的结点
        this.data=element;
    }
    public T getDate(){return data;}//获取数据域
    public void setDate(T data) {this.data=data;}
    public BiNode<T> getlChild(){return lChild;}
    public BiNode<T> setlChild(){this.lChild = lChild;}
    public BiNode<T> getrChild(){return rChild;}
    public BiNode<T> setrChild(){this.rChild = rChild;}
}

图示

image-20211118114606918

二叉链表的实现

​ 在BinaryTree类中,通过定义BiNode类型根节点变量root实现二叉链表存储结构。BinaryTree类实现BinaryTreeInterface接口定义的方法。

public class BinaryTree<T> implements BinaryTreeInterface{
    protected BiNode<T> root;
    //成员函数实现二叉树接口算法
}
  • 二叉树初始化(BinaryTree)---构造器
public BinaryTree(){
    root=null;
}
  • 前序遍历(preOrder)
    • 递归算法
public void preOrder(){//前序遍历入口
    preOrder(root);
}
private void preOrder(BiNode node){//前序遍历递归实现
    if(node==null){
        return;
    }else{
        System.out.print(node.getData()+" ");//访问当前节点的数据域
        preOrder(node.getlChild());	//前序递归遍历node的左子树
        preOrder(node.getrChild());	//前序递归遍历node的右子树
    }
}
  • 中序遍历(inOrder)

image-20211118122304643

  • 后序遍历(postOrder)

image-20211118122325651

  • 层序遍历(levelOrder)

image-20211118122355827

image-20211118122424436

  • 算法的伪代码描述

image-20211118122506459

  • 算法实现
public void levelOrder(){
    QueueInterface<BiNode> queue = new LinkedQueue<BiNode>();
    if(root==null){
        return;
    }else{
        queue.enQueue(root);		//根引用入队
        while(!queue.isEmpty()){
            BiNode tempNode = queue.deQueue();//出队
            System.out.print(tempNode.getData()+" ");//输出结点数据域
            if(tempNode.getlChild() !=null)			//结点非空左孩子入队
                queue.enQueue(tempNode.getlChild());
            if(tempNode.getrChild() !=null)			//结点非空右孩子入队
                queue.enQueue(tempNode.getrChild());
        }
    }
}
posted @ 2021-11-18 12:33  DarkerG  阅读(146)  评论(0)    收藏  举报