树是一种重要的数据结构,洛基在平时刷算法题遇到的一些与树有关的操作,在此记录一下。
二叉树的遍历(前、中、后序遍历的递归和非递归实现):
# 二叉树节点的定义
class TreeNode(object):
"""docstring for TreeNode"""
def __init__(self, x):
super(TreeNode, self).__init__()
self.val = x
self.left = None
self.right = None
# 前序遍历: 根 -> 左 -> 右
def front(self, root: TreeNode) -> List[int]:
nlist = []
if not root:
return nlist
stack = []
node = root
while stack or node:
while node:
nlist.append(node.val)
stack.append(node)
node = node.left
node = stack.pop()
node = node.right
return nlist
# 中序遍历: 左 -> 根 -> 右
def middle(self, root: TreeNode) -> List[int]:
nlist = []
if not root:
return nlist
stack = []
node = root
while stack or node:
while node:
stack.append(node)
node = node.left
node = stack.pop()
nlist.append(node.val)
node = node.right
return nlist
# 后序遍历: 左 -> 右 -> 根
def last(self, root: TreeNode) -> List[int]:
nlist = []
if not root:
return nlist
stack = []
node = root
while stack or node:
while node:
stack.append(node)
if node.left:
node = node.left
else:
node = node.right
node = stack.pop()
nlist.append(node.val)
# 这个时候我们需要看,当前被访问的节点是左孩子还是右孩子,如果是左孩子,那么我们需要再访问一下右孩子;
# 如果是右孩子,我们直接访问父亲节点即可。
if stack and stack[-1].left == node:
node = stack[-1].right
else:
# node=None之后,程序会直接访问父节点;不能用node=stack.pop(),否则程序会再重新往下查找孩子节点!
node = None
return nlist
# 二叉树的层次遍历
def hierarchy(self, root: TreeNode) -> List[int]:
nlist = []
if not root:
return nlist
cur = [root]
while cur:
nextLayer = []
for node in cur:
if node:
nlist.append(node.val)
if node.left:
nextLayer.append(node.left)
if node.right:
nextLayer.append(node.right)
cur = nextLayer
return nlist
# 递归的方法前序遍历
def front_recursive(self, node):
if not node:
return
print(node.val)
front_travel(node.left)
front_travel(node.right)
# 递归的中序、后序遍历与前序遍历相似
def middle_recursive(self, node):
if not node:
return
middle_recursive(node.left)
print(node.val)
middle_recursive(node.right)
def right_recursive(self, node):
if not node:
return
right_recursive(node.left)
right_recursive(node.right)
print(node.val)
递归的方式判断两棵树是否相同:
# Definition for a binary tree node
class TreeNode:
def __init__(self, x):
self.val = x
self.left = None
self.right = None
class Solution:
def isSameTree(self, p: TreeNode, q: TreeNode) -> bool:
if p and not q:
return False
if q and not p:
return False
if not p and not q:
return True
return p.val == q.val and self.isSameTree(p.left, q.left) and self.isSameTree(p.right, q.right)
判断一棵二叉树是否是对称二叉树:
# Definition for a binary tree node
class TreeNode:
def __init__(self, x):
self.val = x
self.left = None
self.right = None
class Solution:
# 思路一,用递归的方法,和判断相同的树,思路差不多,
# 只是递归的时候用节点1的左子树与节点2的右子树做对比了。
def isSymmetric(self, root: TreeNode) -> bool:
def check(node_1, node_2) -> bool:
if not node_1 and node_2:
return False
if node_1 and not node_2:
return False
if not node_1 and not node_2:
return True
return node_1.val = node_2.val and check(node_1.left, node_2.right) and check(node_1.right, node_2.left)
return check(root.left, root.right)
# 思路二:用栈来存储这棵树里处在对称位置的节点。
# 用p,q表示一对处在对称位置的节点(初始为根节点的左、右孩子),比较他们的值;
# 接着将p的左孩子与q的右孩子入栈,将p的右孩子与q的左孩子入栈。
# 然后从栈里pop一对节点出来,这一对节点将是对称位置的节点,继续比较。
def isSymmetric_2(self, root: TreeNode) -> bool:
if not root: # 询问面试官,如果根节点不存在怎么办
return True
if not root.left and not root.right:
return True
stack = [root.left, root.right]
while stack:
r = stack.pop()
l = stack.pop()
# 都不为空
if l and r:
if l.val != r.val:
return False
stack.extend([l.left, r.right, l,right, r.left])
# 全为空
elif not l and not r:
continue
# 剩下的就是 l 和 r 中有一个是None的情况
else:
return False
return True
判断一棵树是否是平衡二叉树:
class TreeNode:
def __init__(self, x):
self.val = x
self.left = None
self.right = None
class Solution:
def maxDepth(self, root: TreeNode) -> int:
if not root:
return 0
curLevel = [root]
level = 0
while curLevel:
nextLevel = []
for node in curLevel:
if node.left:
nextLevel.append(node.left)
if node.right:
nextLevel.append(node.right)
curLevel = nextLevel
level = level + 1
return level
def is_balanced(self, root: TreeNode) -> bool:
if not root:
return True
return abs(maxDepth(root.left) - maxDepth(root.right)) <= 1 \
and is_balanced(root.left) and is_balanced(root.right)