树与二叉树

树与二叉树

1. 树

表明一种上下级的关系 ,是n(n>=0)个节点的有限集

1)空树:n=0,不包含任何结点

2)非空树:n>0,此时有且仅有一个“根结点”

​ n>1,此时其余节点可分为(m>0)个互不相交的有限集

1.1 基本的概念

结点的度:结点拥有的子树的个数

叶子结点:度为0的结点称为叶子结点或终端结点

树的度:各个结点度的最大值

树的深度/高度: 树中结点的最大层次数称为树的深度或高度

父亲、儿子、兄弟

父亲:一个结点的直接前驱结点

儿子:一个结点的直接后继结点

兄弟:同一个父亲结点的其他结点

祖先、子孙、堂兄弟

节点的祖先:从根节点到该结点路径上的所有结点

子孙:以某结点为根的树中的任一结点都称为该结点的子孙

有序树、无序树、m叉树

有序树:将树中结点的各子树看成是从左至右是有次序的,子树间不能互换位置,则称该树为有序树。

无序树:以上概念否则为无序树。

m叉树:树中所有结点最大度数为m的有序树称为m叉树

森林:是m棵互不相交的树的集合,对树中每个结点而言,其子树的集合即为森林。

###1.2 树的表示

1.3 树的应用

1,目录结构

2, 单位组织架构

2.二叉树

2.1 概念

每个结点的度均不超过2的有序树,称为二叉树。

一棵二叉树是结点的一个有限集合,该集合或者为空,或者是由一个根节点加上两棵别称为左子树和右子树 的二叉树组成。

2.2 二叉树的特点

  1. 每个结点最多有两棵子树,即二叉树不存在度大于2的结点。
  2. 二叉树的子树有左右之分,其子树的次序不能颠倒。
  3. 对于任何一棵二叉树,如果其终端结点数比树中度为2的结点数多一个。
  4. 二叉树的第i层上,最多有2^(i-1)个结点。

2.3 现实中的二叉树

2.4 特殊二叉树

满二叉树一定是完全二叉树,而完全二叉树不一定是满二叉树。

2.4.1 满二叉树

一个二叉树,如果每一个层的结点数都达到最大值,则这个二叉树就是满二叉树。也就是 说,如果一个二叉树的层数为K,且结点总数是(2^k) -1 ,则它就是满二叉树。

2.4.2 完全二叉树(堆)

若在一棵二叉树中,在最下层从最右侧起去掉相邻的若干叶子结点,得到的二叉树称为完全二叉树。

完全二叉树是效率很高的数据结构,完全二叉树是由满二叉树而引出来的。 要注意的是满二叉树是一种特殊的完全二叉树。

对于一棵有n个结点的完全二叉树的结点进行编号,对于任一结点有:

1,如果i=1,则结点i为二叉树的根结点,无双亲

​ i>1,则其双亲结点PARENT(i)是结点[i/2];

2,如果2i>n,则结点i无左孩子;否则其左孩子是结点2i;

3,如果2i+1>n,则结点i无右孩子,否则其有孩子的结点2i+1;

2.5 二叉树的存储结构

在物理上是一个数组,在逻辑上是一颗二叉树

2.5.1 顺序存储

数组:适用于完全二叉树/满二叉树。对于不是完全二叉树,无法确定结点之间的前驱后继关系,会造成空间浪费。

[外链图片转存失败(img-deHgmlmW-1564736814704)(E:\javaclass\顺序二叉树.png)]

2.5.2 链式存储

[外链图片转存失败(img-axZElskC-1564736814706)(E:\javaclass\二叉链表.png)]

为了方便找到父节点,再加一个域来储存父结点信息 称为三叉链表

[外链图片转存失败(img-oesuPLIZ-1564736814706)(E:\javaclass\三叉链表.png)]

2.6 二叉树的实现

//定义二叉树结点类
class BinaryTreeBode{//二叉链表
    Object Date;
    Node left;
    Node right;
}

class BinaryTreeNode{//三叉链表
    Object value;
    Node left;
    Node right;
    Node parent;
}
2.6.1 二叉树的遍历算法

先序遍历DLR:(根 左子树 右子树)对于结点处理工作是在它的诸儿子结点被处理之前进行的

    /**
     * 二叉树的前序遍历  递归算法
     */
    @Override
    public void preOrderTraverse() {
        System.out.print("二叉树的前序遍历:");
        this.preOrderTraverse(root);
        System.out.println();
    }
    private void preOrderTraverse(BinaryNode root){
        if(root!=null){
            System.out.print(root.value+" ");
            preOrderTraverse(root.left);
            preOrderTraverse(root.right);
        }
    }

