1. 程式人生 > >【資料結構與演算法】002—樹與二叉樹(Python)

【資料結構與演算法】002—樹與二叉樹(Python)

概念

樹是一類重要的非線性資料結構,是以分支關係定義的層次結構

定義:

樹(tree)是n(n>0)個結點的有限集T,其中: 有且僅有一個特定的結點,稱為樹的根(root)

當n>1時,其餘結點可分為m(m>0)個互不相交的有限集T1,T2,……Tm,其中每一個集合本身又是一棵樹,稱為根的子樹(subtree)

特點: 樹中至少有一個結點——根 樹中各子樹是互不相交的集合

基本術語

  • 結點(node)——表示樹中的元素,包括資料項及若干指向其子樹的分支

  • 結點的度(degree)——結點擁有的子樹數 葉子(leaf)——度為0的結點

  • 孩子(child)——結點子樹的根稱為該結點的孩子

  • 雙親(parents)——孩子結點的上層結點叫該結點的~

  • 兄弟(sibling)——同一雙親的孩子

  • 樹的度——一棵樹中最大的結點度數

  • 結點的層次(level)——從根結點算起,根為第一層,它的孩子為第二層……

  • 深度(depth)——樹中結點的最大層次數

  • 森林(forest)——m(m0)棵互不相交的樹的集合



二叉樹

二叉樹是有限個元素的集合,該集合或者為空、或者有一個稱為根節點(root)的元素及兩個互不相交的、分別被稱為左子樹和右子樹的二叉樹組成。

  • 二叉樹的每個結點至多隻有二棵子樹(不存在度大於2的結點),二叉樹的子樹有左右之分,次序不能顛倒。
  • 二叉樹的第i層至多有2^{i-1}個結點
  • 深度為k的二叉樹至多有2^k-1個結點;
  • 對任何一棵二叉樹T,如果其終端結點數為N0,度為2的結點數為N2,則N0=N2+1

遍歷二叉樹

  • 前序遍歷
    若樹為空,則空操作返回。否則,先訪問根節點,然後前序遍歷左子樹,再前序遍歷右子樹。(W)型 (中 左 右)
  • 中序遍歷
    若樹為空,則空操作返回。否則,從根節點開始(注意並不是先訪問根節點),中序遍歷根節點的左子樹,然後是訪問根節點,最後中序遍歷根節點的右子樹。(M)型,(左 中 右)
  • 後續遍歷
    若樹為空,則空操作返回。否則,從左到右先葉子後節點的方式遍歷訪問左右子樹,最後訪問根節點。(左右中)逆時針型 (左 右 中)
  • 層序遍歷
    若樹為空,則空操作返回。否則,從樹的第一層,也就是根節點開始訪問,從上到下逐層遍歷,在同一層中,按從左到右的順序結點逐個訪問。


實現方法

class Node:
    def __init__(self,item):
        self.item = item
        self.child1 = None
        self.child2 = None


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

    def add(self, item):
        node = Node(item)
        if self.root is None:
            self.root = node
        else:
            q = [self.root]

            while True:
                pop_node = q.pop(0)
                if pop_node.child1 is None:
                    pop_node.child1 = node
                    return
                elif pop_node.child2 is None:
                    pop_node.child2 = node
                    return
                else:
                    q.append(pop_node.child1)
                    q.append(pop_node.child2)

    def traverse(self):  # 層次遍歷
        if self.root is None:
            return None
        q = [self.root]
        res = [self.root.item]
        while q != []:
            pop_node = q.pop(0)
            if pop_node.child1 is not None:
                q.append(pop_node.child1)
                res.append(pop_node.child1.item)

            if pop_node.child2 is not None:
                q.append(pop_node.child2)
                res.append(pop_node.child2.item)
        return res

    def preorder(self,root):  # 先序遍歷
        if root is None:
            return []
        result = [root.item]
        left_item = self.preorder(root.child1)
        right_item = self.preorder(root.child2)
        return result + left_item + right_item

    def inorder(self,root):  # 中序序遍歷
        if root is None:
            return []
        result = [root.item]
        left_item = self.inorder(root.child1)
        right_item = self.inorder(root.child2)
        return left_item + result + right_item

    def postorder(self,root):  # 後序遍歷
        if root is None:
            return []
        result = [root.item]
        left_item = self.postorder(root.child1)
        right_item = self.postorder(root.child2)
        return left_item + right_item + result

t = Tree()
for i in range(10):
    t.add(i)
print('層序遍歷:',t.traverse())
print('先序遍歷:',t.preorder(t.root))
print('中序遍歷:',t.inorder(t.root))
print('後序遍歷:',t.postorder(t.root))
層序遍歷: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
先序遍歷: [0, 1, 3, 7, 8, 4, 9, 2, 5, 6]
中序遍歷: [7, 3, 8, 1, 9, 4, 0, 5, 2, 6]
後序遍歷: [7, 8, 3, 9, 4, 1, 5, 6, 2, 0]