以前写过一个堆排序,但是实话实说,根本不知所云。
今天看了算法导论 关于堆排序的讲解,就实现了一下。
在《算法导论》中关于堆排序的描述是:像合并排序而不像插入排序,运行时间为O(n*logn)。
是一种原地排序算法:在任何时间只有常数个数据在数组外面。
堆排序操作的重要伪代码:
1:保持堆的性质;
MAX-HEAPIFY(A,i)
1 l <- LEFT(i)
2 r <- RIGHT(i)
3 if l<=heap-size(A) and A[l] > A[i]
4 then largest <- l
5 else largest <- i
6 if r<=heap-size(A) and A[r] > A[i]
7 then largest <- r
8 if largest != i
9 then exchange A[i]<->A[largest]
10 MAX-HEAPIFY(A,largest)
2:建堆
BUILD-MAX-HEAP(A)
1 heap-size[A] <- length[A]
2 for i <- length[A]/2 downto 1
3 do MAX-HEAPIFY(A,i)
3:排序
HEAP-SORT(A)
1 BUILD-MAX-HEAP(A)
2 for i <- length[A] downto 2
3 do exchange A[1] <-> A[i]
4 heap-size[A] <- heap-size[A]-1
5 MAX-HEAPIFY(A,1)
算法导论中讲解的是最大堆,我实现的是最小堆,其实两者的操作区别不大:
#include<stdio.h>
#include<stdlib.h>
#define TRUE 1
#define FALSE 0
int length;
int parent(int i)
{
return i/2;
}
int left(int i)
{
return 2*i;
}
int right(i)
{
return 2*i+1;
}
void swap(int *group,int i,int k)
{
int temp;
temp = group[i];
group[i]=group[k];
group[k]=temp;
}
//调整堆
void heap_adjust(int group[],int i)
{
int l,r,smallest;
l = left(i);
r = right(i);
if(l<=length && group[l]<group[i])
smallest = l;
else
smallest = i;
if(r<=length && group[r]<group[smallest])
smallest = r;
if(smallest != i)
swap(group,i,smallest);
}
//建立一个堆
void build_heap(int group[])
{
int i;
for(i=length/2;i>=1;i--)
{
heap_adjust(group,i);
}
}
//输出堆中最小的元素
int heap_min(int group[])
{
int min;
if(length<1)return FALSE;
min = group[1];
group[1]=group[length];
length-=1;
heap_adjust(group,1);
return min;
}
//增加堆中某一元素的数值,注意是增加
void heap_increase(int group[],int i,int key)
{
if(key < group[i])return ;
else
{
group[i]=key;
while(i>1&&group[parent(i)]<group[i])
{
swap(group,i,parent(i));
i=parent(i);
}
}
}
//向堆中添加元素
void heap_insert(int group[],int key)
{
length += 1;
group[length] = -999999;
heap_increase(group,length,key);
}
//堆排序
void heap_sort(int *group)
{
int i;
build_heap(group);
for(i=length;i>=2;i--)
{
swap(group,1,i);
length--;
heap_adjust(group,1);
}
}
int main()
{
int *group;
int i,n;
scanf("%d",&n);
group = (int*)malloc(sizeof(int)*(2*n+1));
for(i=1;i<=n;i++)
scanf("%d",group+i);
length = n;
heap_sort(group);
for(i=1;i<=n;i++)
printf("%d ",*(group+i));
return 0;
}