4.2二叉树

学习总结

4.2.1二叉树的定义与分类

1.二叉树的递归定义
        二叉树(Binary Tree)是一种重要的树结构,它的特点是每一个结点最多只能有两棵子树。二叉树的递归定义如下:二叉树或者是一棵空树,或者是一棵由一个根结点和两棵互不相交的分别称为根的左子树和右子树的子树所组成的非空树。
        由二叉树定义可以看出,二叉树中每一个结点的孩子只能是0、1或2个,并且每一个孩子都有左右之分。位于左边的孩子称为左孩子,位于右边的孩子称为右孩子;以左孩子为根的子树称为左子树,以右孩子为根的子树称为右子树。


2.二叉树的基本形态
二叉树的5种基本形态如图4-12所示。

 3.特殊二叉树

(1)满二叉树
        一棵深度为k且有21个结点的二叉树称为满二叉树。满二叉树具有以下特点:①每一层上的结点数都达到最大值,即对给定的高度,它是具有最多结点数的二叉树。
②满二叉树中不存在度数为1的结点,每个分支结点均有两棵高度相同的子树,且树叶都在最下一层。
图4-13是一个度为4的满二叉树。

(2)完全二叉树
        在一棵二叉树中,除了最后一层,都是满的,并且最后一层或者是满的,或者是右边缺少连续若干结点,成为完全二叉树。完全二叉树具有以下特点:
        ①叶子结点只能在最大的一层或最多只能在
层次最大的两层上出现。
        ②对任一结点,若其右分支下子孙的最大层次为n(n≥1),则其左分支下的子孙最大层次不小于n。
        ③若是满二叉树,则必定是完全二叉树,反l之不一定成立。
如图4-14是一棵深度为4的完全二叉树。

 4.2.2 二叉树的性质


性质1:若规定根结点的层数为1,则一棵非空二叉树的第i层上最多有2个结点,其中i≥1。
证明:假设树非空,用数学归纳法证明。
        ①当=1时,因为第1层上只有一个根结点,而2-2°-1,命题成立。

        ②设第i-1层上至多有22个结点。由于二叉树的每个结点至多有两个孩子,故第i层上的结点数至多是第i-1层上的最大结点数的2倍,即该层上至多有2X2-2i个结点,命题成立。

4.2.3 二叉树的抽象数据类型


二叉树的操作主要有创建二叉树、遍历、插入、删除、返回父母结点和孩子结点等。描述二叉树抽象数据类型的BinaryTTree接口声明如下,其中,BinaryNode为二叉树结点类,T为结点的元素类型。

 

