您的位置:首页 > 其它

堆排序

2017-07-23 20:02 113 查看
http://blog.csdn.net/morewindows/article/details/6709644/#reply

参照这个博客写一个最大堆:

父节点与子节点的关系:

堆一般都用数组来表示堆,i结点的父结点下标就为(i – 1) / 2。它的左右子结点下标分别为2 * i + 1和2 * i + 2。如第0个结点左右子结点下标分别为1和2。

堆的增删操作:



堆的插入:

每次插入都是将新数据放在数组最后。可以发现从这个新数据的父结点到根结点必然为一个有序的数列,现在的任务是将这个新数据插入到这个有序数据中。

void MaxHeapFixup(int a[],int i){
int j,temp;
temp = a[i];
j = (i-1)/2;               //父节点             往上
while(j >= 0 && i){        //这个i!=0在这种算法实现上不能省略,下面给出原因
if(a[j] >= temp) break;
a[i] = a[j];
i = j;
j = (i-1)/2;
}
a[i] = temp;
}
void MaxHeapAddNumber(int a[],int i,int val){
a[i] = val;
MaxHeapFixup(a,i);
}


i!=0不能省略的原因,举个例子:第一个插入的数是2(i=0),然后紧接着再插入3(i=1),看插入3这个过程:
i = 1  ;  j = (1-1)/2 = 0 ; 满足while循环,中间不管,到了j = (i-1)/2这一步,i=0 -> j=(0-1)/2 = 0!!所以会出现死循环,这就是i的作用。

堆的删除

按定义,堆中每次都只能删除第0个数据。为了便于重建堆,实际的操作是将最后一个数据的值赋给根结点,然后再从根结点开始进行一次从上向下的调整。调整时先在左右儿子结点中找最小的,如果父结点比这个最小的子结点还小说明不需要调整了,反之将父结点和它交换后再考虑后面的结点。相当于从根结点将一个数据的“下沉”过程。

void MaxHeapFixdown(int a[],int i,int length){
int j,temp;
temp = a[i];
j = 2*i+1;              //往下
while(j < length){
if( j+1 < length && a[j+1] > a[j]) j+=1;
if(a[j] <= temp) break;
a[i] = a[j];
i = j;
j = 2*i + 1;
}
a[i] = temp;
}
void MaxHeapDeleteNumber(int a[],int length){
printf("%d\n",a[0]);
swap(a[0],a[length-1]);      //先把最后一个数据给根节点
MaxHeapFixdown(a,0,length-1);
}


接着是堆建立:

void buildMaxHeap(int a[],int length){
for(int i = length/2-1;i >= 0;i--){
MaxHeapFixdown(a,i,length-1);
}
}


堆排序:

void HeapSort(int a[],int length){
for(int i=length-1;i >= 1;i--){
swap(a[i],a[0]);
MaxHeapFixdown(a,0,i);
}
}


#include <bits/stdc++.h>
using namespace std;
const int AX = 5e4+6;
int a[AX];
int n ;

void Fixdown( int i , int n ){
int j , tmp ;
tmp = a[i];
j = 2 * i + 1;
while( j < n ){
if( j + 1 < n && a[j+1] < a[j] ) j++;
if( a[j] >= tmp ) break;
a[i] = a[j];
i = j;
j = 2 * i + 1;
}
a[i] = tmp;
}

void DeleteNumber( int n ){
swap(a[0],a[n-1]);
Fixdown(0,n-1);
}
void Fixup( int i ){
int j , tmp;
tmp = a[i];
j = ( i - 1 ) / 2 ;
while( j >= 0 && i ){
if( a[j] <= tmp ) break;
a[i] = a[j];
i = j ;
j = ( i - 1 ) / 2;
}
a[i] = tmp;
}

void build_heap(int n){
for( int i = n / 2 ; i >= 0 ; i-- ){
Fixdown(i,n);
}
}

void add( int i , int val ){
a[i] = val;
Fixup(i);
}

void heapSort( int len ){
for( int i = len - 1 ; i ; i-- ){
swap(a[i],a[0]);
Fixdown(0,i);
}
}

int main(){
cin >> n;
for( int i = 0 ; i < n ; i++ ){
cin >> a[i];
}
DeleteNumber(n);
build_heap(n-1);
heapSort(n-1);
for( int i = n - 2 ; i >= 0 ; i-- ){
cout << a[i] << endl;
}
return 0 ;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: