Heap排序法(改进 选择排序法)(数据结构)

问题引入

        选择排序法每次从未排序对象中选择最小值,插入已排序对象的后端,主要问题在大量未排序对象中寻找最小值,数量过大则影响速度。如果可以加快最小值寻找速度,则可提高选择排序法排序速度。基于此,Heap排序法让搜寻的路径由树根至最后一个树叶,而不是整个未排序部份,从而加快最小值寻找速度。

问题分析

        Heap排序法使用Heap Tree(堆积树),树是非线性结构,堆积树Heap Tree是一个二叉树。堆积树每一个双亲节点值若小于子节点,则称为最小堆积(Min Heap)。每一个双亲节点值若大于子节点,则称之为最大堆积(Max Heap),同一层的子节点不在意其大小关系,也即类似于“小顶堆和大顶堆”特点。

        例如,下图为一个堆积树:

         使用一维数组储存堆积树的所有元素及对应顺序,为方便计算,设置起始索引为1,相当于树根位置。如果左子节点储存在阵列中的索引为 i,则其双亲节点的索引为 i/2,而右子节点为 i+1,(不太清楚的伙伴可以复习一下 树 相关概念哦)。例如上图,存储在一维数组后为:

        那么,如何建立堆积树?也就是创建“小顶堆”的过程(不太清楚的伙伴可以复习一下 堆 相关概念哦)。例如下图创建最小堆积树,则每次检查双亲节点和子节点,若双亲节点值是否小于子节点值,将小的元素不断与双亲节点交换,直到满足堆积树的条件为止(条件:双亲结点值必定小于子节点值)。

        建立好堆积树之后,树根一定是整个树的最小值。

        我们的目的是: 取出最小值(树根),同时剩下的元素继续按上述步骤转换为最小堆积树,之后仍是取出最小值(树根),不断重复直至无元素。如下图1、图2所示

图1

图2

        重复上述步骤,因为使用一维数组储存堆积树元素及对应位置,每次均是取最小值,因此,最后得到的一维数组就是已排序好的状态。在整个过程中,和选择排序算法主要区别在于,使用堆积树方式查找最小值速度更快。

代码实现

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define MAX 10
#define SWAP(x,y) {int t; t = x; x = y; y = t;} //元素交换 

//函数声明 
void createheap(int[]); 
void heapsort(int[]);

int main(){
	int number[MAX+1] = {-1}; 
	int i, num;
	srand(time(NULL)); //刷新每次产生的随机数,若无此句,每次随机数相同,亲自尝试一下便知
	printf("排序前:");
	for(i = 1; i <= MAX; i++){ 
		number[i] = rand() % 100; //产生0-99的随机数,这里没有采用固定的数组值进行排序,随机生成
		printf("%d ", number[i]);
	}
	
	printf("\n建立堆积树:"); 
	createheap(number);
	for(i = 1; i <= MAX; i++) printf("%d ", number[i]);
	printf("\n"); 
	heapsort(number); 
	printf("\n");
	return 0;
}

void createheap(int number[]){ 
	int i, s, p;
	int heap[MAX+1] = {-1};
	for(i = 1; i <= MAX; i++){ 
		heap[i] = number[i];
		s = i;
		p = i / 2;
		while(s >= 2 && heap[p] > heap[s]){ 
			//交换元素顺序,也可将交换语句写在此处 
			SWAP(heap[p], heap[s]);
			s = p;
			p = s / 2;
		}
	}
	for(i = 1; i <= MAX; i++) number[i] = heap[i];

}

void heapsort(int number[]){ 
	int i, m, p, s;
	m = MAX;
	while(m > 1){
		//交换元素顺序,也可将交换语句写在此处 
		SWAP(number[1], number[m]); 
		m--;
		p = 1;
		s = 2 * p;
		while(s <= m){
			if(s < m && number[s+1] < number[s]) s++;
			if(number[p] <= number[s]) break;
			//交换元素顺序,也可将交换语句写在此处 
			SWAP(number[p], number[s]); 
			p = s;
			s = 2 * p;
		}
		printf("\n排序中:"); 
		for(i = MAX; i > 0; i--) printf("%d ", number[i]);
	}
}

运行结果

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

等日出看彩虹

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值