數據結構和算法-18-二叉樹的先序/中序/後序遍歷和具體實現

前面一篇我們介紹了二叉樹的廣度優先添加和遍歷元素,在二叉樹的遍歷技術中,除了廣度優先遍歷,還有一種叫深度優先遍歷。本篇就來討論深度遍歷的三種重要的方法,它們分別是先序遍歷和中序遍歷和後序遍歷。

1.三種深度遍歷的概念

深度遍歷有重要的三種方法,這三種方式常被用於訪問樹的節點。它們之間不同在於訪問每個節點的次序不同。這三種遍歷分別叫做先序遍歷(preorder),中序遍歷(inorder)和後序遍歷(postorder).

先序遍歷
在先序遍歷中,我們先訪問根節點,然後遞歸使用先序遍歷訪問左子樹,再遞歸使用先序遍歷訪問右子樹。
根節點->左子樹->右子樹

中序遍歷
遞歸使用中序遍歷先訪問左子樹,然後訪問根節點,最壞遞歸使用中序訪問右子樹。
左子樹->根節點->右子樹


後序遍歷
遞歸使用後序遍歷先訪問左子樹,然後遞歸使用後序遍歷訪問右子樹,最後訪問根節點。
左子樹->右子樹->根節點

 

2.具體一顆二叉樹的三種深度遍歷分析

下面給出一個具體二叉樹,然後我們利用上面的概念,來寫出遍歷輸出元素的順序。

這個按照前面的廣度優先遍歷輸出元素的順序是:0 1 2 3 4 5 6 7 8 9

先序遍歷

先序遍歷順序是先根節點,然後左子樹,然後右子樹。我們這裏拿先序遍歷重點介紹這個思路分析過程。

第一步,遍歷根節點,輸出 0

第二步,發現左節點1下形成一個左子樹,右邊節點2也是一顆樹。左子樹優先右子樹遍歷,所以第二個輸出 1

第三步,遍歷發現3 4節點,左子樹優先元素,輸出 3

第四步,遍歷7 8 節點,輸出7

第五步,在 378這個子樹,剩下8這個右節點,所以輸出 8

第六步,因爲3節點已經遍歷過,這裏遍歷輸出 4

第七步,4節點的只有9這個節點,輸出 9

第八步,到這裏 1節點下左子樹全部遍歷完成,這裏開始遍歷2子樹,這裏輸出 2

第九步,5 6節點,左邊優先,輸出 5

第十步,輸出 6

所以先序遍歷輸出元素順序爲: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

 

3.代碼實現三種深度遍歷

下面接着上一篇python代碼,來寫先序 中序 後序三種遍歷的代碼。

先序遍歷實現

# coding:utf-8


class Node(object):
    """節點"""
    def __init__(self, itme):
        self.ele = itme
        self.lchild = None
        self.rchild = None


class BinaryTree(object):
    """二叉樹"""
    def __init__(self):
        self.root = None

    def add(self, item):
        node = Node(item)
        if self.root is None:
            self.root = node
            return
        # 一個隊列,添加根元素
        queue = [self.root]
        while queue:
            cur_node = queue.pop(0)
            if cur_node.lchild is None:
                cur_node.lchild = node
                return
            else:
                queue.append(cur_node.lchild)
            if cur_node.rchild is None:
                cur_node.rchild = node
                return
            else:
                queue.append(cur_node.rchild)

    def breadth_travle(self):
        """廣度遍歷"""
        if self.root is None:
            return
        queue = [self.root]
        while queue:
            cur_node = queue.pop(0)
            print(cur_node.ele, end=" ")
            if cur_node.lchild is not None:
                queue.append(cur_node.lchild)
            if cur_node.rchild is not None:
                queue.append(cur_node.rchild)

    def preorder(self, node):
        """先序遍歷,node 是根節點"""
        if node is None:
            return
        print(node.ele, end=" ")
        self.preorder(node.lchild)
        self.preorder(node.rchild)


if __name__ == "__main__":
    tree = BinaryTree()
    tree.add(0)
    tree.add(1)
    tree.add(2)
    tree.add(3)
    tree.add(4)
    tree.add(5)
    tree.add(6)
    tree.add(7)
    tree.add(8)
    tree.add(9)
    tree.breadth_travle()
    print(" ")
    tree.preorder(tree.root)

運行結果