中序遍历LDR:(左子树 根 右子树)对于结点处理工作是在它的左子树被处理之后

    /**  
     * 二叉树的中序遍历  递归算法
     */
    @Override
    public void inOrderTraverse() {
        System.out.print("二叉树的中序遍历:");
         this.inOrderTraverse(root);
        System.out.println();
    }
    private void inOrderTraverse(BinaryNode root){
        if(root!=null){
            inOrderTraverse(root.left);
            System.out.print(root.value+" ");
            inOrderTraverse(root.right);
        }
    }
    /**
     * 非递归式中序遍历 借助栈
     */
    @Override
    public void inOrderByStack() {
        System.out.print ("中序非递归遍历:");
        Deque<BinaryNode> stack = new LinkedList<BinaryNode>();
        BinaryNode current = root;
        while (current!=null || !stack.isEmpty()){
            while (current!=null){
                stack.push(current);
                current = current.left;
            }
            if(!stack.isEmpty()){
                current=stack.pop();
                System.out.print(current.value+" ");
                current =current.right;
            }
        }
    }

后序遍历LRD:(左子树 右子树 根)对于结点处理工作是在它的诸儿子结点被处理之后进行的

 /**
     * 二叉树的后序遍历
     */

    @Override
    public void postOrderTraverse() {
        System.out.print("二叉树的后续遍历:");
        this.postOrderTraverse(root);
        System.out.println();
    }
    private void postOrderTraverse(BinaryNode root){
        if(root!=null){
            this.postOrderTraverse(root.left);
            this.postOrderTraverse(root.right);
            System.out.print(root.value+" ");
        }
    }

二叉树按层次遍历

    /**
     * 按照层次进行遍历  借助队列
     */
    @Override
    public void levelOrderByStack() {
        if(root!=null){
            System.out.print("二叉树按层次遍历:");
            //新建队列
            Queue<BinaryNode> queue = new LinkedList<BinaryNode>();
            ((LinkedList<BinaryNode>) queue).add(root);
            while (queue.size()!=0){
                int len =queue.size();
                for(int i=0;i<len;i++){
                    BinaryNode temp = queue.poll();
                    System.out.print(temp.value+" ");
                    if (temp.left!=null){
                        ((LinkedList<BinaryNode>) queue).add(temp.left);
                    }
                    if(temp.right!=null){
                        ((LinkedList<BinaryNode>) queue).add(temp.right);
                    }

                }
            }
            System.out.println();
        }else {
            System.out.println("二叉树为空");
        }
    }
}
2.6.2 二叉树的高度
    /**
     *二叉树的高度
     * @return
     */
    @Override
    public int getHeight() {
        System.out.print("二叉树的高度为: ");
        return getHeight(root);
    }
    private int getHeight(BinaryNode root){
        if(root!=null){
            int LHeight = this.getHeight(root.left);
            int RHeight = this.getHeight(root.right);
            return (LHeight>RHeight ? LHeight+1:RHeight+1);
        }else {
            return 0;
        }
    }
2.6.3 二叉树的结点个数
    /**
     * 获取二叉树的结点个数
     * @return
     */
    @Override
    public int size() {
        System.out.print("二叉树的结点个数为:");

        return this.size(root);
    }
    private int size(BinaryNode root){
        if(root!=null){
            int lSize = this.size(root.left);
            int rSize = this.size(root.right);
            return lSize+rSize+1;
        }else {
            return 0;
        }
    }
2.6.4 在二叉树中找指定的某一值
    /**
     * 在二叉树中查找某一指定值
     * @param value
     * @return
     */
    @Override
    public BinaryNode findKey(Object value) {
        return findKey(value,root);
    }
    private BinaryNode findKey(Object value,BinaryNode root){
        if (root==null){
            return null;
        }else if(root!=null && root.value==value){
            return root;
        }else {
            BinaryNode node1 = this.findKey(value,root.left);
            BinaryNode node2 = this.findKey(value,root.right);
            if(node1!=null&& node1.value==value){
                return node1;
            }else if(node2!=null && node2.value==value){
                return node2;
            }else {
                return null;
            }
        }
    }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值