堆排序的实现
堆排序看了很久,并未实现。这次把编程珠玑和课本上的方法拿来一起温习
//堆排序
#include<iostream>
using namespace std;
void sift(int a[],int low,int high)
{
int i=low,j=2*i;
int tmp=a[i];
while(j<=high)
{
if(j<high&&a[j]>a[j+1])
j++; //j指示孩子结点中较小的节点
if(tmp>a[j])
{
a[i]=a[j]; //a[j]调整到双亲结点
i=j; //修改i和j的值,继续向下筛选
j=2*i;
}
else
break;
}
a[i]=tmp;
}
void SiftSort(int a[],int n)
{
int tmp;
for(int i=n/2;i>0;i--) //生成初始的小根堆
sift(a,i,n);
for(int i=n;i>1;i--)
{
tmp=a[1]; //将最后一个元素和第一个元素交换
a[1]=a[i];
a[i]=tmp;
sift(a,1,i-1); //交换后可能不满足堆的性质,需要重新生成i-1个元素的堆
}
}
void siftup(int a[],int n) //假定a[1]~a[n-1]已是小根堆,从堆的最底层插入新的结点,有可能破坏堆的性质,所以需要从堆底向堆顶判断是否符合堆的性质,
//若不符合则要交换结点,使其满足堆的性质
{
int tmp;
int p;
int i=n;
while(1)
{
if(i==1)
break;
p=i/2;
if(a[i]>a[p])
break;
else
{
tmp=a[i];
a[i]=a[p];
a[p]=tmp;
}
i=p;
}
}
void siftdown(int a[],int n) //将堆的第一个元素和最后一个元素交换后,可能造成第一个元素到倒数第二个元素不满足堆的性质。需要从上到下维护堆
{
int j,tmp, i=1;
while(i<n)
{
j=2*i;
if(j>n)
break;
if(j+1<=n&&a[j]>a[j+1])
j++;
if(a[i]>a[j])
{
tmp=a[i];
a[i]=a[j];
a[j]=tmp;
}
else
break;
i=j;
}
}
void SiftSort2(int a[],int n)
{
int tmp;
for(int i=1;i<=n;i++)
siftup(a,i);
for(int i=n;i>=1;i--)
{
tmp=a[1];
a[1]=a[i];
a[i]=tmp;
siftdown(a,i-1);
}
}
int main()
{
int a[]={0,2,3,4,1,9,7,8,6,5};
SiftSort(a,9);
cout<<"第一种堆排序方法:"<<endl;
for(int i=1;i<=9;i++)
cout<<a[i]<<" ";
cout<<endl;
cout<<"第二种堆排序方法:"<<endl;
int b[]={0,2,3,4,1,9,7,8,6,5};
SiftSort2(b,9);
for(int i=1;i<=9;i++)
cout<<b[i]<<" ";
return 0;
}
浙公网安备 33010602011771号