完整代码戳这里
【1】在一个关键码集合中挑选具有最小或最大关键码的元素进行处理的数据结构称为优先队列,堆(heap)也称为优先队列,堆的所有元素按照完全二叉树的顺序存储在一个一维数组中,同队列一样,堆在堆底插入元素,在堆头删除元素。
【2】堆可分为大堆和小堆。大堆:父亲节点大于等于其孩子节点;小堆:父亲节点小于等于其孩子节点。对于父亲节点和孩子节点两者之间关系(child=2*parent+1; parent=(child-1)/2)
【3】建立堆
思想:
- 明确所建的是大堆还是小堆(大堆:父亲节点大于孩子节点)
- 从第一个非叶子结点建立
- 建立向下调整算法:
- 1.找出孩子节点较大值和父亲节点相比较,大于父亲节点则交换
- 2.父亲节点和孩子节点若交换,可能会影响后面的堆结构,所以要沿着堆向下调整,循环比较
typedef int Datatype;
void AdjustDown(Datatype* a, size_t n, int root)//向下调整
{
int parent = root;
int child = (root * 2 + 1);//左孩子
while (child < n)
{
if (a[child] < a[child+1] && (child < n))//比较左右孩子大小。取较大值
{
++child;
}
if (a[parent] < a[child])//父亲和较大值比较一次后,可能影响后面的左右子树,所以重复比较,向下调整
{
Datatype tmp = a[child];
a[child] = a[parent];
a[parent] = tmp;
parent = child;
child = parent * 2 + 1;
}
else
break;
}
}
void MakeHeap(Datatype* a,size_t n)//建堆
{
int i = (n - 2) / 2;
for (; i >= 0; i--)
AdjustDown(a, n, i);
}
void TestHeap()
{
int a[] = { 1,2,3,19,4,5,6,7,8,9 };
printf("初始数组>");
for (int i = 0; i < sizeof(a) / sizeof(a[0]); i++)
{
printf("%d ", a[i]);
}
printf("\n");
MakeHeap(a, sizeof(a) / sizeof(a[0]));
printf("大堆>");
for (int i = 0; i < sizeof(a) / sizeof(a[0]); i++)
{
printf("%d ", a[i]);
}
}
堆的应用:
堆—-优先级队列
海量数据top-k问题
堆排序