二叉树堆
void Swap(HPDataType* p1, HPDataType* p2)
{
HPDataType x = *p1;
*p1 = *p2;
*p2 = x;
}
//向上调整
void AdjustUp(HPDataType* a, int child)
{
int 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)
{
//建堆 ---- 向上调整堆 --- o(N*logN)
for (int i = 1; i < n; i++)
{
AdjustUp(a, i);
}
}
int main()
{
int a[10] = { 2, 1, 5, 7, 6, 8, 0, 9, 4, 3}; // 对数组排序
HeapSort(a, 10);
for (int i = 0; i < 10; i++)
{
printf("%d ", a[i]);
}
return 0;
}
i = 1 时
i = 2 时
i = 3 时
i = 4 时
略…
从以上步骤来看,将完全二叉树分成左右两个区块,从第一个孩子结点开始,依靠孩子结点找父亲,然后大的数组往上浮,小的数字往下沉,左边的只扶左边最大的值为根,右边的只扶右边最大的值为根,这种操作我们叫做建大堆。
它的时间复杂度为o(N*logN)
向下调整堆
//左右子树都是大堆/小堆,向下调整
void AdjustDown(HPDataType* a, int n, int parent)
{
int child = parent * 2 + 1;
while (child<n)
{
if (child+1<n && a[child+1]>a[child])
{
++child;
}
if (a[child] > a[parent])
{
Swap(&a[child], &a[parent]);
parent = child;
child = parent * 2 + 1;
}
else
{
break;
}
}
}
//建堆 -- 向下调整建堆 -- o(N)
void HeapSort(int* a, int n)
{
//建堆 -- 向下调整建堆 -- o(N)
for (int i = (n-1-1)/2; i >= 0; --i)
{
AdjustDown(a, n, i);
}
}
int main()
{
int a[10] = { 2, 1, 5, 7, 6, 8, 0, 9, 4, 3}; // 对数组排序
HeapSort(a, 10);
for (int i = 0; i < 10; i++)
{
printf("%d ", a[i]);
}
return 0;
}
略…
从上面的简介图的过程来看,向下取整是从最后一个孩子结点的父亲结点开始向下取整,直到所有的父亲结点都过完一次才结束,大的数字往上浮,小的数字往下面沉,这种操作也叫建大堆
向下取整的时间复杂度为o(N)