二叉树的两颗子树有明确的左右之分.
说子树时必须说明是左子树/右子树. 根节点从1开始计数. 高度和深度是从0开始, 层数是从1开始
- 在非空二叉树第i层中至多有
2**(i-1)
次方个结点 - 在高度为h的二叉树
总结点数
最多为2**(h+1)-1
个结点 - 序号为1的点是根
- 对于i>0, 其父节点的编号是
i/2
- 如果节点
i
有左右子节点, 那么左子树编号是2*i
, 右节点编号是2*i+1
种类
- 满二叉树
除了叶子节点外其它节点都有左右子节点 - 完全二叉树
叶子节点在最底下两层, 最后一层的叶子节点都靠左排列. 除了最后一层其它层的节点个数达到最大
存储方式
- 链式存储法(链表)
- 顺序存储法(数组)
如果一棵树是完全二叉树, 那么使用数组存储是最节省空间的方式
遍历
遍历即将树的所有结点访问一次, 按照节点位置的不同分为前序遍历, 中序遍历, 后序遍历
- 前序遍历: 根节点-->左子树-->右子树 (DBACEGF)
- 中序遍历: 左子树-->根节点-->右子树 (ABCDEFG)
- 后序遍历: 左子树-->右子树-->根节点 (ACBFGED)
# coding:utf-8
"""
二叉树遍历
时间复杂度: O(n)
"""
class BinaryTree(object):
def __init__(self, data, left=None, right=None):
self.data = data
self.left = left
self.right = right
def pre(root):
"""前序遍历"""
if root is None:
return
print(root.data, end="")
pre(root.left)
pre(root.right)
def mid(root):
"""中序遍历"""
if root is None:
return
pre(root.left)
print(root.data, end="")
pre(root.right)
def after(root):
"""后续遍历"""
if root is None:
return
pre(root.left)
pre(root.right)
print(root.data, end="")
def level(root):
"""
按层级遍历, 广度优先遍历
:param root:
:return:
"""
from collections import deque
d = deque([])
d.append(root)
while d:
node = d.popleft()
print(node.data, end="")
if node.left:
d.append(node.left)
if node.right:
d.append(node.right)
if __name__ == '__main__':
root = BinaryTree(
'D',
BinaryTree(
'B',
BinaryTree('A'),
BinaryTree('C')
),
BinaryTree(
'E',
right=BinaryTree(
'G',
BinaryTree('F')
)
)
)
pre(root)
print("
")
mid(root)
print("
")
after(root)
print("
")
level(root)
"""
DBACEGF
BACDEGF
BACEGFD
DBEACGF
"""
广度优先
使用队列
# coding:utf-8
from collections import deque
class Node(object):
def __init__(self, value, left=None, right=None):
self.value = value
self.left = left
self.right = right
def width(root):
if root is None:
return
queue = []
d = deque(queue)
d.append(root)
while d:
node = d.popleft()
print(node.value),
if node.left:
d.append(node.left)
if node.right:
d.append(node.right)
if __name__ == '__main__':
root = Node('D',Node('B',Node('A'),Node('C')),Node('E',right=Node('G',Node('F'))))
width(root)
"""
D B E A C G F
"""
深度优先遍历
使用栈
# coding:utf-8
"""
深度优先遍历
"""
from collections import deque
class Node(object):
def __init__(self, data, left=None, right=None):
self.data = data
self.left = left
self.right = right
def depth(root):
if root is None:
return
res = []
d = deque([])
d.append(root)
while d:
node = d.pop()
res.append(node.data)
if node.right:
d.append(node.right)
if node.left:
d.append(node.left)
return res
if __name__ == '__main__':
root = Node('D', Node('B', Node('A'), Node('C')), Node('E', right=Node('G', Node('F'))))
res = depth(root)
assert res == ["D", "B", "A", "C", "E", "G", "F"]
根据前序遍历和中序遍历, 求后续遍历
分析: 前序遍历的第一个值就是根节点, 然后在中序遍历中找到这个值, 那么这个值的左边部分就是当前二叉树的左子树部分中序遍历结果, 这个值的右边部分就是当前二叉树的右子树部分中序遍历结果. 因此, 通过这个分析, 可以恢复这颗二叉树
#!/usr/bin/env python
# coding:utf-8
pre = list('DBACEGF')
mid = list('ABCDEFG')
after = []
def find_after_tree(pre, mid, after):
if len(pre) == 0:
return
if len(pre) == 1:
after.append(pre[0])
return
# 根据前序遍历得到根节点
root = pre[0]
# 在中序遍历中得到根节点的位置, 那么左半部分就是左子树, 另外是右子树
n = mid.index(root)
find_after_tree(pre[1:n+1], mid[:n], after)
find_after_tree(pre[n+1:], mid[n+1:], after)
# 最后把根节点添加进去
after.append(root)
find_after_tree(pre, mid, after)
print after
"""
['A', 'C', 'B', 'F', 'G', 'E', 'D']
"""
求最大树深
# coding:utf-8
"""
求最大树深
"""
def get_max_depth(root):
if root is None:
return -1
return max(get_max_depth(root.left), get_max_depth(root.right)) + 1
求两个树是否相同
# coding:utf-8
"""
求两个树是否完全相同
"""
def is_same_tree(tree1, tree2):
if tree1 is None and tree2 is None:
return True
elif tree1 and tree2:
return tree1.data == tree2.data and is_same_tree(tree1.left, tree2.left) and is_same_tree(tree1.right,
tree2.right)
else:
return False