堆排序是基于堆(假设为大根堆)的特性来进行排序的方法,
其基本思想是:首先将待排序序列构造成一个堆,此时 ,选出堆中最大的元素即堆顶元素记录,然后将堆顶记录移走,并将剩余的记录再调整成堆,这样再次找出次大的记录,依此类推,直到堆中只有一个记录为止,
思路:1、用一个函数来堆调整,(i,为当前节点,j=i*2为当前节点的左孩子,(2*i)+1为当前节点的右孩子)
1.1 找到当前比较的节点的左右孩子的较大值
1.2 比较当前节点和最大值的大小,小则交换,大则退出函数
1.3 如果交换以后记得 i=j ; j=2*i;
2、从 n/2 开始的节点出开始调整,因为n/2=最后一个非叶子节点的位置!!
代码:
#include <iostream>
#include<stdio.h>
#include <cstdio>
#include<cstring>
using namespace std;
int r[20];
void Sift(int r[],int k,int m){
int i,j,tmp;
i=k,j=2*i; //i为当前节点,j为i 的左孩子
while(j<=m){
if(j<m&&r[j]<r[j+1]){ //左孩子小于右孩子,j指向大的孩子
j++;
}
if(r[i]>r[j]) break; //如果i大于两个孩子,则可以结束了
else{
tmp=r[j];
r[j]=r[i];
r[i]=tmp; //交换
}
i=j;
j=2*i; //交换后要记得改变i和j 的值!!
}
}
int main()
{
for(int i =1;i<9;i++){
scanf("%d",&r[i]);
}
int i,n=8;
for(int i=n/2;i>=1;i--){
Sift(r,i,n);
}
for(int i =1;i<n;i++){
r[0]=r[1];r[1]=r[n-i+1];r[n-i+1]=r[0];
Sift(r,1,n-i);
}
for(int i=1;i<9;i++){
printf("%d ",r[i]);
}
printf("\n");
return 0;
}