二叉樹的建立以及遍歷的多種實現(python版)


二叉樹是很重要的數據結構,在面試還是日常開發中都是很重要的角色。

首先是建立樹的過程,對比C或是C++的實現來講,其涉及到了較為復雜的指針操作,但是在面向對象的語言中,就不需要考慮指針, 內存等。首先我們需要定義一個樹節點, 我們采用基於鏈表設計的節點, 首先定義一個數據域, 其次就是左孩子和右孩子。如下定義:

# 樹節點的定義
class Node:
    def __init__(self, data=-1, lchild=None, rchild=None):
        self.lchild = lchild  # 表示左子樹
        self.rchild = rchild  # 表示右子樹
        self.data = data  # 表示數據域

 

建立樹的實現有兩種,遍歷建樹與層次建樹,這兩種分別是基於堆棧和隊列來實現的,先來看看最基本的遞歸建樹。
遞歸建樹的過程無非就是一路走到底,但是需要將節點的左右孩子節點對其余的節點相關聯起來。因此,我們可以如此來實現:

def traversal_create(self, root):
data = input()
if data is "#":
return None
else:
root.data = data
root.lchild = self.traversal_create(root.lchild)
root.rchild = self.traversal_create(root.rchild)
return root

首先我們傳入的參數是一個默認的節點,其data數據域為-1,然后我們接受輸入的數據,賦值給節點數據域,然后就是遞歸了,將左右孩子節點關聯起來。總體來講,應該不難理解。

下面看看層次建樹的實現,所謂層次建樹其實就是基於隊列的操作,利用隊列先進先出的特點,每次我們訪問一個節點的時候,將其存入隊列中,待遍歷玩當前節點的左右孩子節點,隊列就彈出一個節點,之后的操作都是一樣的。看看代碼:

def add(self, elem):
node = Node(elem)
# 根節點
if self.root.data == -1:
self.root = node
self.myQueue.append(self.root)
else:
treeNode = self.myQueue[0] # 記錄結點
if treeNode.lchild is None:
treeNode.lchild = node
self.myQueue.append(treeNode.lchild)
else:
treeNode.rchild = node
self.myQueue.append(treeNode.rchild)
self.myQueue.popleft() # 彈出已經處理好左右子樹的父結點

我們輸入一個數據,然后根據數據初始化一個節點,放入隊列中,隨后就是訪問的操作了。

樹的三序遍歷就不用說了,基於遞歸的,很好理解,那么基於隊列以及堆棧的的遍歷呢?
對比下基於隊列的建樹,我們完全可以寫出基於隊列的遍歷, 也是使用隊列來存儲節點,然后輸出左右孩子的數據:

# 層次遍歷 使用隊列
def queue_tarversal(self, root):
if root is None:
return
q = deque()
q.append(root)
while q:
node = q.pop()
print(node.data)
if node.lchild is not None:
q.append(node.lchild)
else:
q.append(node.rchild)

基於堆棧的呢?聯想下堆棧的特點,我們一路沿着左子樹遍歷下去,同時使用堆棧來存儲元素,然后在彈出遍歷右孩子節點:

# 使用堆棧來遍歷
def stack_traversal(self, root):
if root is None:
return
mystack = []
node = root
while node or mystack:
while node:
print(node.data)
mystack.append(node)
node = node.lchild
node = mystack.pop()
node = node.rchild

數據結構是難點也是基礎,不管怎么樣都應該好好學習。

完整代碼:

''' 二叉樹的建立及實現 (遞歸與非遞歸) '''
from collections import deque


# 樹節點的定義
class Node:
    def __init__(self, data=-1, lchild=None, rchild=None):
        self.lchild = lchild  # 表示左子樹
        self.rchild = rchild  # 表示右子樹
        self.data = data  # 表示數據域


class Create_Tree:
    def __init__(self):
        self.root = Node()  # 表示結點
        self.myQueue = deque()  # 使用隊列不會有太多的內存開銷

    # 按層次生成樹
    def add(self, elem):
        node = Node(elem)
        # 根節點
        if self.root.data == -1:
            self.root = node
            self.myQueue.append(self.root)
        else:
            treeNode = self.myQueue[0]  # 記錄結點
            if treeNode.lchild is None:
                treeNode.lchild = node
                self.myQueue.append(treeNode.lchild)
            else:
                treeNode.rchild = node
                self.myQueue.append(treeNode.rchild)
                self.myQueue.popleft()  # 彈出已經處理好左右子樹的父結點

    # 遞歸建樹
    def traversal_create(self, root):
        data = input()
        if data is "#":
            return None
        else:
            root.data = data
            root.lchild = self.traversal_create(root.lchild)
            root.rchild = self.traversal_create(root.rchild)
        return root

    # 前序遍歷輸出
    def digui(self, root):
        if root is None:
            return
        print(root.data)
        self.digui(root.lchild)
        self.digui(root.rchild)

    # 使用堆棧來遍歷
    def stack_traversal(self, root):
        if root is None:
            return
        mystack = []
        node = root
        while node or mystack:
            while node:
                print(node.data)
                mystack.append(node)
                node = node.lchild
            node = mystack.pop()
            node = node.rchild

    # 層次遍歷 使用隊列
    def queue_tarversal(self, root):
        if root is None:
            return
        q = deque()
        q.append(root)
        while q:
            node = q.pop()
            print(node.data)
            if node.lchild is not None:
                q.append(node.lchild)
            else:
                q.append(node.rchild)


if __name__ == "__main__":
    elems = range(10)
    tree = Create_Tree()
    for i in elems:
        # 非遞歸建樹,主要就是根據 隊列FIFO的特點以及廣度遍歷的思路
        tree.add(i) 

    # 遞歸建樹
    # tree.traversal_create(tree.root)

    # 遞歸遍歷
    tree.digui(tree.root)
    # 棧遍歷
    # tree.stack_traversal(tree.root)
View Code


免責聲明!

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



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