堆排序
堆有两种分类,一种是大根堆,一种是小根堆;
大根堆
- 父亲节点的值均大于孩子结点的值
- 构建的这个堆必须是满二叉树
小根堆
- 父亲结点的值均小于孩子节点的值
- 构建的堆必须是满二叉树
思想:我们首先必须构建出堆;把数字先像二叉树一样排列好,如下:
接下来我们需要调整成为大根堆,从0号位置开始和它的子节点c1和c2比较,和它们中最大的换,接续和下面的孩子比较,如果比孩子小,继续换,我们这样就可以构建出最大堆。
构建出堆之后,我们把跟结点的和最后一个交换,输出最后一个,继续调整剩下的堆,然后继续把根节点和最后一个交换,直到输出完
代码如下:
void heap(int *arr, int n,int i) //父节点和子节点交换
{
if (i >= n)
{
return;
}
int c1 = i * 2 + 1;
int c2 = i * 2 + 2;
int max = i;
if (c1 < n && arr[c1] > arr[max])
{
max = c1;
}
if (c2 < n && arr[c2] > arr[max])
{
max = c2;
}
if (max != i)
{
swap(arr[max], arr[i]);
heap(arr, n, max);
}
}
void buildheap(int *arr, int n) //从第一个不是叶子几点调整堆,使其变为大根堆/小根堆
{
int last_node = n - 1;
int i = (last_node - 1) / 2;
for (; i >= 0; i--)
{
heap(arr, n, i);
}
}
void heapsort(int *arr, int n) //根结点和最后一个交换,将剩下的继续调整
{
buildheap(arr, n);
for (int i = n - 1; i >= 0; i--)
{
swap(arr[i], arr[0]);
heap(arr, i,0);
}
}