二叉树笑谈
一个仙人有两个子女,左儿右女。儿女各有家谱。
计算机能理解的方式
class TreeNode:
def __ini__(self, left=None, right=None):
self.left = left
self.right = right
先序遍历
所谓遍历就是,对相应的人进行某种操作。
先对六道仙人操作,然后对儿子然后女儿操作,这就是先序遍历。
递归三剑客
- 剑尖
- 出口
- 剑身
- 递归函数
- 剑柄
- 递归参数
def preOrder(root):
#剑尖
if not root:
return
#剑身
print(root.val)
preOrder(root.left)
preOrder(root.right)
朴素迭代剑法
res = ListNode(-1)
cur = root
stack = []
while stack or cur:
# cur是个人
while cur:
result.next = ListNode(cur.val) #先查这个人
stack.append(cur) # 保存这个人,方便后面再查他女儿
cur = cur.left # 查他儿子
cur = stack.pop() #找到之前的保存的人信息,查不到他儿子查他女儿
cur = cur.right
后序遍历
先查以儿子为祖先的族谱,然后再查 以女儿为祖先的族谱,最后处理仙人。
def postOrder(root):
if not root:
return root
postOrder(root.left)
postOrder(root.right)
print(root.val)
return
这玩意的迭代有点难理解,先这么写吧。。。。。。
这里记住一个逻辑,如果你要查某个人,你肯定要思考他的女儿是否查过,如果查过,那么你就可以查这个人。而且你会发现。 如果他的女儿没查过,那么先查女儿。
如何判断、女儿是否查过???
这里有个诀窍,就是记录一个pre人,这个人就是之前查的人。
如果上一个被查的人是当前的人的女儿,说明可以查当前这个人了。
因为女儿的族谱里,根节点(女儿)是最后最近一个被遍历的。
stack = []
res = ListNode(-1)
cur = root
pre = None
while cur or stack;
while cur:
stack.append(cur)
cur = cur.left
cur = stack[-1]
# 女儿没有查过
if cur.right and cur.next != prev:
cur = cur.right
else:
stack.pop()
res.next = ListNode(cur.val)
pre = cur
cur = None # 但凡能走到这,肯定父亲已经在stack里了
中序遍历
粗话来说就是:
- 先查他儿子,再查(他)祖宗,再查他女儿。
def inOrder(root):
if not root:
return
inOrder(root.left)
print(root.val)
inOrder(root.right)
return
res = ListNode(-1)
cur = root
stack = [] # 没有查完的人
while cur or stack: # 是个人就查, 没查完继续查他其他子女
while cur: # 是个人
stack.append(cur) # 存着本人信息
cur = cur.left #先从他儿子下手
cur = stack.pop() # 查完了儿子的儿子的儿子,查儿子的儿子的女儿。这里的cur是上面的cur他父母
res.next = ListNode(cur.val)
cur = cur.right
总结
def helper(root):
if not root:
return
# 先干啥
helper(root.left)
# 中干啥
helper(root.right)
# 后干啥
while stack or cur:
while cur:
#先干什么
stack.append(cur)
cur = cur.left
cur = stack.pop()
# 中间干什么
# 后面干什么
cur = cur.right