堆排序
优先队列的结构是节点i的孩子为2*i和2*i+1节点,大顶堆要求父节点大于等于其2个子节点,小顶堆要求父节点小于等于其2个子节点。优先队列可以以O(NlogN)时间进行排序,基于该思想的算法叫做堆排序。
首先将数组构造成一个大顶堆,然后在每次deleteMax之后,堆缩小了1,让最后的单元存放刚刚删去的元素,直至最后删掉堆中所有元素,即可得到非递减序列。
堆排序不是稳定排序,是原地排序。
/************************************堆排序*************************************/
#include <vector>
#include <iostream>
using namespace std;
void heapSort(vector<int> &a); //堆排序
int leftChild(int i); //得到左孩子
void percDown(vector<int> &a,int i,int n); //维持一个大顶堆
int main()
{
vector<int> ivec(5);
for(size_t i=0;i<ivec.size();i++)
cin>>ivec[i];
heapSort(ivec);
for(size_t i=0;i<ivec.size();i++)
cout<<ivec[i]<<"\t";
system("pause");
return 0;
}
/*堆排序
* 输入a:待排序的数组
*/
void heapSort(vector<int> &a)
{
for(int i=a.size()/2;i>=0;i--) //将a改成一个大顶堆
percDown(a,i,a.size());
for(int j=a.size()-1;j>0;j--) //循环,
{
swap(a[0],a[j]); //将大顶堆第一个元素和最后一个元素交换
percDown(a,0,j-1); //维持一个大顶堆
}
}
/*求左孩子节点
*/
int leftChild(int i)
{
return 2*i;
}
/*维持一个大顶堆
*输入a:待排序的数组
* i:维持大顶堆的起始位置
* n:大顶堆的节点数目
*/
void percDown(vector<int> &a,int i,int n)
{
int child;
int tmp=a[i]; //暂存父节点的值
while(leftChild(i)<n)
{
child=leftChild(i);
if(child!=n-1&&a[child]<a[child+1]) //如果有右孩子,看左孩子值大还是右孩子值大
child++; //child 为节点值大的孩子
if(tmp<a[child]) //如果父节点没有孩子节点值大
a[i]=a[child]; //交换孩子节点和父节点
else
break;
i=child; //继续修改下面的节点
}
a[i]=tmp; //将tmp暂存的值给最后的i节点
}