二叉樹(python3版)


1.二叉樹定義特點:

定義:二叉樹是n(n>=0)個結點的有限集合,該集合或者為空集(稱為空二叉樹),或者由一個根結點和兩棵互不相交的、分別稱為根結點的左子樹和右子樹的二叉樹組成。它是樹中的一種。

特點

1)樹中每個節點最多只能有兩棵樹,即每個節點的度最多為2。(ps;度也就是葉子的概念)

2)二叉樹的子樹有左右之分,即左子樹右子樹,次序不能顛倒。

3)二叉樹即使只有一個子樹時,也要區分是左子樹還是右子樹。

這里說一下特殊的幾種二叉樹:斜樹(左斜樹與右斜樹)、滿二叉樹、完全二叉樹。具體百度或者看(大話數據結構)。完全二叉樹可以理解為滿二叉樹少一點點。這兩種樹的深度比較容易計算。

1.1 滿二叉樹

  滿二叉樹作為一種特殊的二叉樹,它是指:所有的分支節點都存在左子樹與右子樹,並且所有的葉子節點都在同一層上。其特點有:
  (1)葉子節點只能出現在最下面一層
  (2)非葉子節點度一定是2
  (3)在同樣深度的二叉樹中,滿二叉樹的節點個數最多,節點個數為: 2h−1 ,其中 h 為樹的深度。


 

1.2 完全二叉樹

  若設二叉樹的深度為 h ,除第 h 層外,其它各層 (1h1)的結點數都達到最大個數,第 h 層所有的結點都連續集中在最左邊,這就是完全二叉樹。其具有以下特點
  (1)葉子節點可以出現在最后一層或倒數第二層。
  (2)最后一層的葉子節點一定集中在左部連續位置。
  (3)完全二叉樹嚴格按層序編號。(可利用數組或列表進行實現,滿二叉樹同)
  (4)若一個節點為葉子節點,那么編號比其大的節點均為葉子節點。


  這兩個的深度計算可以統稱為:!log 2n!+1,其中!x!這個符號定義為不大於x的意思。n是結點數。

2.二叉樹的建立

暫且看這個(以后碰到好的或者例子

3.二叉樹的五種遍歷

常見的五種遍歷:前序遍歷、中序遍歷、后序遍歷,層次遍歷,深度優先遍歷,看這里。 

以下遍歷以該二叉樹為例:


 

3.1 前序遍歷

  思想:先訪問根節點,再先序遍歷左子樹,然后再先序遍歷右子樹。總的來說是根—左—右
  上圖先序遍歷結果為為:1,2,4,8,9,5,3,6,71,2,4,8,9,5,3,6,7
  代碼如下:

    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,78,4,9,2,5,1,6,3,7
  代碼如下:

    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,18,9,4,5,2,6,7,3,1
  代碼如下:

    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,91,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,71,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 代碼運行結果

 

4.二叉樹一道劍指上的例題:

 

解題與調試全代碼:

 

#!/usr/bin/env python
#-*-coding:utf-8 -*-


class Node(object):
    def __init__(self, number):
        self.val = number
        self.left = None
        self.right = None


class Tree(object):
    lis = []

    def __init__(self):
        self.root = None

    def add(self, number):
        node = Node(number)

        if self.root == None:
            self.root = node
            Tree.lis.append(self.root)
        else:
            while True:
                point = Tree.lis[0]

                if point.left == None:
                    point.left = node
                    Tree.lis.append(point.left)
                    return
                elif point.right == None:
                    point.right = node
                    Tree.lis.append(point.right)
                    Tree.lis.pop(0)
                    return


    #先序遍歷函數
    def preOrderTrave(self, bt):
        if bt is not None:
            print(bt.val, end=" ")
            self.preOrderTrave(bt.left)
            self.preOrderTrave(bt.right)

def FindPath(root, expectNumber):
    # write code here
    if not root:
        return []
    if root and not root.left and not root.right and root.val == expectNumber:
        return [[root.val]]
    res = []
    print(root.val,expectNumber)
    left = FindPath(root.left, expectNumber-root.val)
    right = FindPath(root.right, expectNumber-root.val)
    for i in left+right:
        res.append([root.val]+i)
    return res


if __name__ == '__main__':
    t = Tree()
    data_list = [10,5,12,4,7]
    for x in data_list:
        t.add(x)
    t.preOrderTrave(t.root)

    # 以上是創建書中的二叉樹,下面是解題
    res = FindPath(t.root, 22)
    print(res)

 

 

 

 

 

 

 


免責聲明!

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



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