树的概念
节点的度:一个节点含有的子节点(A的度 3)
叶节点或终端节点: 度为0的节点(E F C D) 非终端节点或分支节点: 度不为0的节点(A B) 双亲节点或父节点: (A是B C D 的父节点) 孩子节点或子节点: (B C D是A的子节点) 树的度: 最大节点的度(该图数的度 3) 节点的层次: 从根节点(A)开始计算,根为第一层,根的子节点为第二层,以此类推 树的高度或深度:树中节点的最大层次(该图为3)
二叉树
二叉树不存在节点大于2的
满二叉树每层节点达到最大值
满二叉树是一种特殊的完全二叉树
当树的深度为h时
满二叉树节点 : 2^h-1
完全二叉树 : [2^(h-1),2^h-1]
树的节点为N时
满二叉树高度:log(N+1)
完全二叉树: [logN+1,log(N+1)]
任何一个二叉树
度为0的比度为2的多一个
任何一个完全二叉树
度为1的个数只能为0或1
堆
堆是一个完全二叉树,按照完全二叉树顺序储存
根节点最大的叫大根堆或最大堆,所有父节点都大于或等于子节点
最小的叫小根堆或最小堆,所有子节点都小于或等于父节点
二叉树中父子节点关系
parent=(child-1)/2
leftchild=parent*2+1
rightchild=parent*2+2
堆不是有序的
堆排序
排升序 建大堆
排降序 建小堆
向下调整堆时,左右子树必须是大堆或小堆
向上调整堆时,上面的数据必须构成堆
void AdjustDown(HeapDatatype* a, int n)
{
int parent = 0;
int child = parent * 2 + 1;//假设左孩子比右孩子大
while (child<n)
{
//如果右孩子比左孩子大,交换
if (child + 1 < n && a[child + 1] > a[child])//child+1>n防止数组越界
{
child++;
}
if (a[child] > a[parent])
{
Swap(&a[child], &a[parent]);
parent = child;
child = parent * 2 + 1;
}
else
{
break;
}
}
}
void Adjustup(HeapDatatype* a, HeapDatatype child)//向上调整
{
HeapDatatype parent = (child - 1) / 2;
while (child > 0)
{
if (a[child] > a[parent])
{
Swap(&a[child], &a[parent]);//交换
child = parent;
parent = (child - 1) / 2;
}
else
{
break;
}
}
}
//排升序
void HeapSort(int* a, int n)
{
for (int i = 1; i < n; i++)//向上调整建大堆
{
Adjustup(a, i);
}
//排序
int end = n - 1;
while (end>0)
{
Swap(&a[0], &a[end]);
AdjustDown(a, end);
end--;
}
}
向上调整时间复杂度 O(NlogN)
向下调整时间复杂度 O(N)
top k 问题
建小堆 ,堆顶数据就是堆中最小的数,如果出现比堆顶大的就替换,然后向下调整
不能建大堆,因为堆顶是最大的数,如果出现比堆顶小的,但是比堆中数据大就不能替换