Python 數據結構之二叉樹的實現

1、基本概念

二叉樹 是一種簡單的樹形結構,是每個節點最多有兩個子樹的樹結構。通常子樹被稱作“左子樹”(left subtree)和“右子樹”(right subtree)。二叉樹是一種遞歸結構。
二叉樹的基本概念

  • 空樹:不包含任何節點的二叉樹成爲空樹。只包含一個節點的二叉樹稱爲一個單點樹。
  • 父節點和子節點:一顆二叉樹的根節點稱爲該數的子樹根節點的父節點,與之對應的,子數的根節點稱爲二叉樹樹根節點的子節點。注意父節點和子節點是相對的。
  • 葉子節點:在二叉樹中沒有子節點的節點稱爲葉子節點。
  • 分支節點:只有存在子節點的節點都是分之節點。
  • 度數:一個節點的子節點的個數稱爲該節點的度數。即 葉子節點的度數永遠爲0,分之節點的度數爲1或2。
  • 二叉樹的層:二叉樹是一種層次結構,根節點稱爲二叉樹的0層,從根節點到任一節點的路徑長度就是該節點所在的層數,也稱爲該節點的層數。
  • 二叉樹的高度:也稱爲深度,就是樹中節點的最大層數。

二叉樹的性質

  • 性質1: 在二叉樹的第i層上至多有2^(i-1)個結點(i>0)
  • 性質2: 高度爲h的二叉樹至多有2^h - 1個結點(h>0)
  • 性質3: 對於任意一棵二叉樹,如果其葉結點數爲N0,而度數爲2的結點總數爲N2,則N0=N2+1;
  • 性質4:具有n個結點的完全二叉樹的深度必爲 log2(n+1)
  • 性質5:對完全二叉樹,若從上至下、從左至右編號,則編號爲i 的結點,其左孩子編號必爲2i,其右孩子編號必爲2i+1;其雙親的編號必爲i/2(i=1 時爲根,除外)

滿二叉樹:如果二叉樹中所有分支節點的度數都是2,這樣的二叉樹稱爲滿二叉樹。
完全二叉樹:若設二叉樹的高度爲h,除第 h 層外,其它各層 (1~h-1) 的結點數都達到最大個數,第h層有葉子結點,並且葉子結點都是從左到右依次排布,這就是完全二叉樹。
二叉樹的遍歷:

深度優先遍歷:
	深度優先搜索(Depth First Search)是沿着樹的深度遍歷樹的節點,儘可能深的搜索樹的分支。
	那麼深度遍歷有重要的三種方法。這三種方式常被用於訪問樹的節點,它們之間的不同在於訪問每個節點的次序不同。
	這三種遍歷分別叫做先序遍歷(preorder),中序遍歷(inorder)和後序遍歷(postorder)。
	先序遍歷:在先序遍歷中,先訪問根節點,然後遞歸使用先序遍歷訪問左子樹,再遞歸使用先序遍歷訪問右子樹。即 根節點->左子樹->右子樹
	中序遍歷:在中序遍歷中,遞歸使用中序遍歷訪問左子樹,然後訪問根節點,最後再遞歸使用中序遍歷訪問右子樹。即 左子樹->根節點->右子樹
	後序遍歷:在後序遍歷中,先遞歸使用後序遍歷訪問左子樹和右子樹,最後訪問根節點。即 左子樹->右子樹->根節點
   
廣度優先遍歷:
	是按路徑長度由近到遠地訪問節點。也就是按二叉樹的層次逐層訪問樹中各個節點,這種遍歷不能寫成一個遞歸過程。

2、二叉樹基於Python 列表的簡單實現

# 二叉樹基於Python語言list的實現

class BinTreeListWay(object):
    """
    二叉樹類
    """
    def __init__(self, data, left=None, right=None):
        self.__bintree = [data,left, right]

    def is_empty(self):
        """
        判斷二叉樹是否爲空
        """
        return self.__bintree == None
    
    def root(self):
        """
        返回根節點
        """
        return self.__bintree[0]

    def left(self):
        return self.__bintree[1]

    def right(self):
        return self.__bintree[2]

    def set_root(self, data):
        """
        設置根節點
        """
        self.__bintree[0] = data

    def set_left(self, data):
        self.__bintree[1] =data

    def set_right(self, data):
        self.__bintree[2] = data

    def show(self):
        """
        返回二叉樹
        """
        return self.__bintree

