java數據結構之二叉樹的定義和遞歸實現


定義
最多有兩棵子樹的有序樹,稱為二叉樹。二叉樹是一種特殊的樹。
遞歸定義:二叉樹是n(n>=0)個有限結點構成的集合。N=0稱為空二叉樹;n>0的二叉樹由一個根結點和兩互不相交的,分別稱為左子樹和右子樹的二叉樹構成。
二叉樹中任何結點的第1個子樹稱為其左子樹,左子樹的根稱為該結點的左孩子;二叉樹中任何結點的第2個子樹稱為其右子樹,左子樹的根稱為該結點的右孩子。如下圖是一個二叉樹:

 


滿二叉樹和完全二叉樹
在一棵二叉樹中,如果所有分支結點都存在左子樹和右子樹,並且葉子結點都在同一層上,這樣的二叉樹稱作滿二叉樹。一棵深度為k且由2k-1個結點的二叉樹稱為滿二叉樹。
如果一棵具有n個結點的二叉樹的結構與滿二叉樹的前n個結點的結構相同,這樣的二叉樹稱作完全二叉樹。


基本性質
這里規定二叉樹的根結點的層次為1。
性質1:則二叉樹的第i 層最多有2i-1個結點(在此二叉樹的層次從1開始,i≥1)
性質2:深度為k的二叉樹最多有2k-1個結點。(k≥1)
性質3:對任何一棵二叉樹T, 如果其葉結點個數為n0, 度為2的非葉結點個數為n2, 則有
             n0 = n2 + 1

性質4:具有 n(n>0)個結點的完全二叉樹的深度為⎣log2n⎦+1;⎦x⎦表示不超過x的最大整數。
性質5:如果對一棵有n個結點的完全二叉樹的結點按層序編號(從第1層到第⎣l og2n⎦ +1層,每層從左到右),則對任一結點i(1≤i≤n),有:
(1)如果i=1,則結點i無雙親,是二叉樹的根;如果i>1,則其雙親是結點⎣i/2⎦。
(2) 如果2i<=n, 則結點i的左孩子結點是2i;否則,結點i為葉子結點,無左孩子結點。
(3)如果2i+1<=n,則結點i的右孩子是結點2i+1; 否則,結點i為葉子結點,無右孩子結點。


抽象數據類型
數據元素:具有相同特性的數據元素的集合。
結構關系:樹中數據元素間的結構關系由二叉樹的定義確定。
基本操作:樹的主要操作有
(1)創建樹IntTree(&T)
(2)銷毀樹DestroyTree(&T)
(3)構造樹CreatTree(&T,deinition)
(4)置空樹ClearTree(&T)
(5)判空樹TreeEmpty(T)
(6)求樹的深度TreeDepth(T)
(7)獲得樹根Root(T)
(8)獲取結點Value(T,cur_e,&e),將樹中結點cur_e存入e單元中。
(9)數據賦值Assign(T,cur_e,value),將結點value,賦值於樹T的結點cur_e中。
(10)獲得雙親Parent(T,cur_e),返回樹T中結點cur_e的雙親結點。
(11)獲得最左孩子LeftChild(T,cur_e),返回樹T中結點cur_e的最左孩子。
(12)獲得右兄弟RightSibling(T,cur_e),返回樹T中結點cur_e的右兄弟。
(13)插入子樹InsertChild(&T,&p,i,c),將樹c插入到樹T中p指向結點的第i個子樹之前。
(14)刪除子樹DeleteChild(&T,&p,i),刪除樹T中p指向結點的第i個子樹。
(15)遍歷樹TraverseTree(T,visit())

