遞迴轉非遞迴 棧模擬 Recursive to Non-recursive stack simulated 總結
As is well known, recursive codes could be transformed into non-recursive codes leveraging stack. However, simulating the recursive procedure should take care of what should be done before and after each function call. The recursive codes generally could be classified into 3 categories: preorder, inorder and postorder. For the preorder, the tag to distinguish the left node or right node is not necessary. But for the inorder and postorder, a tag is significant. The following is the basic flow for recursive the non-recursive.
def NonRecursive(self, root):
stack = []
while ((Go to the Most Left Leaf) or (Stack is Not Empty)):
while (Go to the Most Left Leaf):
stack.append(Left Leaf Function Call)
#Go to deeper left node
if (Stack is Not Empty):
cur = stack.pop()
if (cur["tag"] == 'l'):
# Do the right thing
elif (cur["tag"] == 'r'):
root = cur["node"]
# Do the right thing
Here're examples for tree traversal:
from itertools import permutations
# Definition for a binary tree node.
class TreeNode:
def __init__(self, x):
self.val = x
self.left = None
self.right = None
class Solution:
def p1(self, root):
if (root == None):
return
print(root.val)
self.p1(root.left)
self.p1(root.right)
def p2(self, root):
stack = []
while (root != None or stack):
while (root != None):
print(root.val)
stack.append(root)
root = root.left
if (stack):
root = stack.pop()
root = None if root == None else root.right
def i1(self, root):
if (root == None):
return
self.i1(root.left)
print(root.val)
self.i1(root.right)
def i2(self, root):
stack = []
while (root != None or stack):
while (root != None):
stack.append({'node':root, 'tag':'l'})
root = root.left
if (stack):
cur = stack.pop()
if (cur["tag"] == 'l'):
print(cur["node"].val)
if (cur["node"].right != None):
stack.append({'node': cur["node"].right, 'tag': 'r'})
root = None
elif (cur["tag"] == 'r'):
root = cur["node"]
def post1(self, root):
if (root == None):
return
self.post1(root.left)
self.post1(root.right)
print(root.val)
def post2(self, root):
stack = []
while (root != None or stack):
while (root != None):
stack.append({'node':root, 'tag':'l'})
root = root.left
if (stack):
cur = stack.pop()
if (cur["tag"] == 'l'):
stack.append({'node': cur["node"], 'tag': 'r'})
root = None if cur["node"].right == None else cur["node"].right
elif (cur["tag"] == 'r'):
print(cur["node"].val)
root = None
n1 = TreeNode(1)
n2 = TreeNode(2)
n3 = TreeNode(3)
n4 = TreeNode(4)
n5 = TreeNode(5)
n6 = TreeNode(6)
n7 = TreeNode(7)
n1.left = n2
n1.right = n3
n2.left = n4
n2.right = n5
n3.left = n6
n3.right = n7
s = Solution()
s.post1(n1)
print('------------------')
s.post2(n1)
Another two examples, Hanoi is inorder:
from itertools import permutations
def h1(src, des, via, n):
if (n == 0):
return
#Before recursive call of left child, des and via swap for left child going deeper
h1(src, via, des, n-1)
#After recursive call, print will be done for left child
print("{0}:{1}-->{2}".format(n, src, des))
#Before recursive call of right child, via and src swap for right child going deeper
h1(via, des, src, n-1)
#After recursive call of right child, nothing will be done again
def h2(src, des, via, n):
stack = []
while (stack or n > 0):
#Deeper for left child
while (n > 0):
stack.append({'src': src, 'des': via, 'via':des, 'n': n-1, 'child':'left'})
des, via = via, des
n = n - 1
if (stack):
top = stack.pop()
if (top['child'] == 'left'):
src, des, via, n, child = top['src'], top['via'], top['des'], (top['n'] + 1), top['child']
print("{0}:{1}-->{2}".format(n, src, des))
stack.append({'src': via, 'des': des, 'via': src, 'n': n - 1, 'child': 'right'})
n = 0
elif (top['child'] == 'right'):
src, des, via, n, child = top['src'], top['des'], top['via'], (top['n'] + 1), top['child']
n = n - 1
h1('A', 'C', 'B', 3)
print('------------------')
h2('A', 'C', 'B', 3)
A better hanoi version:
#A better python version
#call: push to stack
#enter calling: pop from stack
def h2(src, des, via, n):
stack = []
while (stack or n > 0):
# Deeper for left child
while (n > 0):
stack.append({'src': src, 'des': des, 'via': via, 'n': n, 'child': 'left'})
des, via = via, des
n = n - 1
if (stack):
top = stack.pop()
if (top['child'] == 'left'):
print("{0}:{1}-->{2}".format(top['n'], top['src'], top['des']))
if (top['n'] > 1):
stack.append({'src': top['via'], 'des': top['des'], 'via': top['src'], 'n': top['n']-1, 'child': 'right'})
elif (top['child'] == 'right'):
src, des, via, n, child = top['src'], top['des'], top['via'], top['n'], top['child']
Quicksort is preorder:
from itertools import permutations
def partition(a, l, r):
i, j = l, r
pivot = a[(i + j) // 2]
while (i <= j): # Ensure i, j are not at the same position after partition, so i <=j instead of i <j
while (a[i] < pivot):
i = i + 1
while (a[j] > pivot):
j = j - 1
if (i <= j):
a[i], a[j] = a[j], a[i]
i, j = (i + 1), (j - 1)
return i, j
def q1(a, l, r):
i, j = partition(a, l, r)
if (i < r):
q1(a, i, r)
if (j > l):
q1(a, l, j)
return a
#preorder doesn't need tag
def q2(a, l, r):
stack = []
while (stack or l < r):
while (l < r):
i, j = partition(a, l, r)
if (j > l):
stack.append({'left': l, 'right': j})
l, r = i, r
if (stack):
top = stack.pop()
l, r = top['left'], top['right']
return a
#preorder doesn't need tag
def q3(a, l, r):
stack = []
while (stack or l <= r):
while (l <= r):
i, j = partition(a, l, r)
stack.append({'l':l, 'r':r, 'i':i, 'j':j})
l, r = i, r
if (stack):
cur = stack.pop()
l, r = cur['l'], cur['j']
return a
for perm in permutations([1, 2, 3, 3, 4, 5, 6], 7):
y = q3(list(perm), 0, 6)
print(y)
相關文章
- 棧Stack——遞迴替身?遞迴
- 快速排序【遞迴】【非遞迴】排序遞迴
- 遞迴總結遞迴
- 反轉連結串列(遞迴與棧)遞迴
- 遞迴和遞推總結遞迴
- 【C++】翻轉二叉樹(遞迴、非遞迴)C++二叉樹遞迴
- 遍歷二叉樹-------遞迴&非遞迴二叉樹遞迴
- 棧實現遞迴遞迴
- 快速排序(遞迴及非遞迴演算法原始碼)排序遞迴演算法原始碼
- 遞迴和尾遞迴遞迴
- python-動態規劃的遞迴、非遞迴實現Python動態規劃遞迴
- 揹包問題的遞迴與非遞迴演算法遞迴演算法
- Vue3.0的遞迴監聽和非遞迴監聽Vue遞迴
- 資料結構:歸併排序(非遞迴)資料結構排序遞迴
- 實現反轉連結串列--遞迴、迭代、雙指標、棧遞迴指標
- 遞迴和非遞迴分別實現求n的階乘遞迴
- 二叉樹的四種遍歷(遞迴與非遞迴)二叉樹遞迴
- 樹3-二叉樹非遞迴遍歷(棧)二叉樹遞迴
- Android遍歷所有控制元件的遞迴和非遞迴實現Android控制元件遞迴
- 最新情報:所有的遞迴都可以改寫成非遞迴?遞迴
- 我對遞迴的理解和總結遞迴
- 遞迴遞迴
- 二分法的簡單實現——-遞迴和非遞迴遞迴
- 遍歷二叉樹的遞迴與非遞迴程式碼實現二叉樹遞迴
- Python 八皇后解法(非遞迴版本)Python遞迴
- 資料結構與演算法——歸併排序: 陣列&連結串列&遞迴&非遞迴解法全家桶資料結構演算法排序陣列遞迴
- 資料結構-樹以及深度、廣度優先遍歷(遞迴和非遞迴,python實現)資料結構遞迴Python
- 連結串列與遞迴遞迴
- 通用-遞迴樹結構遞迴
- 資料結構-遞迴資料結構遞迴
- 連結串列反轉非遞迴演算法!看不懂打死我!遞迴演算法
- 二叉樹的前中後序遍歷(遞迴和非遞迴版本)二叉樹遞迴
- 二十一、氣泡排序演算法——JAVA實現(遞迴與非遞迴)排序演算法Java遞迴
- python實現二叉樹及其七種遍歷方式(遞迴+非遞迴)Python二叉樹遞迴
- 二叉樹——後序遍歷的遞迴與非遞迴演算法二叉樹遞迴演算法
- 什麼是遞迴?遞迴和迴圈的異同遞迴
- js深度繼承的非遞迴方法JS繼承遞迴
- 歸併排序的非遞迴實現排序遞迴