栈版本
前序遍历
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def preorderTraversal(self, root: TreeNode):
if not root:
return []
stack = [root]
res = []
while stack:
node = stack.pop()
res.append(node.val)
if node.right:
stack.append(node.right)
if node.left:
stack.append(node.left)
return res
中序遍历
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def inorderTraversal(self, root: TreeNode):
stack = []
res = []
tmp = root
while tmp is not None or stack:
if tmp:
stack.append(tmp)
tmp = tmp.left
else:
tmp = stack.pop()
res.append(tmp.val)
tmp = tmp.right
return res
后序遍历
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def postorderTraversal(self, root: TreeNode):
if not root:
return []
res = []
stack = [root]
while stack:
tmp = stack.pop()
res.append(tmp.val)
if tmp.left:
stack.append(tmp.left)
if tmp.right:
stack.append(tmp.right)
return res[::-1]
Morris遍历
- morris遍历是二叉树遍历算法的超强进阶算法,跟递归、非递归(栈实现)的空间复杂度(O(n))相比,morris遍历可以将非递归遍历中的空间复杂度降为O(1)(因为只是指针的操作),从而实现时间复杂度为O(N),而空间复杂度为O(1)的精妙算法。
- morris遍历利用的是树的叶子节点左右指针为空,实现空间开销的极限缩减。
- morris遍历对于没有左子树的节点只遍历一次,对于有左子树的节点会遍历两次
前序遍历
首先记root节点为cur:
- 如果cur无左孩子,打印cur.val,cur向右移动(cur=cur.right)
- 如果cur有左孩子,找到cur左子树上最右的节点,记为pre:
- 如果pre的right指针指向空,让其指向cur,打印cur.val,cur向左移动(cur=cur.left)
- 如果pre的right指针指向cur,让其指向空,cur向右移动(cur=cur.right)
实现以上的原则,即实现了morris前序遍历。
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def preorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
cur = root
res = []
while cur:
if cur.left:
pre = cur.left
while pre.right and pre.right != cur:
pre = pre.right
if not pre.right:
pre.right = cur
res.append(cur.val)
cur = cur.left
continue
elif pre.right == cur:
pre.right = None
else:
res.append(cur.val)
cur = cur.right
return res
中序遍历
首先记root节点为cur:
- 如果cur无左孩子,打印cur.val,cur向右移动(cur=cur.right)
- 如果cur有左孩子,找到cur左子树上最右的节点,记为pre:
- 如果pre的right指针指向空,让其指向cur,cur向左移动(cur=cur.left)
- 如果pre的right指针指向cur,让其指向空,打印cur.val,cur向右移动(cur=cur.right)
实现以上的原则,即实现了morris中序遍历。
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def inorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
cur = root
res = []
while cur:
if cur.left:
pre = cur.left
while pre.right and pre.right != cur:
pre = pre.right
if not pre.right:
pre.right = cur
cur = cur.left
continue
elif pre.right == cur:
pre.right = None
res.append(cur.val)
cur = cur.right
return res
后序遍历(比较复杂)
首先记root节点为cur:
- 如果cur无左孩子,cur向右移动(cur=cur.right)
- 如果cur有左孩子,找到cur左子树上最右的节点,记为pre:
- 如果pre的right指针指向空,让其指向cur,cur向左移动(cur=cur.left)
- 如果pre的right指针指向cur,让其指向空,倒序打印cur左子树的右路径(定义函数addPath实现),cur向右移动(cur=cur.right)
- 跳出后倒序打印root的右路径
实现以上的原则,即实现了morris后序遍历。
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def postorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
cur = root
res = []
def addVal(node):
count = 0
while node:
count += 1
res.append(node.val)
node = node.right
i, j = len(res)-count, len(res)-1
while i < j:
res[i], res[j] = res[j], res[i]
i += 1
j -= 1
while cur:
if cur.left:
pre = cur.left
while pre.right and pre.right != cur:
pre = pre.right
if not pre.right:
pre.right = cur
cur = cur.left
continue
elif pre.right == cur:
pre.right = None
addVal(cur.left)
cur = cur.right
addVal(root)
return res