二叉樹的實現
二叉樹接口BTree
    package datastructure.tree.btree;  
      
    public interface BTree {  
        /**
         * 添加左子樹
         * @param lChild 左子樹
         */  
        public void addLeftTree(BTree lChild);  
        /**
         * 添加右子樹
         * @param rchild 右子樹
         */  
        public void addRightTree(BTree rchild) ;  
        /**
         * 置空樹
         */  
        public void clearTree();  
        /**
         * 求樹的深度
         * @return 樹的深度
         */  
        public int dept();  
        /**
         * 求左孩子 結點
         * @return
         */  
        public BTree getLeftChild();  
          
        /**
         * 求右孩子結點
         * @return
         */  
        public BTree getRightChild();  
        /**
         * 獲得根結點的數據
         * @return
         */  
        public Object getRootData();  
        /**
         * 是否有左子樹
         * @return
         */  
        public boolean hasLeftTree();  
        /**
         * 是否有右子樹
         * @return
         */  
        public boolean hasRightTree();  
        /**
         * 判斷是否為空樹
         * @return 如果為空,返回true,否則返回false
         */  
        public boolean isEmpty();  
        /**
         * 判斷是否為葉子結點
         * @return
         */  
        public boolean isLeaf();  
        /**
         * 刪除左子樹
         */  
        public void removeLeftChild();  
        /**
         * 刪除右子樹
         */  
        public void removeRightChild();  
        /**
         * 獲得樹根
         * @return 樹的根
         */  
        public BTree root();  
        /**
         * 設置根結點的數據
         */  
        public void setRootData(Object data);  
        /**
         * 求結點數
         * @return 結點的個數  
         */  
        public int size();  
    }  


二叉鏈表的實現
    package datastructure.tree.btree;  
      
    public class LinkBTree implements BTree {  
        private Object data;  
        private BTree lChild;  
        private BTree rChild;  
          
        public LinkBTree() {  
            this.clearTree();  
        }  
        public LinkBTree(Object data) {  
            this.data = data;  
            this.lChild = null;  
            this.rChild = null;  
        }  
        @Override  
        public void addLeftTree(BTree lChild) {  
            this.lChild = lChild;  
        }  
      
        @Override  
        public void addRightTree(BTree rChild) {  
            this.rChild = rChild;  
        }  
      
        @Override  
        public void clearTree() {  
            this.data = null;  
            this.lChild = null;  
            this.rChild = null;  
        }  
      
        @Override  
        public int dept() {  
            return dept(this);  
        }  
          
        private int dept(BTree btree) {  
            if(btree.isEmpty()) {  
                return 0;  
            }else if(btree.isLeaf()) {  
                return 1;  
            } else {  
                if(btree.getLeftChild() == null) {  
                    return dept(btree.getRightChild()) + 1;  
                } else if(btree.getRightChild() == null) {  
                    return dept(btree.getLeftChild()) + 1;  
                } else {  
                    return Math.max(dept(btree.getLeftChild()), dept(btree.getRightChild()))+1;  
                }  
            }  
        }  
      
        @Override  
        public BTree getLeftChild() {  
            return lChild;  
        }  
      
      
        @Override  
        public BTree getRightChild() {  
            return rChild;  
        }  
      
        @Override  
        public Object getRootData() {  
            return data;  
        }  
      
        @Override  
        public boolean hasLeftTree() {  
            if(lChild != null)  
                return true;  
            return false;  
        }  
      
        @Override  
        public boolean hasRightTree() {  
            if(rChild != null)  
                return true;  
            return false;  
        }  
      
        @Override  
        public boolean isEmpty() {  
            if((lChild == null && rChild == null && data == null) || this == null) {  
                return true;  
            }  
            return false;  
        }  
          
        @Override  
        public boolean isLeaf() {  
            if(lChild == null && rChild == null) {  
                return true;  
            }  
            return false;  
        }  
      
        @Override  
        public void removeLeftChild() {  
            lChild = null;  
        }  
      
        @Override  
        public void removeRightChild() {  
            rChild = null;  
        }  
        @Override  
        public BTree root() {  
            return this;  
        }  
        @Override  
        public void setRootData(Object data) {  
            this.data = data;  
        }  
        @Override  
        public int size() {  
            return size(this);  
        }  
        private int size(BTree btree) {  
            if(btree == null)   
                return 0;  
            else if(btree.isLeaf())   
                return 1;  
            else {  
                if(btree.getLeftChild() == null) {  
                    return size(btree.getRightChild()) + 1;  
                } else if(btree.getRightChild() == null) {  
                    return size(btree.getLeftChild()) + 1;  
                } else {  
                    return size(btree.getLeftChild()) + size(btree.getRightChild()) + 1;  
                }  
            }   
        }  
          
      
    }  

