二叉樹的基本性質、存儲方式與遍歷(Python實現)


二叉樹

二叉樹(Binary Tree)是樹的一種特殊形式,也就是每個節點之下最多擁有2個孩子,相應地若最多不超過M個孩子,那就成爲M叉樹,但實際上我們統稱爲多叉樹。對於二叉樹,常用的定理有四條:

  • 深度爲i的二叉樹最多含有2i1 個節點;
  • 第i層至多有2i1 個節點;
  • 對於任意一顆二叉樹,若其終端節點數爲n0 ,度爲2的節點數爲n2 ,則n0=n2+1 。證明如下:

    1n=n0+n1+n2
    2n=B+1B
    3B=n1+2n2
    由上述三式即可得出此定理。

  • 對於一棵完全二叉樹(除最後一層外每一層都爲滿二叉樹)而言,其葉子節點數具有以下關係:
    n0=n2nn+12n


二叉樹的存儲

在將二叉樹的存儲之前,我們先了解一下樹的存儲方式,常用輸的存儲方式有三種,在介紹之前,我們先把樹的例子放出來,再來看各種存儲方式的不同。
這裏寫圖片描述

  • 雙親表示法
    所謂雙親表示法就是會設置一個指示器來指向其雙親所在的位置。那麼我最終應當會存儲爲一個如下的數組:
    這裏寫圖片描述
    • 優點:Parent(T,x)可以很快找到雙親
    • 缺點:求節點的孩子時就必須遍歷整個結構
  • 孩子表示法
    所謂孩子表示法就是會在數據後面存儲其孩子節點,但也有兩種方式:
    • 方法一:
      這裏寫圖片描述
      但是這樣的方法比較浪費空間,因爲你並不知道多叉樹中每個節點一共有多少個孩子節點,而不存在的節點,也必須進行保存爲null;
    • 方法二:
      這裏寫圖片描述
      這樣的方法相對於第一種加入了degree的值,可以更節省空間,但是對樹進行插入或刪除等的操作的時候卻增加了複雜度。
  • 孩子兄弟表示法
    孩子兄弟表示法也是二叉樹的一種表示方法,數據的兩端分別存放其左節點的孩子和其兄弟節點。
    這裏寫圖片描述

其數據結構也可以很方便的定義:

typedef struct CSNode{
ElementType data;
Struct      CSNode *firstchild,*nextsibling;
} CSNode,*CSTree;

二叉樹的遍歷

所謂遍歷(Traversal)是指沿着某條搜索路線,依次對樹中每個結點均做一次且僅做一次訪問。訪問結點所做的操作依賴於具體的應用問題。
 遍歷是二叉樹上最重要的運算之一,是二叉樹上進行其它運算之基礎。
 從二叉樹的遞歸定義可知,一棵非空的二叉樹由根結點及左、右子樹這三個基本部分組成。因此,在任一給定結點上,可以按某種次序執行三個操作:
 (1)訪問結點本身(N),
 (2)遍歷該結點的左子樹(L),
 (3)遍歷該結點的右子樹(R)。

在訪問時要求必須先訪問左子樹再訪問右子樹,按照對根節點的訪問順序,二叉樹的遍歷分爲三種:先序中序和後序遍歷。
我們還是以剛纔的二叉樹作爲例子,那麼

  • 先序遍歷的結果應該爲:RACDBEF
  • 中序遍歷的結果應該爲:CADREBF
  • 後序遍歷的結果應該爲:CDAEFBR

用二叉鏈表做爲存儲結構,中序遍歷算法可描述爲:

 void InOrder(BinTree T)
        {
          if(T) { // 如果二叉樹非空
              InOrder(T->lchild);
              printf("%c",T->data); // 訪問結點
              InOrder(T->rchild);
            }
           } // InOrder

代碼實現

#! /usr/bin/env python                                                           
# -*-coding:utf-8 -*-                                                            
# Fuction: Create a binary search tree and tranversal in different way           
# Coder: Memory                                                                  
# Date: 2015-04-18                                                               


class treeNode(): 
    def __init__(self, data, left, right):                                       
        self.data = data                                                            
        self.left = left                                                            
        self.right = right 

class BTree:                                                                        
    def __init__(self):                                                             
        self.root = None                                                            

    def is_empty(self):                                                             
        if self.root is None:                                                       
            return True                                                          
        else:                                                                    
            return False                                                         

    def insert(self, data):                                                      
        r = self.root                                                            
        if r is None:                                                            
            self.root = treeNode(data, None, None)                                  
            return                                                                  
        while True:                                                                 
            # 比根結點小放在左邊                                                    
            if r.data > data:                                                       
                if r.left is None:                                                  
                    r.left = treeNode(data, None, None)                             
                    break                                                           
                else:                                                               
                    r = r.left                                                      
            else:                                                                   
                # 比根結點大放在右邊                                                
                if r.right is None:                                                 
                    r.right = treeNode(data, None, None)                            
                    break                                                           
                else:                                                               
                    r = r.right                                                     

    def traversal(self, root):                                                      
        if root is None:                                                            
            return                                                                  
        else:                                                                       
            # 先序遍歷                                                              
            print root.data                                                        
            self.traversal(root.left)    
            # 中序遍歷去掉下一行的註釋
            # print root.data                                           
            self.traversal(root.right)                                              
        # 後序遍歷同上
        # print root.data


if __name__ == '__main__':                                                          
    bt = BTree()                                      
    bt.insert(10)                                                                
    bt.insert(3)                                                                 
    bt.insert(12)                                                                
    bt.insert(6)                                                                 
    bt.insert(24)                                                                
    bt.insert(30)                                                                
    bt.insert(1)                                                                 
    bt.insert(5)  
    # 若用戶輸入的是數組,就一個個一個地輸入就好了。                                                               
    bt.traversal(bt.root)                                                        

二叉樹的應用和衍生有很多,比如:哈夫曼樹(最優二叉樹),二叉搜索樹等等。將在後續的博文中一一介紹。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章