树(Tree)以及二叉树的遍历

树(tree)是一种抽象数据类型(ADT)或是实作这种抽象数据类型的数据结构,用来模拟具有树状结构性质的数据集合。它是由n(n>0)个有限节点组成一个具有层次关系的集合。把它叫做“树”是因为它看起来像一棵倒挂的树,也就是说它是根朝上,而叶朝下的。

树的特点:

  • 每个节点有零个或多个子节点;
  • 没有父节点的节点称为根节点;
  • 每一个非根节点有且只有一个父节点;
  • 除了根节点外,每个子节点可以分为多个不相交的子树;

常用到的术语:

  • 节点的度:一个节点含有的子树的个数称为该节点的度(上图 A->2 B->3 J->0)
  • 树的度:一棵树中,最大的节点的度称为树的度(上图B节点 3个度 最大)
  • 叶节点或终端节点:度为零的节点(上图A K O P)
  • 父亲节点或父节点:若一个节点含有子节点,则这个节点称为其子节点的父节点(上图A是BC的父节点 B是DEF的父节点)
  • 孩子节点或子节点:一个节点含有的子树的根节点称为该节点的子节点(上图BC是A的子节点 DEF是B的子节点)`;
  • 兄弟节点:具有相同父节点的节点互称为兄弟节点(上图BC DEF LM是相互的兄弟节点 )
  • 节点的层次:从根开始定义起,根为第1层,根的子节点为第2层,以此类推(上图A为第1层 BC第2层 DEFGH第三层 ...)
  • 树的高度或深度 :树中节点的最大层次(上图为5层)
  • 堂兄弟节点:父节点在同一层的节点互为堂兄弟(上图FG为堂兄弟节点)
  • 森林:由m(m>=0)棵互不相交的树的集合称为森林;

种类

  • 无序树:树中任意节点的子节点之间没有顺序关系,这种树称为无序树,也称为自由树;
  • 有序树:树中任意节点的子节点之间有顺序关系,这种树称为有序树;
  • 二叉树:每个节点最多含有两个子树的树称为二叉树;
    • 完全二叉树:对于一颗二叉树,假设其深度为d(d>1)。除了第d层外,其它各层的节点数目均已达最大值,且第d层所有节点从左向右连续地紧密排列,这样的二叉树被称为完全二叉树;
      • 满二叉树:所有叶节点都在最底层的完全二叉树(下图所示);
    • 平衡二叉树:当且仅当任何节点的两棵子树的高度差不大于1的二叉树;
    • 排序二叉树(二叉查找树)(英语:Binary Search Tree),也称二叉搜索树、有序二叉树);
  • ......
满二叉树
完全二叉树

二叉树的性质:

  1. 在二叉树的第i层上至多有2^(i-1)个结点。
  1. 深度为k的二叉树之多有(2^k)-1个结点。
  2. 对任何一棵二叉树T,如果其终端结点数为n0,度为2的结点树为n2,则n0=n2+1。
  3. 具有n个结点的完全二叉树的深度为(logn)+1。
  4. 如果对一棵有n个结点的完全二叉树的结点按层序号遍历,对任意结点i有:
    如果i=1,则结点i是二叉树的根,无双亲;如果i>1,则其双亲是结点i/2。
    如果2i>n,则结点i无左孩子;否则其左孩子是结点2i。
    如果2i+1>n,则结点i无右孩子;否则其右孩子是结点2i+1.

二叉树的表示方法:

双亲表示法
在每个结点中,附设一个指示器指示其双亲结点到链表中的位置。这种方式返回来找父节点不方便


双亲表示法

孩子表示法:也不助于查找父节点



孩子兄弟表示法:


比较好的表示方案:借用HashMap的思想,一个组head表示父节点,一组都是该父节点的子节点。

二叉树的遍历:

  • 前序遍历:若二叉树为空,则空操作返回,否则先访问根结点,然后前序遍历左子树,再前序遍历右子树。 中-->左-->右
前序遍历
  • 中序遍历:若二叉树为空,则空操作返回,否则从根结点开始,中序遍历根节点的左子树,然后访问根结点,再中序遍历根结点的右子树。左-->中-->右
中序排列
  • 后序遍历:若二叉树为空,则空操作返回,否则从左到右先叶子后节点的方式遍历访问左子树和右子树,最后是访问根结点。左-->右-->中
    后序遍历
  • 层次遍历:若二叉树为空,则空操作返回,否则从树的第一层开始,也就是根结点开始访问,从上而下逐层遍历,在同一层中,按从左到右的顺序对结点逐个访问。一层一层的遍历
层次遍历

JAVA实现一个简单的二叉树的遍历

public class BinaryTree {
    private TreeNode  root = null;
    
    public BinaryTree(){
        root = new TreeNode(1, "A");
    }
    
    /**
     * 构建二叉树
     *         A
     *     B       C
     * D      E        F
     */
    public void createBinaryTree(){
        TreeNode nodeB = new TreeNode(2, "B");
        TreeNode nodeC = new TreeNode(3, "C");
        TreeNode nodeD = new TreeNode(4, "D");
        TreeNode nodeE = new TreeNode(5, "E");
        TreeNode nodeF = new TreeNode(6, "F");
        root.leftChild = nodeB;
        root.rightChild = nodeC;
        nodeB.leftChild = nodeD;
        nodeB.rightChild = nodeE;
        nodeC.rightChild = nodeF;
    }
    
    /**
     * 求二叉树的高度
     * @author Administrator
     *
     */
    public int getHeight(){
        return getHeight(root);
    }
    
    private int getHeight(TreeNode node) {
        if(node == null){
            return 0;
        }else{
            int i = getHeight(node.leftChild);
            int j = getHeight(node.rightChild);
            return (i<j)?j+1:i+1;
        }
    }

    /**
     * 获取二叉树的结点数
     * @author Administrator
     *
     */
    public int getSize(){
        return getSize(root);
    }
    
    
    private int getSize(TreeNode node) {
        if(node == null){
            return 0;
        }else{
            return 1+getSize(node.leftChild)+getSize(node.rightChild);
        }
    }

    /**
     * 前序遍历——迭代
     * @author Administrator
     *
     */
    public void preOrder(TreeNode node){
        if(node == null){
            return;
        }else{
            System.out.println("preOrder data:"+node.getData());
            preOrder(node.leftChild);
            preOrder(node.rightChild);
        }
    }
    
    /**
     * 前序遍历——非迭代
     */
    
    public void nonRecOrder(TreeNode node){
        if(node == null){
            return;
        }
        Stack<TreeNode> stack = new Stack<TreeNode>();
        stack.push(node);
        while(!stack.isEmpty()){
            //出栈和进栈
            TreeNode n = stack.pop();//弹出根结点
            //压入子结点
            System.out.println("nonRecOrder data"+n.getData());
            if(n.rightChild!=null){
                stack.push(n.rightChild);
                
            }
            if(n.leftChild!=null){
                stack.push(n.leftChild);
            }
        }
    }
    /**
     * 中序遍历——迭代
     * @author Administrator
     *
     */
    public void midOrder(TreeNode node){
        if(node == null){
            return;
        }else{
            midOrder(node.leftChild);
            System.out.println("midOrder data:"+node.getData());
            midOrder(node.rightChild);
        }
    }
    
    /**
     * 后序遍历——迭代
     * @author Administrator
     *
     */
    public void postOrder(TreeNode node){
        if(node == null){
            return;
        }else{
            postOrder(node.leftChild);
            postOrder(node.rightChild);
            System.out.println("postOrder data:"+node.getData());
        }
    }
    public class TreeNode{
        private int index;
        private String data;
        private TreeNode leftChild;
        private TreeNode rightChild;
        
    
        public int getIndex() {
            return index;
        }


        public void setIndex(int index) {
            this.index = index;
        }


        public String getData() {
            return data;
        }


        public void setData(String data) {
            this.data = data;
        }


        public TreeNode(int index,String data){
            this.index = index;
            this.data = data;
            this.leftChild = null;
            this.rightChild = null;
        }
    }
    
    
    public static void main(String[] args){
        BinaryTree binaryTree = new BinaryTree();
        binaryTree.createBinaryTree();
        int height = binaryTree.getHeight();
        System.out.println("treeHeihgt:"+height);
        int size = binaryTree.getSize();
        System.out.println("treeSize:"+size);
//      binaryTree.preOrder(binaryTree.root);
//      binaryTree.midOrder(binaryTree.root);
//      binaryTree.postOrder(binaryTree.root);
        binaryTree.nonRecOrder(binaryTree.root);
    }
}


水平有限,文中有什么不对或者有什么建议希望大家能够指出,谢谢!

推荐阅读更多精彩内容

  • B树的定义 一棵m阶的B树满足下列条件: 树中每个结点至多有m个孩子。 除根结点和叶子结点外,其它每个结点至少有m...
    笨尛孩你谁啊阅读 5,568评论 0 22
  • 树的概述 树是一种非常常用的数据结构,树与前面介绍的线性表,栈,队列等线性结构不同,树是一种非线性结构 1.树的定...
    Jack921阅读 3,147评论 1 30
  • 数据结构和算法--二叉树的实现 几种二叉树 1、二叉树 和普通的树相比,二叉树有如下特点: 每个结点最多只有两棵子...
    sunhaiyu阅读 3,340评论 0 13
  • 四、树与二叉树 1. 二叉树的顺序存储结构 二叉树的顺序存储就是用数组存储二叉树。二叉树的每个结点在顺序存储中都有...
    MinoyJet阅读 731评论 0 7
  • 这个周末我在网上找电影准备吐槽一番 看到这部屌炸天的电影《囧贼》 不为别的,只是因为看到有个“囧”字 以为会跟泰囧...
    虾聊阅读 322评论 0 51