堆排序原理简述及C实现实例

1, 简述

堆结构是一种数组结构,它可以被视为一棵完全二叉树。

 

属性:元素个数(length[A]), 树的根为A[1], 给定某个节点下标i, 其父节点PARENT(i),左儿子LEFT(i),右儿子RIGHT(i).存在以一关系:

        PARENT(i)= i/2;

        LEFT(i) = 2i;

        RIGHT(i) = 2i+1

 

堆应满足以下性质:

        A PARENT(i)]≧A[i];

 

节点高度:从该节点到树的叶节点的最长向下的简单路径上边的数目。

树的高度:根节点高度。

 

2,堆排序

       三个过程

1) heapify过程,运行时间为O(lgn),是用来维持堆性质的关键。

2) build-heap过程,以线性时间运行,可以从无序的输入数组中构造出一个堆来。

3) heapsort过程,运行时间为O(nlgn),对一个数组进程排序。

 

Heapify:维持当前节点与其子节点的堆性质。

Build-heap:将整个数组构建成堆,每个节点均满足堆的性质。

       1 for i=length[A]/2 downto 1

              Do heapify(A, i)

       此过程对每个非叶节点都调用一次heapify,对各节点的处理次序保证了以某个节点i的子节点为根的子树都已成为堆后才处理i.此过程可以认为是线性时间过程,详细证明见算法导论。

 

Heapsort:

       堆中最大元素在A[1],将A[1]与A[n]互换,并将最后一个节点去掉,将剩余元素重新构建成堆。直至堆的大小为2为止。


#include<stdio.h>
#include<stdlib.h>


#define LEFT(i) (i<<1)
#define RIGHT(i) (LEFT(i)|0x1)


#define MAX_LEN 10000
//#define MAX_LEN 100000
int array[MAX_LEN];

void heapify(int *arr,int len, int i);
void swap(int *a, int *b);
void print_array(int *arr);
void init_array(int *arr);
void build_heap(int *arr, int len);

void swap(int *a, int *b)
{
int tmp=*a; *a = *b; *b=tmp;
}


void heapify(int *arr, int len, int i)
{
int max;
if (LEFT(i)<=len&&(arr[i-1]<arr[LEFT(i)-1]))
max = LEFT(i);
else 
max = i;
if (RIGHT(i)<=len&&(arr[max-1]<arr[RIGHT(i)-1]))
max = RIGHT(i);
if (max != i)
{
swap(&arr[max-1], &arr[i-1]);
heapify(arr, len, max);
}
}


void build_heap(int *arr, int len)
{
int i;
for (i=len/2; i>0; i--)
{
heapify(arr, len, i);
}
}


int main(void)
{
time_t ts1, ts2;
int len;
int i;


len = MAX_LEN;
init_array(array);
print_array(array);


time(&ts1);
build_heap(array, len);
for (i=len-1; i>0; i--)
{
swap(&array[0], &array[i]);
build_heap(array, i);
}
time(&ts2);
print_array(array);

printf("time:%lx;%lx;%lx",ts1, ts2,  ts2-ts1);
return 0;
}


void init_array(int *arr)
{
int i;
int val;
for (i=0; i<MAX_LEN; i++)
arr[i] = (int)(((double)random()/RAND_MAX)*MAX_LEN);
//arr[i] = MAX_LEN-i;
}

void print_array(int *arr)
{
int i;
for (i=0; i<MAX_LEN; i++)
{
printf("%-6d", arr[i]);
if (i%20 == 0)
printf("\n");
}
printf("\n");
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值