c语言堆排序课程设计报告,C语言堆排序的实现

堆排序是一种树形选择排序,在排序过程中,将数组a[]看成一棵完全二叉树,利用双亲节点和孩子节点之间的内在关系,在当前无序的序列中选择关键字最大(或最小)的排序。其空间复杂度为O(1),在最坏的情况下时间复杂度为O(nlog2n)。堆排序是一种不稳定的算法,且只能用于顺序结构,不能用于链式结构;初始建堆所需的比较次数较多,因此记录少的时候不宜采用。堆排序在最坏情况下的时间复杂度比快速排序下最坏的时间复杂度O(n2)更为优秀,当记录比较多的时候较为高效。

下面实现代码:

首先是预定义和类型定义:

#define OK 1

#define ERROR 0

typedef int Status;

typedef int ElemType;

typedef struct{

ElemType *data;

int length;

}SqList;

顺序表的插入:

Status EnSqList(SqList *L,ElemType e,int n)

{

if (L->length > n)

return ERROR;

L->data[L->length + 1] =

e;

L->length++;

return OK;

}

筛选法调整堆:

void HeapAdjust(SqList *L, int s, int m)

{

int j;

ElemType rc;

rc = L->data[s];

for (j = 2 * s; j <= m; j *= 2)

{

if (L->data[j] <

L->data[j + 1] & &j

< m )

j++;

if (rc>=L->data[j])

break;

L->data[s] = L->data[j];

s = j;

}

L->data[s] = rc;

}

声明rc用于储存下标为s的元素的值。初始化j为2*s,使j指向s的左子树,当j小于或等于最大上限m的时候,执行循环:如果j小于m并且下标为j的元素小于其后一个元素时,让j加1使j指向下一个元素,即在s的左右子树总选取最大值并在j中记录其下标;如果左右子树中最大值小于rc的值,则跳出循环,此时s指向rc应该储存的位置,即其双亲节点大于rc,其左右子树节点均小于rc;若左右子树中最大值大于rc的值,则让其子树节点j的值赋值给双亲节点s,然后让s指向其子树节点j。

跳出循环后让rc的值赋值给下标为s的节点。

建初堆:

void CreatHeap(SqList *L)

{

int i;

for (i = L->length / 2; i >=

1;i--)

HeapAdjust(L, i,L->length);

}

从最后一个节点的双亲节点开始,逐步调用HeapAdjust()以创建大根堆,以确保以i为双亲节点的树是大根堆(从图上来看,是从底层到顶层创建大根堆的做法)。

堆排序算法的实现:

void HeapSort(SqList *L)

{

int i;

ElemType x;

CreatHeap(L);

for (i = L->length; i > 1;

--i)

{

x = L->data[1];

L->data[1] =L->data[i];

L->data[i] = x;

HeapAdjust(L, 1, i - 1);

}

}

先引用CreatHeap()函数对数组进行排序,使其成为大根堆,而后,交换下标为1和最后一个元素(即下标i元素)的值,因为堆排序的结果得到的是一个小根堆,并且在数组中呈递增,,而此时下标为1的元素保存着最大元素的值,而最后一个元素(下标为i的元素)保存着最小元素的值,故将其对调后,最后一个元素(下标为i的元素)保存的必然是最大元素,已经达到目的位置,让i减一(往前移动一位),令原来i的前一位为最后一个数据继续进行堆排序(类似于将未排序完成的元素作为一个数组,排序完成的元素作为一个数组,排序时不对已经排序完成的数组进行操作,仅仅对未排序的数组进行堆排序,结束的时候将最后一位,即排序归并到排序完成的数组中)。

加入main()函数:

int main(void)

{

SqList L;

ElemType e;

int i, n;

L.length = 0;

printf("输入元素个数:");

scanf("%d", &n);

L.data = (int *)malloc(sizeof(int)*n);

srand((int)time(0));

for (i = 0; i < n; i++)

{

e = rand();

EnSqList(&L, e, n);

}

printf("排序前数组:");

for (i = 0; i < L.length; i++)

printf("%d ",L.data[i + 1]);

printf("\n");

HeapSort(&L);

printf("排序后数组:");

for (i = 0; i < L.length; i++)

printf("%d ",L.data[i + 1]);

printf("\n");

return 0;

}

a4c26d1e5885305701be709a3d33442f.png

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值