遞迴轉非遞迴 棧模擬 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++二叉樹遞迴
- 遍歷二叉樹-------遞迴&非遞迴二叉樹遞迴
- 【資料結構】二叉樹遍歷(遞迴+非遞迴)資料結構二叉樹遞迴
- 棧實現遞迴遞迴
- 遞迴演算法轉換為非遞迴演算法的技巧遞迴演算法
- 快速排序(遞迴及非遞迴演算法原始碼)排序遞迴演算法原始碼
- 關於樹型結構資料遞迴查詢,轉非遞迴查詢的實現遞迴
- 遞迴和尾遞迴遞迴
- 揹包問題的遞迴與非遞迴演算法遞迴演算法
- Vue3.0的遞迴監聽和非遞迴監聽Vue遞迴
- 用棧+回溯+非遞迴解決N皇后問題遞迴
- python-動態規劃的遞迴、非遞迴實現Python動態規劃遞迴
- 遞迴和非遞迴分別實現求n的階乘遞迴
- 二叉樹的四種遍歷(遞迴與非遞迴)二叉樹遞迴
- 斐波那契數列的遞迴和非遞迴實現遞迴
- 原:八皇后問題的遞迴和非遞迴Java實現遞迴Java
- 資料結構:歸併排序(非遞迴)資料結構排序遞迴
- 樹3-二叉樹非遞迴遍歷(棧)二叉樹遞迴
- 產生遞迴呼叫 (Recursive Call 或 recursive SQL statements) 的幾種情況遞迴SQL
- Java遍歷資料夾的兩種方法(非遞迴和遞迴)Java遞迴
- 實現反轉連結串列--遞迴、迭代、雙指標、棧遞迴指標
- 遞迴與goto (轉)遞迴Go
- 遞迴遞迴
- 我對遞迴的理解和總結遞迴
- 遍歷二叉樹的遞迴與非遞迴程式碼實現二叉樹遞迴
- 二分法的簡單實現——-遞迴和非遞迴遞迴
- Android遍歷所有控制元件的遞迴和非遞迴實現Android控制元件遞迴
- 【演算法拾遺】二分查詢遞迴非遞迴實現演算法遞迴
- 斐波那契數列(Fibonacci)遞迴和非遞迴實現遞迴
- 二叉樹建立及遍歷演算法(遞迴及非遞迴)二叉樹演算法遞迴
- ACM(遞迴遞推—A)ACM遞迴
- 漢諾塔非遞迴演算法遞迴演算法
- 資料結構與演算法——歸併排序: 陣列&連結串列&遞迴&非遞迴解法全家桶資料結構演算法排序陣列遞迴
- 【資料結構】——搜尋二叉樹的插入,查詢和刪除(遞迴&非遞迴)資料結構二叉樹遞迴