0 1 2 3 4 5 6 7 8 9  
0 1 3 7 8 4 9 2 5 6 

第一個是廣度遍歷順序,第二行是先序遍歷結果。

中序遍歷代碼

上面知道了先序遍歷,那麼中序遍歷就簡單了,調整以下這行打印順序就行。

# coding:utf-8


class Node(object):
    """節點"""
    def __init__(self, itme):
        self.ele = itme
        self.lchild = None
        self.rchild = None


class BinaryTree(object):
    """二叉樹"""
    def __init__(self):
        self.root = None

    def add(self, item):
        node = Node(item)
        if self.root is None:
            self.root = node
            return
        # 一個隊列,添加根元素
        queue = [self.root]
        while queue:
            cur_node = queue.pop(0)
            if cur_node.lchild is None:
                cur_node.lchild = node
                return
            else:
                queue.append(cur_node.lchild)
            if cur_node.rchild is None:
                cur_node.rchild = node
                return
            else:
                queue.append(cur_node.rchild)

    def breadth_travle(self):
        """廣度遍歷"""
        if self.root is None:
            return
        queue = [self.root]
        while queue:
            cur_node = queue.pop(0)
            print(cur_node.ele, end=" ")
            if cur_node.lchild is not None:
                queue.append(cur_node.lchild)
            if cur_node.rchild is not None:
                queue.append(cur_node.rchild)

    def preorder(self, node):
        """先序遍歷,node 是根節點"""
        if node is None:
            return
        print(node.ele, end=" ")
        self.preorder(node.lchild)
        self.preorder(node.rchild)

    def inorder(self, node):
        """中序遍歷"""
        if node is None:
            return
        self.inorder(node.lchild)
        print(node.ele, end=" ")
        self.inorder(node.rchild)


if __name__ == "__main__":
    tree = BinaryTree()
    tree.add(0)
    tree.add(1)
    tree.add(2)
    tree.add(3)
    tree.add(4)
    tree.add(5)
    tree.add(6)
    tree.add(7)
    tree.add(8)
    tree.add(9)
    tree.breadth_travle()
    print(" ")
    tree.preorder(tree.root)
    print(" ")
    tree.inorder(tree.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

第三行是中序結果,下面直接貼出後續代碼。

# coding:utf-8


class Node(object):
    """節點"""
    def __init__(self, itme):
        self.ele = itme
        self.lchild = None
        self.rchild = None


class BinaryTree(object):
    """二叉樹"""
    def __init__(self):
        self.root = None

    def add(self, item):
        node = Node(item)
        if self.root is None:
            self.root = node
            return
        # 一個隊列,添加根元素
        queue = [self.root]
        while queue:
            cur_node = queue.pop(0)
            if cur_node.lchild is None:
                cur_node.lchild = node
                return
            else:
                queue.append(cur_node.lchild)
            if cur_node.rchild is None:
                cur_node.rchild = node
                return
            else:
                queue.append(cur_node.rchild)

    def breadth_travle(self):
        """廣度遍歷"""
        if self.root is None:
            return
        queue = [self.root]
        while queue:
            cur_node = queue.pop(0)
            print(cur_node.ele, end=" ")
            if cur_node.lchild is not None:
                queue.append(cur_node.lchild)
            if cur_node.rchild is not None:
                queue.append(cur_node.rchild)

    def preorder(self, node):
        """先序遍歷,node 是根節點"""
        if node is None:
            return
        print(node.ele, end=" ")
        self.preorder(node.lchild)
        self.preorder(node.rchild)

    def inorder(self, node):
        """中序遍歷"""
        if node is None:
            return
        self.inorder(node.lchild)
        print(node.ele, end=" ")
        self.inorder(node.rchild)

    def postorder(self, node):
        """中序遍歷"""
        if node is None:
            return
        self.postorder(node.lchild)
        self.postorder(node.rchild)
        print(node.ele, end=" ")

if __name__ == "__main__":
    tree = BinaryTree()
    tree.add(0)
    tree.add(1)
    tree.add(2)
    tree.add(3)
    tree.add(4)
    tree.add(5)
    tree.add(6)
    tree.add(7)
    tree.add(8)
    tree.add(9)
    tree.breadth_travle()
    print(" ")
    tree.preorder(tree.root)
    print(" ")
    tree.inorder(tree.root)
    print(" ")
    tree.postorder(tree.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 

 

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