【二叉樹】用python實現二叉樹的遍歷

二叉樹有四種種常見的遍歷方式:
前序遍歷:按照根—>左子樹——>右子樹的遞歸方式進行遍歷
中序遍歷:按照左子樹—>根——>右子樹的遞歸方式進行遍歷
後序遍歷:按照左子樹—>右子樹——>根的遞歸方式進行遍歷
層次遍歷:採用逐層的方式進行遍歷

下面分別就上述四種遍歷方式給出遞歸解法和非遞歸的解法。

1. 前序遍歷
  • 遞歸方式

以節點爲單位進行遞歸,遞歸函數爲子樹根節點入列+左子樹遞歸+右子樹遞歸。遞歸終止條件爲到達葉子節點,無子樹。

def preorder_traversal(t:BinaryTree, stores=[]):
    if t:
        stores.append(t.getRootVal())
        preorder_traversal(t.getLeftChild(), stores)
        preorder_traversal(t.getRightChild(), stores)
    return stores
  • 非遞歸方式

作爲一種DFS,採用棧+循環的方式進行遍歷。核心思想爲:將子樹根節點彈出,依次壓入右子樹根節點和左子樹根節點。

def preorder_traversal(t: BinaryTree):
    if t.key is None:
        return None

    root = t
    stack = Stack()   # 存放節點棧
    nodes = []          # 存放結果
    stack.push(root)

    while not stack.isEmpty():
        current = stack.pop()
        if current.getRightChild():
            stack.push(current.getRightChild())
        if current.getLeftChild():
            stack.push(current.getLeftChild())
        nodes.append(current.key)

    return nodes
2. 中序遍歷
  • 遞歸方式

以節點爲單位進行遞歸,遞歸函數爲左子樹遞歸+子樹根節點入列+右子樹遞歸。遞歸終止條件爲到達葉子節點,無子樹。

def midorder_traversal(t: BinaryTree, stores=[]):
    if t:
        midorder_traversal(t.getLeftChild(), stores)
        stores.append(t.getRootVal())
        midorder_traversal(t.getRightChild(),stores)
    return stores
  • 非遞歸方式

作爲一種DFS,仍採用棧+循環的方式進行遍歷。核心思想爲:先將左子樹全部壓入棧堆,然後作爲根節點彈出,若根節點存在右子樹,重複上述過程,否則回溯到上層的根節點。

def midorder_traversal(t: BinaryTree):
    if t.key is None:
        return None

    current = t
    stack = Stack()   # 存放節點棧
    nodes = []          # 存放結果

    while current is not None or not stack.isEmpty():
        if current is not None:
            stack.push(current)
            current = current.getLeftChild()
        else:
            current = stack.pop()
            nodes.append(current.key)
            current = current.getRightChild()

    return nodes
3. 後序遍歷
  • 遞歸方式

以節點爲單位進行遞歸,遞歸函數爲左子樹遞歸+右子樹遞歸+子樹根節點入列。遞歸終止條件爲到達葉子節點,無子樹。

def postorder_traversal(t: BinaryTree, stores=[]):
    if t:
        postorder_traversal(t.getLeftChild(), stores)
        postorder_traversal(t.getRightChild(),stores)
        stores.append(t.getRootVal())

    return stores
  • 非遞歸方式

後序遍歷可視爲前序遍歷的變種(根節點——>右子樹——>左子樹)的轉置。因此可以在前序遍歷的基礎上直接逆序結果。

def postorder_traversal(t: BinaryTree):
    if t.key is None:
        return None

    root = t
    stack = Stack()
    nodes = []

    stack.push(root)

    while not stack.isEmpty():
        current = stack.pop()
        if current.getLeftChild():
            stack.push(current.getLeftChild())
        if current.getRightChild():
            stack.push(current.getRightChild())
        nodes.append(current.key)

    return list(reversed(nodes))
4. 層次遍歷
  • 遞歸方式

以一層根節點爲單位進行遞歸,遞歸函數爲本層節點數據+下一層根節點的遞歸節點入列。遞歸終止條件爲到達最下面一層葉子節點。

def levelorder_traversal(level_trees=[], stores=[]):
    next_level_trees = []
    if level_trees:
        for t in level_trees:
           stores.append(t.getRootVal())
           if t.getLeftChild():
               next_level_trees.append(t.getLeftChild())
           if t.getRightChild():
               next_level_trees.append(t.getRightChild())
        levelorder_traversal(next_level_trees, stores)
    return stores
  • 非遞歸方式

採用隊列的方式對每層節點進行出列,同時對這些節點的左、右子樹進行入列操作。

def levelorder_traversal(t: BinaryTree):
    if t.key is None:
        return None

    root = t
    quene = Quene()
    nodes = []
    quene.enquene(root)
    while not quene.isEmpty():
        current = quene.dequene()
        if current.getLeftChild():
            quene.enquene(current.getLeftChild())
        if current.getRightChild():
            quene.enquene(current.getRightChild())
        nodes.append(current.key)
    return nodes

上述代碼依賴的基本數據結構包括:

  • 二叉樹
class BinaryTree(object):
    def __init__(self, rootObj):
        self.key = rootObj
        self.leftChild = None
        self.rightChild = None

    # 插入左子數
    def insertLeft(self, newBranch):
        if self.leftChild is None:
            self.leftChild = BinaryTree(newBranch)
        else:
            t = BinaryTree(newBranch)
            t.leftChild = self.leftChild
            self.leftChild = t

    # 插入右子樹
    def insertRight(self, newBranch):
        if self.rightChild is None:
            self.rightChild = BinaryTree(newBranch)
        else:
            t = BinaryTree(newBranch)
            t.rightChild = self.rightChild
            self.rightChild = t

    # 獲取根節點值
    def getRootVal(self):
        return self.key

    # 設置根節點值
    def setRootVal(self, value):
        self.key = value

    # 獲取左子樹
    def getLeftChild(self):
        return self.leftChild

    # 獲取右子樹
    def getRightChild(self):
        return self.rightChild
class Stack(object):
    def __init__(self):
        self.head = None

    def push(self, value):
        node = Node(value)
        if self.head is None:
            self.head = node

        else:
            node.next = self.head
            self.head = node

    def pop(self):
        if self.isEmpty():
            raise IndexError("pop from empty stack")

        else:
            node = self.head.value
            self.head = self.head.next
            return node
            
    def isEmpty(self):
        return self.head is None
  • 隊列
class Quene(object):
    def __init__(self):
        self.head = None

    def __repr__(self):
        data = []
        current = self.head
        if current is None:
            return None
        else:
            while current:
                data.append(current.value)
                current = current.next
        return str(data)

    def enquene(self, value):
        # 入隊列
        new_node = Node(value)
        if self.isEmpty():
            self.head = new_node
        else:
            current = self.head
            while current.next is not None:
                current = current.next
            current.next = new_node

    def dequene(self):
        # 出隊列
        if self.isEmpty():
            raise IndexError("dequene from empty quene")
        else:
            current = self.head
            self.head = self.head.next
            return current.value

    def isEmpty(self):
        return self.head is None
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章