public interface BinaryTTree<T>{
    public boolean isEmptyO;
    //判断是否为空
    public int count ();
    //统计二叉树结点的个数
    public int height(;
    //返回二叉树的高度
    public void preorder ();
    //先序遍历
    public void inorder();
    //中序遍历
    public void postOrder(;
    //后序遍历
    public BinaryNode<T> search(T key);/查找并返回首次出现的关键
    字为key元素结点*/
    public BinaryNode<T>getParent (BinaryNode<T> node);/*返回
    node的父母结点*/
    public void insertRoot (T x);//插入元素×作为根结点
    public BinaryMode<T> insertChild (BinaryNode<T> p, T x, boolean
    leftchild) ;//插入孩子结点
    public void removechild (BinaryNode<T> p, boolean leftchild);
    /*删除p结点的左或右子树*/
    public void removeAll(;
    //删除二叉树
}

4.2.4 二叉树的存储结构

1.顺序存储结构

2.链式存储结构

4.3 二叉树的遍历

1.先序遍历

4.3.1 先序遍历
若二叉树为空,则退出,否则进行下面操作:访问根结点。
先序遍历左子树。3 先序遍历右子树。
先序遍历的递归算法实现:

 

public void preorder (BinaryNode<T> P) {
    if(p != null) {
        System.out.print (p.data toString() +"");
        preorder(p.lchild) ;
        preorder(p.rchild);
    }
}

2.中序遍历

若二叉树为空,则退出,否则进行下面操作:
1中序遍历左子树。2.访问根结点。3中序遍历右子树。
中序遍历的递归算法实现:

 

public void inorder (BinaryNode<T>p){
    if(p !=null) {
        inorder(p.lchild) ;
        System.out.print(p.data.tostring() +"");
        inorder(p.rchild);
    }
}

3.后序遍历

若二叉树为空,则退出,否则进行下面操作:

1后序遍历左子树。
2后序遍历右子树。③访问根结点。
后序遍历的递归算法实现:

 

public void postOrder(BinaryNode<T>p){
    if(p != null)(
        postorder(p.lchild);postorder(p.rchild);
        System.out.print (p.data.toString(+"");
    }
}

4.3.4 二叉树的基本操作

1.二叉树的创建
创建二叉树一般有两种情况:初始化一个根结点或者初始化一棵空二叉树.代码如下:

public class BinaryTree<T> implements BinaryTTree<T>[
    public BinaryNode<T>root;
    public BinaryTree(){
    this.root =null;
    public BinaryTree(BinaryNode<T>root) {
    this.root = root;
    public BinaryNode<T> getRoot(){
    return root;
    public void setRoot (BinaryNode<T>root) {
    this.root = root;
    }
}

2.判断二叉树是否为空
判断二叉树是否为空,只需要判断根结点是否存在即可。代码如下:

public boolean isEmpty(
    return this.root==null;
}


3.求二叉树的深度
        求二叉树的深度,首先需要一种获取以某个结点为子树的深度方法,使用递归实现。如果一个结点为空,那么这个结点肯定是一棵空树,深度为0:如果不为空,则遍历比较它的左右子树的深度,其中较大的一个即为这棵子树的深度,然后再加上自身的深度(1)即可。

public int height{
    return height (this.root);
}
public int height (BinaryNode<T> p){
    if(p==null) {
        return 0;
    }
    int lh = height(p.lchild);
    int lr = height (p.rchild);
    return (lh>lr) ?lh + 1: lr +1;
}

4.求二叉树的结点数
        获取二叉树的结点数,需要获取以某个结点为根的子树的结点数。如果结点为空,则个数肯定为0:如果不为空,则算上这个结点之后,继续递归计算所有子树的结点数,全部相加即可。

 

public int count(){
    return count(this.root);
}
public int count(BinaryNode<T>p){
    if(p ==null){
        return 0;
    }
    return 1 + count(p.lchild) + count(p.rchild);
}

5.返回某结点的父亲结点
使用递归获取某个结点在某个子树中的父结点,以现有的这种二叉树的形式,没有办法直接获取一个结点的父结点,只能通过从根结点遍历比较获取。

 

public BinaryNode<T>getParent(BinaryNode<T> node) {
    if (root == null Ilnode -= null ll node == root){    
        return null;
    }
    return getParent(this.root, node);
    }
    public BinaryNode<T> getParent (BinaryNode<T> p,BinaryNode<T> node)
        if(p==null Ilnode -= null){
        return null;
    }
        if (p.lchild -= node ll p.rchild -= node){
        return p;
    )
    BinaryNode<T> find - getParent(p.lchild,node) ;if(find == null) {
        return getParent(p.rchild, node);
    }
    return find;
}

6.返回左右子树
这个操作很简单,直接用结点的方法获取即可。

 

    public Binarywode getleftTree(BinaryNode node){
        return node.getLchildil;
    }

    public BinaryNode getrightTree(BinaryNode node){
        return node.getRchild();
    }

7.二叉树的插入
        二叉树的插入结点分两种情况:①插入某个结点的左子结点;②插入某个结点的右子结点。当这个结点本身有子结点时,这样的插入也会覆盖原来在这个位置上的结点。另外,虽然插入的是子结点,但是子结点也可以代表一棵子树。因为单从这个结点来看,并不知道这个结点是否有左右子树存在,所以虽然插入的是一个结点,但有可能插入了很多结点(插入的是一棵子树)。

//插入根结点
public void insertRoot(T ×){
    root = new BinaryNode<T>(x,root, null);
}
//插入子结点
public BinaryNode<T> insertchild (BinaryNode<T> p, T x, BooleanlchildChild){
    if(Pp --null Ilx ==null) {
    return null;
    }
    if (lchildchild){
        p.lchild = new BinaryNode<T>(x,p.lchild, null):
        return p.lchild;
    }
    p.rchild = new BinaryNode<T>(x,p.rchild, null);
    return p.rchild;
}

8.删除子结点
删除子结点首先判断左孩子是否为空,若不为空,设置左孩子为null,否则设置右孩子为null。

 

public void removechild (BinaryNode<T> p, boolean leftchild)(
    if(p != nul1){
        if(leftchild){
        p.lchild = null;
    }else{
        p.rchild = null;
    }
}
}

9.查找
在一棵二叉树中查找关键字为key元素,返回首次出现的关键字为key元素的结点,若未找到,则返回null。该方法使用先序遍历二叉树进行查找,若一棵二叉树存在多个关键字为key元素,返回首次出现元素结点,此时首次出现的次序由二叉树遍历次序决定。

public BinaryNode<T>search(T key){
    return search(this . root, key;
}
    public BinaryNode<T> search(Binarywode<T> p,T key)(
        if(p -= null II key -=nul1){
            return null;
        }
        if(p.data.equals (key)){
        return p;
        }
    BinaryNode<T>find = search(p.lchild, key);
    if (find == null){
        find = search(p.rchild,key);
    }
    return find;
}

10.二叉树的清空
        对于二叉树的清空,首先提供一个清空某个结点为根结点的子树的方法,即递归删除每个结占,接着提供删除一个删除树的方法。

public void clear (BinaryNode node){
        if(node !=null){
        clear (node.getLchild();
        clear(node.getRchild();
        node = null; //删除结点
    }
}
//清空树
public void clear(){
    clear (root);
}

  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值