题目描述
给定一组数据,使用堆排序完成数据的降序排序。(建小顶堆)。
输入
数据个数n,n个整数数据
输出
初始创建的小顶堆序列
每趟交换、筛选后的数据序列,输出格式见样例
输入样例1
8 34 23 677 2 1 453 3 7
输出样例1
8 1 2 3 7 23 453 677 34
8 2 7 3 34 23 453 677 1
8 3 7 453 34 23 677 2 1
8 7 23 453 34 677 3 2 1
8 23 34 453 677 7 3 2 1
8 34 677 453 23 7 3 2 1
8 453 677 34 23 7 3 2 1
8 677 453 34 23 7 3 2 1
NOTICE:
堆排序要解决两个问题:
1、根据给定序列建堆:按照给定序列的顺序直接放进数组中,从第一个非叶子结点(下标n/2)开始,至第一个结点,每个都进行筛选;
2、交换掉根节点后,将剩下的结点调整为新的堆(筛选):循环n-1次,每次将根节点与最后一个结点交换,并断除根节点与二叉树的联系(如代码中改变tail);筛选根节点;
筛选是算法的核心,需要注意:
1、筛选只有两种情况,一是结点只有左孩子并且左孩子值小于结点值(若为升序则为大于),交换左孩子与结点;二是结点有左右孩子并且结点值小于孩子值,交换结点与孩子中较小者;其他情况均不作交换;
2、筛选完结点后,还要注意交换后可能引起下面的堆结构被破坏,需要检查;从刚刚被交换的结点开始检查,若堆结构被破坏,进行交换,并且继续检查;直到遇到叶子结点或者结点满足堆结构,则检查结束;
#include <iostream>
using namespace std;
void swap(int* a, int* b)
{
int tmp = *a;
*a = *b;
*b = tmp;
}
void shaixuan(int* a, int n, int i)
{
int p;
if (2 * i <= n && 2 * i + 1 > n && a[i] > a[2 * i])
{
swap(&a[i], &a[2 * i]);
p = 2 * i;
}
else if (2 * i <= n && 2 * i + 1 <= n && (a[i] > a[2 * i] || a[i] > a[2 * i + 1]))
{
if (a[2 * i] < a[2 * i + 1])
{
swap(&a[i], &a[2 * i]);
p = 2 * i;
}
else
{
swap(&a[i], &a[2 * i + 1]);
p = 2 * i + 1;
}
}
else
return;
//修改后其他结点有没有变动
while (1)
{
//循环直到叶子节点或者根节点值小于等于子节点值
if (2 * p > n && 2 * p + 1 > n)
break;
if (2 * p <= n && 2 * p + 1 <= n && a[p] <= a[2 * p] && a[p] <= a[2 * p + 1])
break;
if (2 * p <= n && 2 * p + 1 > n && a[p] <= a[2 * p])
break;
if (2 * p <= n && 2 * p + 1 > n && a[p] > a[2 * p])
{
swap(&a[p], &a[2 * p]);
p = 2 * p;
}
else if (2 * p <= n && 2 * p + 1 <= n && (a[p] > a[2 * p] || a[p] > a[2 * p + 1]))
{
if (a[2 * p] < a[2 * p + 1])
{
swap(&a[p], &a[2 * p]);
p = 2 * p;
}
else
{
swap(&a[p], &a[2 * p + 1]);
p = 2 * p + 1;
}
}
}
}
void HeapSort(int* a, int n)
{
//建堆
//从n/2开始逐步筛选
for (int i = n / 2; i >= 1; i--)
{
shaixuan(a, n, i);
}
//输出
cout << n << " ";
for (int i = 1; i <= n; i++)
{
cout << a[i];
if (i == n)
cout << endl;
else
cout << " ";
}
int t = n - 1;//循环n-1次
int tail = n;
while (t--)
{
swap(&a[1], &a[tail--]);
shaixuan(a, tail, 1);
//输出
cout << n << " ";
for (int i = 1; i <= n; i++)
{
cout << a[i];
if (i == n)
cout << endl;
else
cout << " ";
}
}
}
int main()
{
int n;
cin >> n;
int* a = new int[n + 1];//下标从1开始
for (int i = 1; i <= n; i++)
cin >> a[i];
HeapSort(a, n);
return 0;
}