数据结构之二叉树(JAVA实现)

目录

1. 什么是二叉树

2. 二叉树的性质

3. 二叉树的分类:

3.1. 满二叉树:

3.2. 完全二叉树

4. 二叉树的存储方式

4.1 顺序存储

4.2 链式存储

5. 二叉树的遍历

5.1 前序遍历:

5.2 中序遍历:

5.3 后序遍历

5.4 层次遍历


1. 什么是二叉树

满足以下两个条件的树称之为二叉树:

1. 本质上为有序树;

2. 每个结点的度不能超过2,即结点的度仅能为0,1,2。

2. 二叉树的性质

性质1:二叉树第i层的结点数最多为2^(i-1) (i>=1)。

性质2:深度为k的二叉树最多有2^k - 1个结点。

性质3:在任意一颗二叉树中,若终端结点(叶子结点)的个数为n0,度为2的结点树为n2,则n0=n2+1。

证明:设二叉树中度为1的结点数为n1,结点总数为n,则n = n0 + n1 +n2。同时,度为2的子结点共有2*n2个,度为1的子结点共有n1个,总结点数=子结点数+根结点 故n = n2*2 + n1 +1。两等式联立得出n0 = n2 +1。

3. 二叉树的分类:

3.1. 满二叉树:

若二叉树中除了叶子结点,每一个节点的度都为2,则称此二叉树为满二叉树。

满二叉树具有以下性质:

1. 满二叉树的第i层结点数为2^(i-1);

2. 深度为k的满二叉树有2^k - 1个结点,叶子结点有2^(k-1)个;

3. 具有n个结点的满二叉树的深度为log2(n+1);

4. 满二叉树中不存在度为1的结点,叶子结点仅存在在最底层。

3.2. 完全二叉树

若二叉树除了最后一层结点满足满二叉树的定义,且最后一层节点满足从左到右分布的次序,则该二叉树被称为完全二叉树。

数据结构之二叉树(JAVA实现)_第1张图片

完全二叉树除了满足普通二叉树的性质外,还满足以下性质:

1.  n个结点的完全二叉树的深度为⌊log2n⌋+1;

2. 将完全二叉树按照层次从左到右编号,

(1)当i > 1时,序号为i的结点的父结点为结点[i / 2];

(2)若2*i > n, 则序号为i的结点无左子女结点,否则该节点的左子女结点序号为2*i;

(3)若2*i+1>n,则序号为i的结点无右子女结点,否则该结点的右子女结点的序号为2*i+1。

4. 二叉树的存储方式

二叉树的存储方式有两种,顺序存储和链式存储。

4.1 顺序存储

顺序存储只适用于完全二叉树,若想存储普通二叉树,需要先将其转化为完全二叉树。满二叉树也是一种特殊的完全二叉树。

普通二叉树转化成完全二叉树的方法如下

数据结构之二叉树(JAVA实现)_第2张图片

 对于完全二叉树的存储,仅需对其从根节点开始仅需编号,使用数组存储编号即可。取出式依据完全二叉树由左到右分布的性质恢复即可。

数据结构之二叉树(JAVA实现)_第3张图片

4.2 链式存储

顺序存储会造成一定程度上的空间浪费,链式存储可以很好地解决这个问题。链式存储中每个结点包含三部分:左孩子结点、数据域和右孩子结点。

数据结构之二叉树(JAVA实现)_第4张图片

数据结构之二叉树(JAVA实现)_第5张图片

链式存储的JAVA实现为:

class tListnode{
    int val;
    tListnode leftChild;
    tListnode rightChild;
    tListnode(){

    }
    tListnode(int val){
        this.val = val;
    }
}

5. 二叉树的遍历

二叉树的遍历指从根结点出发,按照某种次序依次访问二叉树中所有的结点,每个结点被访问的次数有且仅有一次。

二叉树存在四种遍历方式:前序遍历、中序遍历、后序遍历和层次遍历

5.1 前序遍历:

前序遍历的思想是:(根左右)

1. 先访问根结点;

2. 访问当前结点的左子树;

3. 访问当前结点的右子树。

