堆排序(heap sort)是对简单选择排序的一种改进,改进的着眼点是:如何减少记录的比较次数。简单选择排序在一趟排序中仅选出最小记录,没有把一趟的比较结果保存下来,因而记录的比较次数较多。堆排序在选出最小记录的同时,也找出较小记录,减少了选择的比较次数,从而提高整个排序的效率。堆排序算法的基本思想如下:
首先将待排序序列构造成一个大根堆,即选出了堆中所有记录的最大者,将它从堆中移走,并将剩余的记录再调整成堆,这样又找出了次小的记录,以此类推,直到堆中只有一个记录。
现在希望算出从小到大堆排序的过程中,每次进行堆调整后(包括构造初始堆),打印输出堆的次序。
【输入形式】
第一行一个整数N, 第二行有N个整数,无序。0<N <= 100
【输出形式】
输出共 N 行。第i行对应第i次堆调整后N-i+1个整数的次序。
【样例输入】
5
2 3 1 5 4
【样例输出】
5 4 1 3 2
4 3 1 2
3 2 1
2 1
1
分析:
堆排序 利用完全二叉树的性质 构建一个大根堆(小根堆)把最大的(最小的)放到根节点 然后把根节点与最后一个结点交换数值
本质上就是利用重复构建大根堆(小根堆)的方法,找到最大(最小)的值 然后利用和最后一个结点交换的方式进行排序
构建堆的函数
void adjust(int arr[],int n,int i)
{
int left=i*2+1;//下标为i的左孩子
int right=i*2+2;//下标为i的右孩子
int maxi = i;
if(left<n&&arr[left]>arr[maxi])
maxi=left;
if(right<n&&arr[right]>arr[maxi])
maxi=right;
if(maxi!=i)//当下标为i 的结点不是它和它孩子节点中最大数时
{
swap(arr[maxi],arr[i]);
adjust(arr,n,maxi);
}
}
排序输出堆的函数
void heapSort(int arr[],int n)
{
for(int i=n/2-1;i>=0;i--)//从第一个非叶子结点开始
{
adjust(arr,n,i);//初始建堆
}
for(int i =0;i<n;i++)
{
cout<<arr[i]<<" ";
}
cout<<endl;
for(int i=n-1,j=n-1;i>=1;i--,j--)//经过初始建堆后 还需n-1次建堆
//每次最大的在树的根节点上
{
swap(arr[0],arr[i]);//把根节点和最后一个结点交换
adjust(arr,i,0);//继续进行排堆 从下标为0的结点开始 对剩下的i个进行堆排序
for(int i=0;i<j;i++)
{
cout<<arr[i]<<" ";//输出堆排序后每次堆调整后的次序
}
cout<<endl;
}
}
主函数
int main()
{
int n;
cin>>n;
int arr[n];
for(int i=0;i<n;i++)
{
cin>>arr[i];
}
heapSort(arr,n);
}
在下是一名小白 如果有不恰当的地方 欢迎指正