资讯专栏INFORMATION COLUMN

二叉树

FrancisSoung / 1621人阅读

摘要:完全二叉树深度为有个结点的二叉树,其每个结点的编号与深度为的满二叉树中编号从的结点一一对应叶子结点只可能在层数最大的两层上出现。

二叉树的性质
(1) 在二叉树的第 i 层最多有 2^i-1 个结点 (i>=1).
(2) 深度为 k 的二叉树最多有 2^k - 1 个结点 (k>=1).
(3) 对任何一棵二叉树,如果其叶子结点数为 n0, 度为 2 的结点数为 n2, 则 n0 = n2 + 1. 原因:设度为 1 的结点数为 n1, 则结点总数 n = n0 + n1 + n2; 设分支数为 B, 由于只有根结点没有分支进入, 因此 n = B + 1; 由于分支都是从度为 1 或 2 的结点引出的, 因此 B = n1 + 2 * n2; 联立上述等式可得 n0 = n2 + 1.

满二叉树
深度为 k 且有 2^k - 1 个结点的二叉树。

完全二叉树
(1) 深度为 k、有 n 个结点的二叉树,其每个结点的编号与深度为 k 的满二叉树中编号从 1~n 的结点一一对应.
(2) 叶子结点只可能在层数最大的两层上出现。
(3) 对任意结点,若其右下分支下的子孙的最大层次为 lv, 则其左下分支下的子孙的最大层次必为 lv / lv + 1
(4) 结点数为 n 的完全二叉树,其深度为 logn + 1.
(5) 结点数为 n 的完全二叉树,结点按层编号,则对编号为 i 的结点 (1 <= i <= n):

     若 i==1, 则结点 i 为二叉树的根, 无双亲;
     若 i>1 , 则结点 i 的双亲是 i/2;
     若 2i>n, 则结点 i 无左孩子, 否则其左孩子是结点 2i;
     若 2i+1>n, 则结点 i 无右孩子, 否则其右孩子是结点 2i+1.

存储结构
二叉链表的存储表示

class BiTNode {
    int data;
    BiTNode lchild, rchild;
}

先序遍历: 根-左-右
(1) 递归

    void preOrderRecursive(BiTNode tree) {
        if(tree!=null) {
            visit(tree);
            preOrderRecursive(tree.lchild);
            preOrderRecursive(tree.rchild);
        }
    }

(2) 非递归
:初始化栈,并且树的根结点进栈;每次循环都将栈顶结点出栈并打印,然后先后将该结点的右子结点左子结点进栈,直到栈为空。

    void preOrder(BiTNode tree) {
        if(tree==null) {
            return;
        }
        LinkedList stack = new LinkedList();
        stack.push(tree);
        while(stack.size()>0) {
            BiTNode node = stack.pop();
            visit(node);
            if(node.rchild!=null) {
                stack.push(node.rchild);
            }
            if(node.lchild!=null) {
                stack.push(node.lchild);
            }
        }
    }

中序遍历: 左-根-右
(1) 递归

    void inOrderRecursive(BiTNode tree) {
        if(tree!=null) {
            inOrderRecursive(tree.lchild);
            visit(tree);
            inOrderRecursive(tree.rchild);
        }
    }

(2) 非递归
:初始化栈,并且树的根结点进栈。每次循环中,首先向左走到尽头并将访问到的每个结点进栈,此时栈顶存在空指针,需要将其出栈,然后将栈顶结点出栈,并访问该结点,同时将该结点的右孩子进栈;直到栈为空。

    void inOrder(BiTNode tree) {
        if(tree==null) {
            return;
        }
        LinkedList stack = new LinkedList();
        stack.push(tree);
        while(stack.size()>0) {
            BiTNode node = stack.peek();
            while(node!=null) {
                stack.push(node.lchild);
                node = stack.peek();
            }
            stack.pop();
            if(stack.size()>0) {
                node = stack.pop();
                visit(node);
                stack.push(node.rchild);
            }
        }
    }

