樹(Tree)以及二叉樹的遍歷

樹(tree)是一種抽象數(shù)據(jù)類型(ADT)或是實作這種抽象數(shù)據(jù)類型的數(shù)據(jù)結(jié)構(gòu),用來模擬具有樹狀結(jié)構(gòu)性質(zhì)的數(shù)據(jù)集合。它是由n(n>0)個有限節(jié)點組成一個具有層次關(guān)系的集合。把它叫做“樹”是因為它看起來像一棵倒掛的樹,也就是說它是根朝上,而葉朝下的。

樹的特點:

  • 每個節(jié)點有零個或多個子節(jié)點;
  • 沒有父節(jié)點的節(jié)點稱為根節(jié)點;
  • 每一個非根節(jié)點有且只有一個父節(jié)點;
  • 除了根節(jié)點外,每個子節(jié)點可以分為多個不相交的子樹;

常用到的術(shù)語:

  • 節(jié)點的度:一個節(jié)點含有的子樹的個數(shù)稱為該節(jié)點的度(上圖 A->2 B->3 J->0)
  • 樹的度:一棵樹中,最大的節(jié)點的度稱為樹的度(上圖B節(jié)點 3個度 最大)
  • 葉節(jié)點或終端節(jié)點:度為零的節(jié)點(上圖A K O P)
  • 父親節(jié)點或父節(jié)點:若一個節(jié)點含有子節(jié)點,則這個節(jié)點稱為其子節(jié)點的父節(jié)點(上圖A是BC的父節(jié)點 B是DEF的父節(jié)點)
  • 孩子節(jié)點或子節(jié)點:一個節(jié)點含有的子樹的根節(jié)點稱為該節(jié)點的子節(jié)點(上圖BC是A的子節(jié)點 DEF是B的子節(jié)點)`;
  • 兄弟節(jié)點:具有相同父節(jié)點的節(jié)點互稱為兄弟節(jié)點(上圖BC DEF LM是相互的兄弟節(jié)點 )
  • 節(jié)點的層次:從根開始定義起,根為第1層,根的子節(jié)點為第2層,以此類推(上圖A為第1層 BC第2層 DEFGH第三層 ...)
  • 樹的高度或深度 :樹中節(jié)點的最大層次(上圖為5層)
  • 堂兄弟節(jié)點:父節(jié)點在同一層的節(jié)點互為堂兄弟(上圖FG為堂兄弟節(jié)點)
  • 森林:由m(m>=0)棵互不相交的樹的集合稱為森林;

種類

  • 無序樹:樹中任意節(jié)點的子節(jié)點之間沒有順序關(guān)系,這種樹稱為無序樹,也稱為自由樹;
  • 有序樹:樹中任意節(jié)點的子節(jié)點之間有順序關(guān)系,這種樹稱為有序樹;
  • 二叉樹:每個節(jié)點最多含有兩個子樹的樹稱為二叉樹;
    • 完全二叉樹:對于一顆二叉樹,假設其深度為d(d>1)。除了第d層外,其它各層的節(jié)點數(shù)目均已達最大值,且第d層所有節(jié)點從左向右連續(xù)地緊密排列,這樣的二叉樹被稱為完全二叉樹;
      • 滿二叉樹:所有葉節(jié)點都在最底層的完全二叉樹(下圖所示);
    • 平衡二叉樹:當且僅當任何節(jié)點的兩棵子樹的高度差不大于1的二叉樹;
    • 排序二叉樹(二叉查找樹)(英語:Binary Search Tree),也稱二叉搜索樹、有序二叉樹);
  • ......
滿二叉樹
完全二叉樹

二叉樹的性質(zhì):

  1. 在二叉樹的第i層上至多有2^(i-1)個結(jié)點。
  1. 深度為k的二叉樹之多有(2^k)-1個結(jié)點。
  2. 對任何一棵二叉樹T,如果其終端結(jié)點數(shù)為n0,度為2的結(jié)點樹為n2,則n0=n2+1。
  3. 具有n個結(jié)點的完全二叉樹的深度為(logn)+1。
  4. 如果對一棵有n個結(jié)點的完全二叉樹的結(jié)點按層序號遍歷,對任意結(jié)點i有:
    如果i=1,則結(jié)點i是二叉樹的根,無雙親;如果i>1,則其雙親是結(jié)點i/2。
    如果2i>n,則結(jié)點i無左孩子;否則其左孩子是結(jié)點2i。
    如果2i+1>n,則結(jié)點i無右孩子;否則其右孩子是結(jié)點2i+1.

二叉樹的表示方法:

雙親表示法
在每個結(jié)點中,附設一個指示器指示其雙親結(jié)點到鏈表中的位置。這種方式返回來找父節(jié)點不方便


雙親表示法

孩子表示法:也不助于查找父節(jié)點



孩子兄弟表示法:


比較好的表示方案:借用HashMap的思想,一個組head表示父節(jié)點,一組都是該父節(jié)點的子節(jié)點。

二叉樹的遍歷:

  • 前序遍歷:若二叉樹為空,則空操作返回,否則先訪問根結(jié)點,然后前序遍歷左子樹,再前序遍歷右子樹。 中-->左-->右
前序遍歷
  • 中序遍歷:若二叉樹為空,則空操作返回,否則從根結(jié)點開始,中序遍歷根節(jié)點的左子樹,然后訪問根結(jié)點,再中序遍歷根結(jié)點的右子樹。左-->中-->右
中序排列
  • 后序遍歷:若二叉樹為空,則空操作返回,否則從左到右先葉子后節(jié)點的方式遍歷訪問左子樹和右子樹,最后是訪問根結(jié)點。左-->右-->中
    后序遍歷
  • 層次遍歷:若二叉樹為空,則空操作返回,否則從樹的第一層開始,也就是根結(jié)點開始訪問,從上而下逐層遍歷,在同一層中,按從左到右的順序?qū)Y(jié)點逐個訪問。一層一層的遍歷
層次遍歷

JAVA實現(xiàn)一個簡單的二叉樹的遍歷

public class BinaryTree {
    private TreeNode  root = null;
    
    public BinaryTree(){
        root = new TreeNode(1, "A");
    }
    
    /**
     * 構(gòu)建二叉樹
     *         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;
        }
    }

    /**
     * 獲取二叉樹的結(jié)點數(shù)
     * @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();//彈出根結(jié)點
            //壓入子結(jié)點
            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);
    }
}


水平有限,文中有什么不對或者有什么建議希望大家能夠指出,謝謝!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內(nèi)容

  • B樹的定義 一棵m階的B樹滿足下列條件: 樹中每個結(jié)點至多有m個孩子。 除根結(jié)點和葉子結(jié)點外,其它每個結(jié)點至少有m...
    文檔隨手記閱讀 13,345評論 0 25
  • 樹的概述 樹是一種非常常用的數(shù)據(jù)結(jié)構(gòu),樹與前面介紹的線性表,棧,隊列等線性結(jié)構(gòu)不同,樹是一種非線性結(jié)構(gòu) 1.樹的定...
    Jack921閱讀 4,489評論 1 31
  • 數(shù)據(jù)結(jié)構(gòu)和算法--二叉樹的實現(xiàn) 幾種二叉樹 1、二叉樹 和普通的樹相比,二叉樹有如下特點: 每個結(jié)點最多只有兩棵子...
    sunhaiyu閱讀 6,529評論 0 14
  • 四、樹與二叉樹 1. 二叉樹的順序存儲結(jié)構(gòu) 二叉樹的順序存儲就是用數(shù)組存儲二叉樹。二叉樹的每個結(jié)點在順序存儲中都有...
    MinoyJet閱讀 1,585評論 0 7
  • 這個周末我在網(wǎng)上找電影準備吐槽一番 看到這部屌炸天的電影《囧賊》 不為別的,只是因為看到有個“囧”字 以為會跟泰囧...
    蝦聊閱讀 797評論 0 51