1、算法原理
原理部分参考下面这个博客即可:
堆排序算法(图解详细流程)
2、C++实现:
解法一:利用vector实现最大堆
注意:heap_max这个函数调用了两次: 建堆时候和交换最大值之后分别调用一次:
//注意:是把一个数组想象成了最大堆!!!!!!
//利用最大堆这种数据结构进行排序:先构建个最大堆,
//然后将根节点与数组最后一个元素交换,然后对剩下的N-1个元素进行迭代(建堆、交换)
void heap_sort(vector<int> &input)
{
//build_heap(input);
// 1、先建堆!!!!!!!
//从第一个非叶子节点开始调整的原因在于叶子节点没有孩子,那么显然它也就满足堆的性质,也就没有调整的必要了。
for(int i=input.size()/2-1;i>=0;i--)//根节点为0,最后一个叶节点的下标为n-1,
//其父节点是第一个非叶节点,下标为((n-1)-1 )/ 2 = (n-2)/2 = n/2 - 1
{
heap_max(input,i,input.size()); //建堆时候这个参数n(第三个参数)一直不变,但是i在变
}
///2、把最大元素移除 接着进行见堆!!!!
for(int j=input.size()-1;j>0;j--) //这里的j是大于0 没有等于
{
// 将根节点(最大值)与数组待排序部分的最后一个元素交换,这样最终得到的是递增序列
int temp;
temp = input[0];
input[0] = input[j];
input[j] = temp;
// 待排序数组长度减一,只要对换到根节点的元素进行排序,将它下沉就好了。
heap_max(input,0,j); //这个时候i这个参数不变,但是参数n(j)一直在变
}
}
// void build_heap(vector<int> &input) //构建最大堆
// {
// //从第一个非叶子节点开始调整的原因在于叶子节点没有孩子,那么显然它也就满足堆的性质,也就没有调整的必要了。
// for(int i=input.size()/2-1;i>=0;i--)//根节点为0,最后一个叶节点的下标为n-1,
// //其父节点是第一个非叶节点,下标为((n-1)-1 )/ 2 = (n-2)/2 = n/2 - 1
// {
// heap_max(input,i,input.size());
// }
// }
void heap_max(vector<int> &input, int i,int n)//将i节点为根的堆中大的数依次上移,n表示堆中的数据个数
{
int left = 2*i+1; // i节点的左孩子
int right = 2*i+2; // i节点的右孩子
int largest = i; //先设置父节点和子节点三个节点中最大值的位置为父节点下标
if(left<n&&input[left]>input[largest])
{
largest = left;
}
if(right<n&&input[right]>input[largest])
{
largest = right;
}
if(largest!=i) //最大值不是父节点,则进行交换
{
int temp;
temp = input[i];
input[i] = input[largest];
input[largest] = temp;
heap_max(input,largest,n); //递归调用,保证子树也是最大堆
}
}
解法二:利用STL的优先级队列
//堆排序解法二:利用STL的优先级队列
void heap_sort2(vector<int> &input)
{
//priority_queue< int, vector<int>, greater<int> > a; // 小顶堆
//priority_queue< int, vector<int>, less<int> > q; // 大顶堆
priority_queue<int> a; //默认是大顶堆
for(int i=0;i<input.size();i++)
{
a.push(input[i]);//优先级队列在push的时候就已经自动排序了,最大值在第一个,后面的没有排序
}
for(int j=0;j<input.size();j++)
{
input[input.size()-1-j] = a.top(); //把最大值给到最后一个
//input[j] = a.top();//小顶堆是直接对应赋值
a.pop();
}
}
解法三:利用#include <algorithm 里的把迭代器指定的range当堆 以及make_heap、push_heap、pop_heap、sort_heap
void heap_sort3(vector<int> &input)
{
//make_heap(input.begin(),input.end(), less<int>());//创建大顶推 此时向量第一个元素为最大值
//make_heap(input.begin(),input.end(), greater<int>());//创建小顶推 此时向量第一个元素为最小值
for(int i=0;i<input.size()-1;i++)
{
make_heap(input.begin()+i,input.end(), greater<int>());
}
}
参考文献: