1.二叉树
高级数据结构之根基,效率极高
适合复杂操作:区间(查询、更新、合并)、分治等等
二叉树性质:每个节点最多有两个子节点:左孩子和右孩子,以它们为根的子树称为左子树、右子树。
二叉树的每个节点不必全有左、右孩子,可以只有一个孩子或没有孩子,没有孩子的节点称为叶子节点
二叉树的第i层,最多有2^(i-1)个节点
有n个点的平衡二叉树,共有O(logn)层
2.二叉树分类
平衡二叉树:在平衡二叉树上能进行极高效率的访问
高级数据结构可近似为基于二叉树的数据结构
满二叉树
每一层的节点都是满的
完全二叉树
只在最后一层有缺失,缺失的编号都在最后
不平衡二叉树:"链状"二叉树,每一层都缺失很多节点,退化成一个长链条状,失去了二叉树的天然优势
3.完全二叉树的权值
求哪个深度的节点权值和最大?
示例
输入:
7
1 6 5 4 3 2 1
输出:
2
import math
n=int(input())
c=int(math.log(n,2))+1 #一共有c层
a=[0]+list(map(int,input().split())) #a[1]~a[n]
s=[0]*(c+1) #记录每层的和,s[1]~s[c]
for i in range(1,c+1):
s[i]=sum(a[2**(i-1):2**i-1 +1]) #注意切片范围
print(s.index(max(s)))
4.二叉树的存储
普通做法:二叉树的一个节点,包括节点的值,以及指向左右子节点的指针
def __init__(self,s,l=None,r=None):
self.val=None #节点的值
self.l=l #指向左右孩子的存储位置
self.r=r
竞赛做法:为了编码简单,加快速度,用静态数组实现二叉树
定义静态数组:tree=[‘’]N
根节点:tree[1]
节点tree[p]的左子节点:tree[2p]
节点tree[p]的右子节点:tree[2*p+1]
5.二叉树的遍历
下面我们用这样一棵树作例子:
宽度优先遍历
一层层地遍历二叉树,用队列实现
出队列的顺序是:EBGADFICH
深度优先遍历
三种方式:
先(根)序遍历
def preorder(p):
print(tree[p],end='') #先打印根节点
if tree[2*p] !='':preorder(2*p) #采用递归,如果左孩子不为空则执行
if tree[2*p+1] !='':preorder(2*p+1)
还是上面的例子,顺序是:EBADCGFIH
中(根)序遍历
def inorder(p):
if tree[2*p] !='': inorder(2*p) #先左
print(tree[p],end='') #再根
if tree[2*p+1] !='': inorder(2*p+1) #后右
顺序是:ABCDEFGHI,结果是字典序!
后(根)序遍历
def postorder(p):
if tree[2*p] !='':postorder(2*p) #左
if tree[2*p+1] !='':postorder(2*p+1) #右
print(tree[p],end='') #根
顺序是:ACDBFHIGE
可以通过二叉树的“中序遍历+先序遍历”或“中序遍历+后序遍历”来确定一棵树,但是只有“先序遍历+后序遍历”不能确定一棵树。