【算法分析】排序算法:堆排序

        堆排序是一种就地排序方法(请参看《算法导论》一书),在代码中,我用递归的方法写了一下,排序数由随机数产生。父节点从0开始,父节点与左、右孩子的位置关系为:

(父节点)father :  i      (左孩子)left :  i * 2 + 1     (右孩子)right : i * 2 + 2 

代码如下:

/*****************************************
Copyright (c) 2015 Jingshuang Hu  
  
@filename:demo.c 
@datetime:2015.09.25  
@author:HJS  
@e-mail:eleftheria@163.com  
@blog:http://blog.csdn.net/hujingshuang 
******************************************/
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
/*****************************************/
#define N 15		//元素个数
#define positive 0	//正向遍历
#define opposite 1	//反向遍历
/*****************************************/
void Heap_Sort(int *data, int n);				//堆排序
void Heap_Creat(int *data, int n);				//创建堆
void Heap_Max_Adjust(int *data, int pos, int n);//调整为最大堆
void Heap_Show(int *data, int n, int way);		//显示堆
/*****************************************/
int main()
{
	int i = 0;
	int data[N] = {0};

	srand((unsigned int)NULL);
	for (i = 0; i < N; i++)
	{
		data[i] = rand() % 50 + rand() % 50;
	}
	//显示随机数
	printf("原数据:");
	Heap_Show(data, N, positive);
	//创建最大堆
	Heap_Creat(data, N);
	printf("最大堆:");
	Heap_Show(data, N, positive);
	printf("\n");
	//堆排序
	Heap_Sort(data, N);
	printf("\n堆排序:");
	Heap_Show(data, N, opposite);
	
	return 0;
}
/*****************************************/
void Heap_Show(int *data, int n, int way)
{
	int i = 0;
	if (!way)//遍历方式
	{
		for (i = 0; i < n - 1; i++)
		{
			printf("%d ", data[i]);
		}
		printf("%d\n", data[i]);
	}
	else
	{
		for (i = n - 1; i > 0; i--)
		{
			printf("%d ", data[i]);
		}
		printf("%d\n", data[i]);
	}
}
/*****************************************/
void Heap_Sort(int *data, int n)
{
	int temp = 0;
	while(n)
	{	//顶、底互换(最大值出列,放在末尾)
		temp = data[0];
		data[0] = data[n - 1];
		data[n - 1] = temp;
		n--;//保护出列元素

		Heap_Max_Adjust(data, 0, n);//自上而下
		printf("调整堆:");
		Heap_Show(data, N, positive);
	}
}
/*****************************************/
void Heap_Creat(int *data, int n)
{
	int i = 0;
	for (i = (n / 2) - 1; i >= 0; i--)
	{
		Heap_Max_Adjust(data, i, n);
	}
}
/*****************************************/
void Heap_Max_Adjust(int *data, int pos, int n)
{
	int temp = 0;
	int father = pos;		//父节点位置
	int left = pos * 2 + 1;	//左孩子位置
	int right = pos * 2 + 2;//右孩子位置

	if (father < (n / 2))
	{
		if (right < n)		//有两个孩子
		{	//情况:①父节点与两个孩子相等②左右孩子相等且比父节点大     解决办法:父节点与左孩子(或是右孩子)互换
			if ((data[left] >= data[father]) && (data[left] >= data[right]))//此处为父节点与左孩子互换
			{
				temp = data[left];
				data[left] = data[father];
				data[father] = temp;
				Heap_Max_Adjust(data, left, n);
			}
			else if ((data[right] > data[father]) && (data[right] > data[left]))
			{
				temp = data[right];
				data[right] = data[father];
				data[father] = temp;
				Heap_Max_Adjust(data, right, n);
			}
		}
		else			//只有左孩子
		{
			if (data[left] > data[father])//相等不用互换
			{
				temp = data[left];
				data[left] = data[father];
				data[father] = temp;
			}
		}
	}
}

        在码完代码后,测试发现,随机数中如果没有出现相同的值,则可以正常正确排序;但是如果有两个及其以上的相同值,就会出现排序错误。经调试发现,未考虑到出现相同值得情况,如代码注释中的情况①②。上述代码已修正,是最终可用的版本。


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值