二叉树的顺序结构
普通的二叉树是不适合用数组来存储的,因为可能会存在大量的空间浪费。而完全二叉树更适合使用顺序结构存储。现实中我们通常把堆(一种二叉树)使用顺序结构的数组来存储,需要注意的是这里的堆和操作系统虚拟进程地址空间中的堆是两回事,一个是数据结构,一个是操作系统中管理内存的一块区域分段。
堆的概念及结构
如果有一个关键码的集合K={k1,k3,k3,···,kn-1,},把它的所有元素按完全二叉树的顺序存储方式存储在一个一维数组中,并满足:ki<=k2i+1且ki<=k2i+2(ki>=k2i+1且ki>=k2i+2)i=0,1,2···,则称为小堆(或大堆)。将根结点最大的堆叫做最大堆大根堆,根节点最小的堆叫做最小堆或小根堆。
堆的性质:
- 堆中某结点,的值总是大于或不小于某父节点的值。
- 堆总是一颗完全二叉树。
实现代码
升序小根堆示例
#include<stdio.h>
//升序,建小堆
//交换数据
void Swap(int* p1, int* p2)
{
int tmp = *p1;
*p1 = *p2;
*p2 = tmp;
}
//向下调整
void AdjustDown(int* a,int n,int root)
{
int parent = root;
int child = parent*2+1;
while (child < n)
{
if (a[child] > a[child + 1] && child + 1 < n)
{
child++;
}
else if (a[parent] > a[child])
{
Swap(&a[parent], &a[child]);
parent = child;
child = parent * 2 + 1;
}
else
{
break;
}
}
}
//堆排序
void HeapSort(int* a,int n)
{
for (int i = (n - 1 - 1) / 2; i >= 0; i--)
{
AdjustDown(a, n, i);
}
int end = n - 1;
while (end > 0)
{
Swap(&a[0], &a[end]);
//再次选次小
AdjustDown(a, end, 0);
end--;
}
}
int main()
{
int a[] = { 27,15,19,18,28,34,65,49,25,37 };
HeapSort(a, sizeof(a) / sizeof(int));
for (int i = 0; i< sizeof(a) / sizeof(int);i++)
{
printf("%d ", a[i]);
}
}