1. 程式人生 > >Python演算法練習--把搜尋樹轉成雙向連結串列

Python演算法練習--把搜尋樹轉成雙向連結串列

本文目前分享的題目都是來自於July的分享,然後把具體演算法實現。搜尋樹轉雙向連結串列主要的實現邏輯是在中序遍歷時,調整節點的左右子樹;因為中序遍歷是遞迴呼叫,所以在調整時一定要注意調整的位置,如果寫錯了,很有可能造成死迴圈。避免的主要辦法是在讀完左子樹時調整左節點,遍歷完右子樹時調整右節點,具體程式碼見trans函式。演算法的時間複雜度是o(logn)。

     輸入樹構建完成後是:

image

程式碼如下:

# -*- coding: utf-8 -*-
"""
題目:輸入一棵二叉搜尋樹(記住是搜尋樹),將該二叉搜尋樹轉換為一個排序的雙向連結串列。要求:不能建立任何新的結點,只能調整樹中結點指標的指向。
1 2 3 4 5 6 7 輸入順序 4 3 1 2 5 6 7用這個順序建立二叉查詢樹
基本思路:用中序遍歷的方式,每一個節點左側連線的應該是左子數的最右邊一個節點,而右邊連線的應該是右子樹最左邊的節點
"""
class TreeNode: """ 樹的節點定義,後面的很多操作都是基於節點的 """ def __init__(self): """ 定義一個樹的節點,初始狀態左右節點為空 """ self.leftNode = None self.rightNode = None def setData(self, data): """ 設定數字的方法 args: data節點值 """ self.data = data def
setLeftNode(self, leftNode):
""" 設定左節點的方法 args: leftNode 左節點 """ self.leftNode = leftNode def setRightNode(self, rightNode): """ 設定右節點的方法 args: rightNode 右節點 """ self.rightNode = rightNode def getData(self): """ 獲取節點數字 return:返回節點數字 """
return self.data def getLeftNode(self): """ 獲取左節點 return:返回左節點 """ return self.leftNode def getRightNode(self): """ 獲取右節點 return:返回右節點 """ return self.rightNode class BuildTree: """ 以輸入順序構建二叉查詢樹,左邊的比根節點小,右側的比根節點大 """ def build(self, dataList): """ 開始構建樹 args:dataList 樹的節點值 """ #遍歷輸入陣列 for i in range(len(dataList)): currData = dataList[i] #初始化一個節點 newTreeNode = TreeNode() newTreeNode.setData(currData); #如果是一個輸入,則作為樹的根節點 if i==0: self.tree = newTreeNode #否則進行大小的比較,構建二叉查詢樹 else: flagNode = self.tree while flagNode is not None: if currData <= flagNode.getData(): #如果當然值小於等於根節點,並且左節點為空的話,則進行左節點賦值 if flagNode.getLeftNode() is None: flagNode.setLeftNode(newTreeNode) break; else: #否則繼續找左節點 flagNode = flagNode.getLeftNode() else: #如果當然值大於根節點,並且右節點為空的話,則進行右節點賦值 if flagNode.getRightNode() is None: flagNode.setRightNode(newTreeNode) break; else: #否則繼續找右節點 flagNode = flagNode.getRightNode() def trans(self, tempNode): """ 遞迴進行中序遍歷 在左子樹遍歷完時,找左子樹最右邊的節點,做為節點的左子樹 在右子樹遍歷完時,找左子樹最右變的節點,做為節點的右子樹 args:tempNode 初始為樹的根節點 """ if tempNode is not None: #遞迴遍歷左子樹 self.trans(tempNode.getLeftNode()) #左子樹遍歷完成,進行左側最右節點的查詢 if tempNode.getLeftNode() is not None: tempNode2 = tempNode.getLeftNode() while tempNode2.getRightNode() is not None: tempNode2 = tempNode2.getRightNode() tempNode.setLeftNode(tempNode2) tempNode2.setRightNode(tempNode) #遞迴遍歷右子樹 self.trans(tempNode.getRightNode()) #右子樹遍歷完成,進行右側最左節點的查詢 if tempNode.getRightNode() is not None: tempNode2 = tempNode.getRightNode() while tempNode2.getLeftNode() is not None: tempNode2 = tempNode2.getLeftNode() tempNode.setRightNode(tempNode2) tempNode2.setLeftNode(tempNode) def callTrans(self): """ 用根節點對trans進行呼叫 """ self.trans(self.tree); def test(self): """ 進行資料的測試,分別從左到右讀和從右到左讀取資料 """ tempNode = self.tree while tempNode.getLeftNode() is not None: #找到最左節點 tempNode = tempNode.getLeftNode() #print tempNode.getData() #從左向右讀 while tempNode.getRightNode() is not None: print tempNode.getData() tempNode = tempNode.getRightNode() print tempNode.getData() #從右向左讀 while tempNode is not None: print tempNode.getData() tempNode = tempNode.getLeftNode() if __name__ == "__main__": #初始化陣列 dataList = [10,6,4,8,2,5,7,9,20,15,28,14,16,24,29] test = BuildTree() #構建排序數 test.build(dataList) #遞迴構建雙向連結串列 test.callTrans() #測試輸出 test.test()             

輸出結果:

2 4 5 6 7 8 9 10 14 15 16 20 24 28 29 29 28 24 20 16 15 14 10 9 8 7 5 4 2

歡迎關注訂閱號“白話演算法”
baihua.png