算法流程:
可以归纳为两个步骤:
步骤一:构造初始堆。将给定无序序列构造成一个大顶堆(一般升序采用大顶堆,降序采用小顶堆)。
步骤二:将堆顶元素与末尾元素进行交换,使末尾元素最大。然后继续调整堆,再将堆顶元素与末尾元素交换,得到第 二大元素。如此反复进行交换、重建、交换。
#include<iostream>
using namespace std;
void swap(int &a, int &b)
{
int temp = a;
a = b;
b = temp;
}
void max_sink(int *data, int node, int length) //步骤一的过程;
{
if (node >= length / 2) return;
int max_index = node;
int max_data = data[node];
bool max_flag = false;
for (int i = 1; i <= 2; i++)
{
if (max_data < data[node * 2 + i] && node * 2 + i < length)
{
max_data = data[node * 2 + i];
max_index = node * 2 + i;
max_flag = true;
}
}
if (max_flag) //如果发生非叶子节点数值下沉,那么就要递归子下沉非叶子节点
{
swap(data[node], data[max_index]);
max_sink(data, max_index, length);
}
}
void heap_sort(int *data, int length)
{
for (int j = length / 2 - 1; j >= 0; j--) //步骤一:建立一个完整的大根堆;
{
max_sink(data, j, length);
}
for (int count = 1; count < length; count++) //步骤二:在一个完整的大根堆基础上,首尾元素互换之后再调整大根堆;
{
swap(data[0], data[length - count]);
max_sink(data, 0, length-count); //重要!调整堆顶的节点即可,不用遍历所有非叶子节点;
}
}
int main()
{
int data[] = { 0,2,1,3,4,5,2,5,45,67,6,78,12,34,23,4,56 };
heap_sort(data, size(data));
for (int i = 0; i < size(data); i++)
{
cout << data[i] << ",";
}
cout << endl;
system("pause");
return 0;
}