排序有很多种,堆排序的耗时是nlogn的现在学习一下。
一开始我尝试运用链表来建立一个堆,但是发现,对于一个堆来说,我们正常的输入都是按照层序输入的,但是层序建堆感觉非常不好建如果用链表的话,还要在输入的时候先进行一次先序或中序或后序变化才行,这增加了许多麻烦,因此放弃链表建堆了,改用数组建堆,就可以实现层序输入了;
对于一个数组,从0开始是他的根节点,那么他的子节点就分别是2*1-1和2*1,因此,对于每个父节点n他的子节点就分别是2*(n+1)-1和2*(n+1)。同理,一个子节点n的父节点就是(n-1)/2;
这样看下去,每个节点都有与之对应的下标,然后在进行堆排序;
1.输入一个无序数组;
2.排成一个大顶堆(根节点大于等于任意子节点)或者小顶堆(根节点小于等于任意子节点);
3.进行排序;
#include<stdio.h>
#include<string.h>
#include<math.h>
//#include<map>
#include<set>
#include<deque>
#include<queue>
#include<stack>
#include<string>
#include<iostream>
#include<algorithm>
using namespace std;
#define ll long long
#define da 0x3f3f3f3f
#define clean(a,b) memset(a,b,sizeof(a))// 水印
/*5 4 6 8 5 9
4
6 8
5 9
9 9 5 1 3 2 6 4 8 7
9 1 2 3 4 5 6 7 8 9
*/
void swap(int *shuzu,int i,int j)//交换函数 i,j;
{
int temp=shuzu[i];
shuzu[i]=shuzu[j];
shuzu[j]=temp;
}
void adjust_heap(int *shuzu,int i,int n)
{
int temp=shuzu[i];//取该节点的值
int k,j;
for(k=i*2+1;k<n;k=k*2+1)//根节点是 0,那么子节点分别是(n+1)*2-1,(n+1)*2;
{//找第一个子节点,该子节点找该子节点的 第一个子节点
if(k+1<n&&shuzu[k]<shuzu[k+1])//该节点有右节点&&右节点>左节点
++k;//选取右节点
if(shuzu[k]>temp)//最大的节点是否大于父节点
{
shuzu[i]=shuzu[k];//父节点取最大值
i=k;//以该点为父节点再次调整
}
else
break;//符合大顶堆结束
}
shuzu[i]=temp;//最后找到的节点放入初始值
}
void sort_heap(int *shuzu,int n)
{
int i,j;
for(i=n/2-1;i>=0;--i)//从最后一个父节点开始 建立一个大顶堆
adjust_heap(shuzu,i,n);//调整该节点
for(j=n-1;j>0;--j)//每次交换堆顶的最大值至堆尾 ,然后该点超脱(不再参与排序)
{
swap(shuzu,0,j);
adjust_heap(shuzu,0,j);//调整大顶堆符合要求 大数放置后面
}
}
int main()
{
int n,shuzu[110];
cin>>n;
int i,j;
for(i=0;i<n;++i)
cin>>shuzu[i];
sort_heap(shuzu,n);//从小到大排序
for(i=0;i<n;++i)
cout<<shuzu[i]<<" ";
}