:初始化栈。每次循环中,若当前结点不空时将该结点进栈,并遍历其左子树;否则将该结点出栈并访问该结点,同时将该结点的右孩子进栈;直到当前结点为空并且栈为空。

    void inOrder(BiTNode tree) {
        if(tree==null) {
            return;
        }
        LinkedList stack = new LinkedList();
        BiTNode node = tree;
        while(node!=null || stack.size()>0) {
            if(node!=null) {
                stack.push(node);
                node = node.lchild;
            } else {
                node = stack.pop();
                visit(node);
                node = node.rchild;
            }
        }
    }

后序遍历: 左-右-根
(1) 递归

    void postOrderRecursive(BiTNode tree) {
        if(tree!=null) {
            postOrderRecursive(tree.lchild);
            postOrderRecursive(tree.rchild);
            visit(tree);
        }
    }

(2) 非递归
:为每个结点增加一个访问标志位 visited; 初始化栈。每次循环中,首先将根结点及其左子树进栈,并将每个结点的访问标志位置为 true,使得栈顶为最左边的左孩子,栈底为根结点;然后将栈顶结点出栈,若该结点的访问标志位为 true, 即该结点被访问了一次,要将该结点重新进栈, 并置其访问标志位为 false, 再访问该结点的右孩子;若该结点的访问标志位为 false, 即该结点被访问了两次, 要输出该结点的值,并将当前结点置为空;直到当前结点为空而且栈为空。

    void postOrder(BiTNode tree) {
        if(tree==null) {
            return;
        }
        List stack = new LinkedList();
        BiTNode node = tree;
        while(node!=null || stack.size()>0) {
            while(node!=null) {
                node.visited = true;
                stack.push(node);
                node = node.lchild;
            }
            if(stack.size()>0) {
                BiTNode temp = stack.pop();
                if(temp.visited) {
                    temp.visited = false;
                    stack.push(temp);
                    node = temp.rchild;
                } else {
                    visit(temp);
                    node = null;
                }
            }
        }
    }

层次遍历

    void levelOrder(BiTNode tree) {
        if(tree==null) {
            return;
        }
        LinkedList queue = new LinkedList();
        queue.add(tree);
        while(queue.size()>0) {
            BiTNode node = queue.remove();
            visit(node);
            if(node.lchild!=null) {
                queue.add(node.lchild);
            }
            if(node.rchild!=null) {
                queue.add(node.rchild);
            }
        }
    }

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/69518.html

相关文章

  • Java数据结构与算法——叉树及操作(包括叉树遍历)

    摘要:本篇主要介绍二叉树的概念二叉树的表示二叉树的操作三种遍历方式实现求二叉树的子树求节点的父节点二叉树高度,可能是考试中的,也可能是面试中的。通常二叉树的遍历根据根节点的遍历次序分为先根遍历中根遍历后根遍历。 声明:码字不易,转载请注明出处,欢迎文章下方讨论交流。 前言:Java数据结构与算法专题会不定时更新,欢迎各位读者监督。本篇主要介绍二叉树的概念、二叉树的表示、二叉树的操作(三种遍历...

    muddyway 评论0 收藏0
  • js数据结构和算法(三)叉树

    摘要:同样结点树的二叉树,完全二叉树的深度最小。二叉树每个结点最多有两个孩子,所以为它设计一个数据域和两个指针域是比较自然的想法,我们称这样的链表叫做二叉链表。 二叉树的概念 二叉树(Binary Tree)是n(n>=0)个结点的有限集合,该集合或者为空集(空二叉树),或者由一个根结点和两棵互不相交的、分别称为根结点的左子树和右子树的二叉树组成。 showImg(https://seg...

    DesGemini 评论0 收藏0
  • 【数据结构初阶之叉树】:叉树相关的性质和经典的习题(用C语言实现,附图详解)

    摘要:当集合为空时,称该二叉树为空二叉树。也就是说,如果一个二叉树的层数为,且结点总数是,则它就是满二叉树。完全二叉树完全二叉树是效率很高的数据结构,完全二叉树是由满二叉树而引出来的。 ...

    Martin91 评论0 收藏0

发表评论

0条评论

FrancisSoung

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<