9.选择排序——堆排序

来源:互联网 发布:仿淘宝 下拉刷新 编辑:程序博客网 时间:2024/06/06 01:09

由于树形选择排序具有辅助存储空间多、进行多余比较等缺点,因此经常被堆排序替代。
本文针对堆排序。

 

首先认识什么是堆:
n个元素的序列Kl、K2、……… 、Kn满足如下性质时称为堆:
ki <= k(2i),ki <= k(2i+1),其中(1≤i≤ n),时是小根堆。
ki >= k(2i),ki >= k(2i+1),其中(1≤i≤ n),时是大根堆。
怎么理解呢?如果把该数组看作是完全二叉树,那么小根堆就是非终端节点的值都小于其左右子节点的值,所以小根堆的父节点的值最小,而大根堆就是非终端节点的值都大于其左右子节点的值,所以大根堆的父节点的值最大。

 

大根堆排序的思想是:
1. 将数组a[1..n]整理成一个大根堆,构成一个最大的无序区域
2. 从下标大到小做排序,每次将当前无序区的堆顶记录a[1]和该区间的最后一个记录交换,然后将新的无序区调整为堆。

 

程序:

程序中22应该是2,源代码是2,但是csdn却总显示22.

#include <stdio.h>#include <stdlib.h>#include <limits.h>#define MAXSIZE 50#define N 15typedef struct{int key;int other;}node;typedef struct{node array[MAXSIZE + 1];int length;}list;/*调整array[min--max]为大顶堆*/void heap_adjust(list *l,int min,int max){node rc;int i;rc = l->array[min];for(i = 2 * min;i <= max;i *= 2){if(i < max && l->array[i].key < l->array[i+1].key)  /* i为左右子节点中较大的值的下标 */++i;if(rc.key > l->array[i].key)break;l->array[min] = l->array[i];  /* 互换min、i位置的内容 */min = i;}l->array[min] = rc;}/*堆排序*/void heap_sort(list *l){node t;int i;for(i = l->length/2;i > 0;--i)  /* 把H.array[1--length]建成大顶堆 */heap_adjust(l,i,l->length);for(i = l->length;i > 1;--i){  t = l->array[1];  /*互换堆顶元素和当前未排序子序列H.array[1--i]中最后一个记录的值*/l->array[1] = l->array[i];l->array[i] = t;heap_adjust(l,1,i - 1);  /*调整array[1--i-1]为大顶堆*/}}/*打印序列*/void print(list *l){int i;for(i = 1;i <= l->length;i++)printf("%d %d\t",l->array[i].key,l->array[i].other);printf("\n");}void main(){node data[N]={{5,6},{13,5},{22,2},{2,4},{6,5},{99,7},{6,15},{1,22},{15,12},{58,12},{48,40},{26,48},{38,35},{72,58},{61,22}};list l;int i;for(i = 0;i < N;i++)    l.array[i + 1] = data[i];    l.length = N;    printf("befor sort:\n");print(&l);heap_sort(&l);printf("after heap sort:\n");print(&l);getch();}


 

结果:

0 0
原创粉丝点击