二叉樹的遍歷
 二叉樹的遍歷是指按照一定的次序訪問樹中所有結點,並且每個結點只被訪問一次的過程。通常的遍歷有三種方式,分別是:前序遍歷、中序遍歷和后序遍歷,假設根結點、左孩子結點和右孩子結點分別用D、R、L表示,則前序遍歷、中序遍歷和后序遍歷的順序分別為DLR、LDR、LRD。所謂訪問某結點,一般指對結點中的數據進行某種操作。所以,我們可以定義一個對結點中的數據進行操作的接口Visit,讓所有遍歷樹的類實現這個接口。
Visit接口:

    package datastructure.tree;  
    /**
     * 對結點進行操作的接口
     * @author Administrator
     *
     */  
    public interface Visit {  
        /**
         * 對結點進行某種操作
         * @param btree 樹的結點
         */  
        public void visit(BTree btree);  
    }  


遍歷二叉樹

    package datastructure.tree;  
    /**
     * 遍歷二叉樹
     * @author Administrator
     *
     */  
    public class OrderBTree implements Visit{  
        /**
         * 前序遍歷
         * @param root 根結點
         */  
        public void preOrder(BTree root) {  
            visit(root);  
            if(root.getLeftChild() != null) {  
                preOrder(root.getLeftChild());  
            }  
            if(root.getRightChild() != null) {  
                preOrder(root.getRightChild());  
            }  
        }  
        /**
         * 中序遍歷
         * @param root 根結點
         */  
        public void inOrder(BTree root) {  
            if(root.getLeftChild() != null)  
                inOrder(root.getLeftChild());  
            visit(root);  
            if(root.getRightChild() != null) {  
                //System.out.println("true");  
                inOrder(root.getRightChild());  
            }  
        }  
        /**
         * 后序遍歷
         * @param root 根結點
         */  
        public void postOrder(BTree root) {  
            if(root.getLeftChild() != null)  
                postOrder(root.getLeftChild());  
            if(root.getRightChild() != null)  
                postOrder(root.getRightChild());  
            visit(root);  
        }  
      
        @Override  
        public void visit(BTree btree) {  
            System.out.print(btree.getRootData() + "\t");  
        }  
      
    }  

二叉樹的測試

    package datastructure.tree;  
    /**
     * 測試二叉樹
     * @author Administrator
     *
     */  
    public class BTreeTest {  
        public static void main(String args[]) {  
            BTree btree = new LinkBTree('A');  
            BTree bt1, bt2, bt3, bt4;  
            bt1 = new LinkBTree('B');  
            btree.addLeftTree(bt1);  
            bt2 = new LinkBTree('D');  
            bt1.addLeftTree(bt2);  
              
            bt3 =  new LinkBTree('C');  
            btree.addRightTree(bt3);  
            bt4 =  new LinkBTree('E');  
            bt3.addLeftTree(bt4);  
            bt4 =  new LinkBTree('F');  
            bt3.addRightTree(bt4);  
              
            System.out.println("樹的深度:" + btree.dept());  
            System.out.println("樹的結點數:" + btree.size());  
            System.out.println("是否為空樹:" + btree.isEmpty());  
            System.out.println("是否為葉子結點:" + btree.isLeaf());  
            System.out.println("最左下邊結點是否為葉子結點:" + btree.getRightChild().getRightChild().isLeaf());  
            System.out.println("root結點:" + btree.root());  
              
            OrderBTree order = new OrderBTree();  
            System.out.println("\n前序遍歷:");  
            order.preOrder(btree);  
            System.out.println("\n中序遍歷:");  
            order.inOrder(btree);  
            System.out.println("\n后序遍歷:");  
            order.postOrder(btree);  
              
            btree.removeLeftChild();  
            System.out.println("\n刪除左子樹后中序遍歷為:");  
            order.inOrder(btree);  
        }  
    }  

結果如下:
樹的深度:3
樹的結點數:6
是否為空樹:false
是否為葉子結點:false
最左下邊結點是否為葉子結點:true
root結點:datastructure.tree.LinkBTree@dc8569

前序遍歷:
A B DCEF
中序遍歷:
D B AECF
后序遍歷:
D B EFCA
刪除左子樹后中序遍歷為:
A E CF

轉載至:http://blog.csdn.net/luoweifu/article/details/9077521


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM