二叉樹及其遍歷方法---python實現

github:代碼實現
本文算法均使用python3實現html


1. 二叉樹

1.1 二叉樹的定義

  二叉樹是一種特殊的樹,它具備如下特色
  (1)樹中每一個節點最多隻能有兩棵樹,即每一個節點的度最多爲2。
  (2)二叉樹的子樹有左右之分,即左子樹右子樹,次序不能顛倒。
  (3)二叉樹即便只有一個子樹時,也要區分是左子樹仍是右子樹。python

1.2 滿二叉樹

  滿二叉樹做爲一種特殊的二叉樹,它是指:全部的分支節點都存在左子樹與右子樹,而且全部的葉子節點都在同一層上。其特色有:
  (1)葉子節點只能出如今最下面一層
  (2)非葉子節點度必定是2
  (3)在一樣深度的二叉樹中,滿二叉樹的節點個數最多,節點個數爲: $ 2^h -1 $ ,其中 $ h $ 爲樹的深度。
git



1.3 徹底二叉樹

  若設二叉樹的深度爲 $ h $ ,除第 $ h $ 層外,其它各層 $ (1~h-1) $ 的結點數都達到最大個數,第 $ h $ 層全部的結點都連續集中在最左邊,這就是徹底二叉樹。其具備如下特色
  (1)葉子節點能夠出如今最後一層或倒數第二層。
  (2)最後一層的葉子節點必定集中在左部連續位置。
  (3)徹底二叉樹嚴格按層序編號。(可利用數組或列表進行實現,滿二叉樹同)
  (4)若一個節點爲葉子節點,那麼編號比其大的節點均爲葉子節點。
github




2. 二叉樹的相關性質

2.1 二叉樹性質

  (1)在非空二叉樹的 $ i $ 層上,至多有 $ 2^{i-1} $ 個節點 $ (i \geq 1) $ 。
  (2)在深度爲 $ h $ 的二叉樹上最多有 $ 2^h -1 $ 個節點 $(k \geq 1) $ 。
  (3)對於任何一棵非空的二叉樹,若是葉節點個數爲 $ n_0 $ ,度數爲 $ 2 $ 的節點個數爲 $ n_2 $ ,則有: $ n_0 = n_2 + 1 $ 。算法

2.1 徹底二叉樹性質

  (1)具備 $ n $ 個的結點的徹底二叉樹的深度爲 $ \log_2{n+1} $ 。.
  (2)若是有一顆有 $ n $ 個節點的徹底二叉樹的節點按層次序編號,對任一層的節點 $ i ,(1 \geq i \geq n)$ 有:
    (2.1)若是 $ i=1 $ ,則節點是二叉樹的根,無雙親,若是 $ i>1 $ ,則其雙親節點爲 $ \lfloor i/2 \rfloor $ 。
    (2.2)若是 $ 2i>n $ 那麼節點i沒有左孩子,不然其左孩子爲 $ 2i $ 。
    (2.3)若是 $ 2i+1>n $ 那麼節點沒有右孩子,不然右孩子爲 $ 2i+1 $ 。數組


3. 二叉樹的遍歷

  如下遍歷以該二叉樹爲例:
數據結構



3.1 前序遍歷

  思想:先訪問根節點,再先序遍歷左子樹,而後再先序遍歷右子樹。總的來講是根—左—右
  上圖先序遍歷結果爲爲:$ 1,2,4,8,9,5,3,6,7 $
  代碼以下:app

def PreOrder(self, root):
        '''打印二叉樹(先序)'''
        if root == None:
            return 
        print(root.val, end=' ')
        self.PreOrder(root.left)
        self.PreOrder(root.right)

3.2 中序遍歷

  思想:先中序訪問左子樹,而後訪問根,最後中序訪問右子樹。總的來講是左—根—右
  上圖中序遍歷結果爲爲:$ 8,4,9,2,5,1,6,3,7 $
  代碼以下:3d

def InOrder(self, root):
        '''中序打印'''
        if root == None:
            return
        self.InOrder(root.left)
        print(root.val, end=' ')
        self.InOrder(root.right)

3.3 後序遍歷

  思想:前後序訪問左子樹,而後後序訪問右子樹,最後訪問根。總的來講是左—右—根
  上圖後序遍歷結果爲爲:$ 8,9,4,5,2,6,7,3,1 $
  代碼以下:code

def BacOrder(self, root):
        '''後序打印'''
        if root == None:
            return
        self.BacOrder(root.left)
        self.BacOrder(root.right)
        print(root.val, end=' ')

3.4 層次遍歷(寬度優先遍歷)

  思想:利用隊列,依次將根,左子樹,右子樹存入隊列,按照隊列先進先出規則來實現層次遍歷。
  上圖後序遍歷結果爲爲:$ 1,2,3,4,5,6,7,8,9 $
  代碼以下:

def BFS(self, root):
        '''廣度優先'''
        if root == None:
            return
        # queue隊列,保存節點
        queue = []
        # res保存節點值,做爲結果
        #vals = []
        queue.append(root)

        while queue:
            # 拿出隊首節點
            currentNode = queue.pop(0)
            #vals.append(currentNode.val)
            print(currentNode.val, end=' ')
            if currentNode.left:
                queue.append(currentNode.left)
            if currentNode.right:
                queue.append(currentNode.right)
        #return vals

3.5 深度優先遍歷

  思想:利用,先將根入棧,再將根出棧,並將根的右子樹,左子樹存入棧,按照先進後出規則來實現深度優先遍歷。
  上圖後序遍歷結果爲爲:$ 1,2,4,8,9,5,3,6,7 $
  代碼以下:

def DFS(self, root):
        '''深度優先'''
        if root == None:
            return
        # 棧用來保存未訪問節點
        stack = []
        # vals保存節點值,做爲結果
        #vals = []
        stack.append(root)

        while stack:
            # 拿出棧頂節點
            currentNode = stack.pop()
            #vals.append(currentNode.val)
            print(currentNode.val, end=' ')
            if currentNode.right:
                stack.append(currentNode.right)
            if currentNode.left:
                stack.append(currentNode.left)          
        #return vals

3.6 代碼運行結果


引用及參考:
[1]《數據結構》李春葆著
[2] http://www.cnblogs.com/polly333/p/4740355.html

寫在最後:本文參考以上資料進行整合與總結,屬於原創,文章中可能出現理解不當的地方,如有所看法或異議可在下方評論,謝謝!
若需轉載請註明http://www.javashuo.com/article/p-plrhlcmv-gx.html

相關文章
相關標籤/搜索