15. 蛤蟆的数据结构进阶十五排序实现之堆排序
本篇名言:“谁要是游戏人生 ,他就一事无成 ;
谁不能主宰自己 ,永远是一个奴隶。--歌德”
继续来看下堆排序。
欢迎转载,转载请标明出处:http://blog.csdn.net/notbaron/article/details/47733553
1. 堆排序
堆排序(Heapsort)是指利用堆积树(堆)这种数据结构所设计的一种排序算法,它是选择排序的一种。可以利用数组的特点快速定位指定索引的元素。堆分为大根堆和小根堆,是完全二叉树。大根堆的要求是每个节点的值都不大于其父节点的值,即A[PARENT[i]]
>= A[i]。在数组的非降序排序中,需要使用的就是大根堆,因为根据大根堆的要求可知,最大的值一定在堆顶。
(a)大顶堆序列:(96,83,27,38,11,09)
(b) 小顶堆序列:(12,36,24,85,47,30,53,91)
如图建堆初始过程:无序序列:(49,38,65,97,76,13,27,49)
2. 代码实现
从一个无序序列建堆的过程就是一个反复筛选的过程。若将此序列看成是一个完全二叉树,则最后一个非终端节点是第[n/2]个元素,由此筛选只需从第[n/2]个元素开始。
代码核心是先将数组假想为完全二叉树。那么偶数位的数是左孩子,奇数位的数是右孩子。
先将数组进行完全二叉树处理,然后将根节点提取出来放到数组最后,将原先数组的最后一个元素放到根节点,因为不能保证原先数组最后一个的元素是剩下元素中最大的,所以要紧接着做一次处理(此次处理将最后一个元素除外)。接下去是继续去根节点放到数组倒数第二个位置,以此循环。
实现如下图1:
3. 源码
#include"stdio.h"
void print(inta[],intn){
for(intj= 0; j<n; j++){
printf("%d",a[j]);
}
}
/**
*已知H[s…m]除了H[s]外均满足堆的定义
*调整H[s],使其成为大顶堆即将对第s个结点为根的子树筛选,
*
* @param H是待调整的堆数组
* @param s是待调整的数组元素的位置
* @param length是数组的长度
*
*/
void HeapAdjust(intH[],ints,
int
length)
{
inttmp = H[s];
intchild = 2*s+1;
//左孩子结点的位置。(i+1为当前调整结点的右孩子结点的位置)
while(child < length) {
if(child+1<length &&
H[child]<H[child+1]){
// 如果右孩子大于左孩子(找到比当前待调整结点大的孩子结点)
++child;
}
if(H[s]<H[child]){ //
如果较大的子结点大于父结点
H[s]=
H[child]; // 那么把较大的子结点往上移动,替换它的父结点
s =child; // 重新设置s ,即待调整的下一个结点的位置
child= 2*s+1;
}
else { // 如果当前待调整结点大于它的左右孩子,则不需要调整,直接退出
break;
}
H[s]= tmp;
// 当前待调整的结点放到比其大的孩子结点位置上
}
// print(H,length);
}
/**
*初始堆进行调整
*将H[length-1]建成堆
*调整完之后第一个元素是序列的最小的元素
*/
void BuildingHeap(intH[],intlength)
{
//最后一个有孩子的节点的位置 i= (length -1) / 2
for (int i= (length -1) / 2 ; i >= 0; --i)
HeapAdjust(H,i,length);
}
/**
*堆排序算法
*/
void HeapSort(intH[],intlength)
{
//初始堆
BuildingHeap(H,length);
//从最后一个元素开始对序列进行调整
for (int i=
length - 1; i > 0; --i)
{
//交换堆顶元素H[0]和堆中最后一个元素
inttemp = H[i];
H[i]= H[0];
H[0]= temp;
//每次交换堆顶元素和堆中最后一个元素之后,都要对堆进行调整
HeapAdjust(H,0,i);
}
}
int main(){
intH[10] = {3,1,5,7,2,4,9,6,10,8};
printf("初始值:\n");
print(H,10);
HeapSort(H,10);
//selectSort(a,8);
printf("\n堆排序后值:\n");
print(H,10);
}
版权声明:本文为博主原创文章,未经博主允许不得转载。