C语言堆排序的实现

来源:互联网 发布:大族激光打标机软件 编辑:程序博客网 时间:2024/05/20 19:14

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

下面实现代码:

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

#define OK 1#define ERROR 0typedef 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 (j < m&&L->data[j] < L->data[j + 1])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;}







0 0
原创粉丝点击