以上图为例,遍历顺序为:

A -> B -> D -> E -> C -> F -> G

JAVA实现:

1. 递归实现

    public static void preOrderTraversal(tListnode root){
        if(root==null){
            return;
        }
        System.out.println(root.val);
        preOrderTraversal(root.leftChild);
        preOrderTraversal(root.rightChild);
    }

2. 非递归实现

 基于栈的实现方式

    public static void preOrderTraversal(tListnode root){
        Stack stack = new Stack<>();
        tListnode cur = root;
        while (!stack.empty() || cur!=null){
            while (cur!=null){
                stack.push(cur);
                System.out.println(cur.val);
                cur = cur.leftChild;
            }
            cur = stack.pop();
            cur = cur.rightChild;
        }
    }

5.2 中序遍历:

中序遍历的思路是:(左根右)

遇到一个节点,先缓存,看其是否有左子节点,若有,则输出左节点,再输出原节点,最后输出右节点。

该二叉树的中序遍历顺序为:

D -> B -> E ->A -> F -> C -> G 

JAVA实现

1. 递归实现

    public static void inOrderTraversal(tListnode root){
        if(root==null){
            return;
        }
        inOrderTraversal(root.leftChild);
        System.out.println(root.val);
        inOrderTraversal(root.rightChild);
    }

2. 非递归实现

 基于栈的实现

    public static void inOrderTraversal(tListnode root){
        Stack stack = new Stack<>();
        tListnode cur= root;
        while(!stack.empty() || cur!=null){
            while (cur!=null){
                stack.push(cur);
                cur = cur.leftChild;
            }
            cur = stack.pop();
            System.out.println(cur.val);
            cur = cur.rightChild;
        }
    }

5.3 后序遍历

 后续遍历的思路是:(左右根)

遇到一个节点,先缓存,看它是否存在左子节点,有则输出,接着看其是否有右子结点,最后输出原节点。

该二叉树的后序遍历顺序为:

D -> E -> B -> F -> G -> C ->A

JAVA实现

1. 递归实现

    public static void postOrderTraversal(tListnode root){
        if(root==null){
            return;
        }
        postOrderTraversal(root.leftChild);
        postOrderTraversal(root.rightChild);
        System.out.println(root.val);
    }

2. 非递归实现

运用双栈 

 public static void postOrderTraversal(tListnode root){
        Stack stack = new Stack<>();
        Stack flag = new Stack<>();
        tListnode cur = root;
        int left = 1;
        int right = 2;
        while(!stack.empty()||cur!=null){
            while (cur!=null){
                stack.push(cur);
                flag.push(left);
                cur = cur.leftChild;
            }

            while(!stack.empty() && flag.peek()==right){
                flag.pop();
                System.out.println(stack.pop().val);
            }

            if(!stack.empty()&&flag.peek()==left){
                flag.pop();
                flag.push(right);
                cur = stack.peek().rightChild;
            }


        }
    }

5.4 层次遍历

按照二叉树的层次从上至下从左至右进行遍历。 

该二叉树的层次遍历顺序为:

A -> B -> C -> D -> E -> F ->G 

实现思路:

1. 根结点入队;

2. 根结点出队,若其存在左子结点,左子结点入队;若其存在右子结点,右子结点出队;

3. 重复1,2直至队列为空。

JAVA实现:

    public static void levelOrderTraversal(tListnode root){
        Queue queue = new LinkedList<>();
        queue.add(root);
        while (!queue.isEmpty()){
            tListnode cur = queue.poll();
            System.out.println(cur.val);
            if(cur.leftChild!=null){
                queue.add(cur.leftChild);
            }
            if(cur.rightChild!=null){
                queue.add(cur.rightChild);
            }
        }
    }

参考链接: 

​​​​​​什么是二叉树,二叉树及其性质详解

二叉树(Java实现) - 卑微芒果 - 博客园

java实现简单二叉树_公号:一条coding-CSDN博客_java 二叉树

二叉树的四种遍历方式 - 林海杜 - 博客园

你可能感兴趣的:(数据结构,java,数据结构,算法)