#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
/* 1).从小到大排序,建立最小堆
* 然后每次删除顶部元素并将顶部元素输出或存储起来
* 直到堆空为止
* 2).从小到大排序,建立最大堆
* 最大对建好后,最大元素在vec[1],vec[1]得放置末尾,需将vec[number]与vec[1]交换
* 交换后还需将vec[1]向下调整保持堆的特性,需要将堆的大小减1,如此反复,直到堆的大小变成1
*/
static std::vector<int> * vec;
static int number;
void Swap(int & index1,int & index2)
{
int temp = (*vec)[index1];
(*vec)[index1] = (*vec)[index2];
(*vec)[index2] = temp;
return;
}
void SiftDown(int & index)
{
int t, flag = 0;
while (index*2<=number && flag==0)
{
//判断与左儿子的关系
if ((*vec)[index]>(*vec)[index*2])
{
t = index * 2;
}
else
{
t = index;
}
//判断与右儿子关系
if (index * 2 + 1 <= number)
{
if ((*vec)[index * 2 + 1] < (*vec)[t])
{
t = index * 2 + 1;
}
}
//如果t与index不相等,说明子节点中有比父节点小的,交换两值
if (t!=index)
{
auto * pS = Swap;
pS(index,t);
index = t; //更换换下标,继续向下调整
}
else
{
flag = 1; //说明当前父节点已经比两个子节点都要小了,不需要进行调整了
}
}
return;
}
void Create()
{
/*
* 首先我们从叶结点开始,因为叶结点没有儿子,所以所有以叶节点为根结点的子树(只有一个结点)
* 都符合最小堆的特性,即父节点的值比子节点的值小,叶节点连子节点都没有,当然符合
* 因此所有叶节点都不需要处理,直接跳过,从第 (number/2)个结点开始处理
*/
auto * pS = SiftDown;
for (int i=number/2;i>=1;i--)
{
pS(i);
}
return;
}
int * DeleteMax()
{
int temp = (*vec)[1];
(*vec)[1] = (*vec)[number];
number--;
int p = 1;
int & index = p;
auto * pS = SiftDown;
pS(index);
return &temp;
}
//堆排序
void HeapSort()
{
while (number<1)
{
int p = 1;
int & index = p;
Swap(index,number);
number--;
auto * pS = SiftDown;
pS(index);
}
return;
}
int main()
{
vec = new vector<int>();
std::cin >> number;
::fill_n(::back_inserter(*vec), (number+1),0);
for (int i = 1; i <= number; i++)
std::cin >> (*vec)[i];
auto * pC = Create;
pC();
int n = number;
auto * pD = *DeleteMax;
for (int i = 1; i <= n; i++)
std::cout << *pD() << std::endl;
delete vec;
vec = nullptr;
::getchar(); ::getchar();
return 0;
}
/*
测试用例:
14
99 5 36 7 22 17 46 12 2 19 25 28 1 92
*/
堆排序
最新推荐文章于 2021-07-24 23:27:25 发布