if __name__ == "__main__":
    d_tree = BinTreeListWay('D', 'F', 'G')
    e_tree = BinTreeListWay('E', 'I', 'H')
    c_tree = BinTreeListWay('C', d_tree.show(), e_tree.show())
    a_tree = BinTreeListWay('A', 'B')
    a_tree.set_right(c_tree.show())
    print(a_tree.show())

3、二叉樹基於Python自建類的實現

# 二叉樹基於Python語言面自建類的實現

class Node(object):
    """
    節點類
    """
    def __init__(self, data, left=None, right=None):
        self.data = data
        self.left = left
        self.right = right


class BinTreeClassWay(object):
    """
    二叉樹類
    """
    def __init__(self, root=None):
        self.root = root
    
    def is_empty(self):
        """
        判斷二叉樹是否爲空
        """
        return self.root == None

    def add(self, data):
        """
        添加節點,此方法無法控制將節點掛在到那顆子樹,也就意味着它最終形成的二叉樹爲完全二叉樹或滿二叉樹
        """
        # 實例化一個新的節點對象
        node = Node(data)
        # 如果樹是空的,則對根節點數據元素賦值
        if self.root == None:
            self.root = node
        else:
            # 創建一個存放節點的隊列
            queue = []
            queue.append(self.root)
            # 對已有的節點按層次進行遍歷
            while queue:
                # 彈出隊列的第一個節點
                head = queue.pop(0)
                if head.left == None:
                    head.left = node
                    return
                elif head.right == None:
                    head.right = node
                    return
                else:
                    #如果左右子樹都不爲空,加入隊列繼續判斷
                    queue.append(head.left)
                    queue.append(head.right)

    # 基於深度優先遍歷
    def preorder(self, bin_tree):
        """
        先序遍歷方法: 根節點->左子樹->右子樹
        """
        if bin_tree == None:
            return
        print(bin_tree.data)
        self.preorder(bin_tree.left)
        self.preorder(bin_tree.right)
    
    # 基於深度優先遍歷
    def inorder(self, bin_tree):
        """
        中序遍歷方法: 左子樹->根節點->右子樹
        """
        if bin_tree == None:
            return
        self.preorder(bin_tree.left)
        print(bin_tree.data)
        self.preorder(bin_tree.right)
    
    # 基於深度優先遍歷
    def postorder(self, bin_tree):
        """
        後序遍歷方法: 左子樹->右子樹->根節點
        """
        if bin_tree == None:
            return
        self.preorder(bin_tree.left)
        self.preorder(bin_tree.right)
        print(bin_tree.data)

    # 基於廣度優先遍歷
    def breadth_first_travel(self, bin_tree):
        """
        廣度優先遍歷
        """
        if bin_tree == None:
            return
        # 該方法和 add 方法中的插入元素類似
        queue = []
        queue.append(bin_tree)
        while queue:
            node = queue.pop(0)
            print(node.data)
            if node.left:
                queue.append(node.left)
            if node.right:
                queue.append(node.right)

    def show(self):
        """
        返回二叉樹
        """
        return self.root

if __name__ == "__main__":
    bin_tree = BinTreeClassWay()
    bin_tree.add('A')
    bin_tree.add('B')
    bin_tree.add('C')
    bin_tree.add('D')
    bin_tree.add('E')
    bin_tree.add('F')
    bin_tree.add('G')
    print('先序遍歷')
    bin_tree.preorder(bin_tree.show())
    print('中序遍歷')
    bin_tree.inorder(bin_tree.show())
    print('後序遍歷')
    bin_tree.postorder(bin_tree.show())
    print('廣度優先遍歷')
    bin_tree.breadth_first_travel(bin_tree.show())
發佈了264 篇原創文章 · 獲贊 202 · 訪問量 110萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章