本文目前分享的題目都是來自於July的分享,而後把具體算法實現。搜索樹轉雙向鏈表主要的實現邏輯是在中序遍歷時,調整節點的左右子樹;由於中序遍歷是遞歸調用,因此在調整時必定要注意調整的位置,若是寫錯了,頗有可能形成死循環。避免的主要辦法是在讀完左子樹時調整左節點,遍歷完右子樹時調整右節點,具體代碼見trans函數。算法的時間複雜度是o(logn)。算法
輸入樹構建完成後是:數組
代碼以下:bash
# -*- 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測試
歡迎關注訂閱號「白話算法」 ui