堆排序的C语言实现

/*
	代码实现了堆排序。堆排序时间复杂度为O(nlog2n),堆排序非常适合在大量数据中选取少量最大/最小的数据,
	因为维护一个小根堆/大根堆比对全体数据进行排序工作量小很多。堆排序不涉及元素两两相互比较,故是非稳定排序。 
*/ 
#include<stdio.h>
#include<stdlib.h>
#define SIZE 7

// 函数状态
#define TRUE 1 // 逻辑1
#define FALSE 0 // 逻辑0
#define OK 1 // 程序运行无误
#define ERROR 0 // 程序运行有误
#define INFEASIBLE -1 
#define OVERFLOW -2 // 结果溢出
typedef int Status; // 函数状态类型
typedef int boolean; // 布尔类型

Status BuildMaxHeap(int a[], int n)
{// 为数组a[]1~n项建立大根堆
 /*
 	基本思想:从n/2到1,调整以他为根子树为大根堆。 
 */ 
 	int i;
 	
 	for(i=n/2;i>=1;i--)
 	{
 		HeadMaxAdjust(a, i, n);	
	}// for
	
	return OK;	
}// BuildMaxHeap()

Status BuildMinHeap(int a[], int n)
{// 为数组a[]1~n建立小根堆
 /*
 	基本思想:从n/2到1,将每个结点为根结点的子树调整为小根堆。 
 */ 
	int i;
	
	for(i=n/2;i>=1;i--)
	{
		HeadMinAdjust(a, i, n);
	}// for
	
	return OK;
}// BuildMinHeap()

Status HeadMaxAdjust(int a[], int v, int n)
{// 调整a[]中以v为根的子树为大根堆
 /*
 	基本思想:若出现了孩子父结点交换,那么也需要再次调整换下的父结点为根的子树。 
 */ 
	int i;
	
	for(i=2*v;i<=n;i*=2)
	{
		if(i<n && a[i]<a[i+1]) // 定位孩子中较大者
			i++;
		if(a[v]>=a[i]) // 根结点更大,无需交换 
			break; 
		// 交换
		a[0] = a[v];
		a[v] = a[i];
		a[i] = a[0];
		v = i; // 下移 
	}// for
	
	return OK;
}// HeadMaxAdjust()

Status HeadMinAdjust(int a[], int v, int n)
{// 调整以数组a[]中以v为根的子树为小根堆
	int i;
	
	for(i=2*v;i<=n;i*=2)
	{
		if(i<n && a[i]>a[i+1]) // 选取孩子中较小者
			i++;
		if(a[i]>=a[v]) // 若根结点更小,无需交换 
			return;
		// 交换
		a[0] = a[v];
		a[v] = a[i];
		a[i] = a[0];
		v = i; // 下移 
	}// for
	
	return OK; 
}// HeadMinAdjust()

Status HeapSort_A(int a[], int n)
{// 对a[]1~n进行升序堆排序
	int i;
	
	if(!BuildMaxHeap(a, n)) // 建立大根堆
		return ERROR;
	for(i=n;i>1;i--)
	{
		// 交换
		a[0] = a[1];
		a[1] = a[i];
		a[i] = a[0];	
		
		// 调整
		HeadMaxAdjust(a, 1, i-1); 
	}// for
	
	return OK;
}// HeapSort_A()

Status HeapSort_D(int a[], int n)
{// 对a[]1~n进行降序堆排序
	int i;
	
	BuildMinHeap(a, n); // 建立小根堆
	for(i=n;i>1;i--)
	{
		// 交换
		a[0] = a[i];
		a[i] = a[1];
		a[1] = a[0];
		
		// 调整
		HeadMinAdjust(a, 1, i-1);	
	}// for
	
	return OK;
}// HeapSort_D()

Status Max(int a[], int n, int v)
{// 选取a[]1~n范围内最大的v个数放到a[]1~v范围内
 /*
 	基本思想:首先建立小根堆,依次扫描后面的元素,若比根大则替换根并重新进行调整。 
 */ 
 	int i;
 	
	if(v<1 || v>n) // 非法
		return ERROR;
	BuildMinHeap(a, v); // 建立小根堆 
	for(i=v+1;i<=n;i++)
	{
		if(a[i]>a[1]) // 元素比根结点更小
		{
			// 交换
			a[0] = a[i];
			a[i] = a[1];
			a[1] = a[0];
			
			// 调整
			HeadMinAdjust(a, 1, v); 
		}// if
	}// for
	
	return OK;
}// Max()

void main()
{
	int a[SIZE+1] = {0, 1, 3, 5, 7, 2, 4, 6};
	int i;
	
	if(Max(a, SIZE, 3))
	{
		printf("选取成功!\n");
		for(i=1;i<=SIZE;i++)
		{
			printf("%d ", a[i]);			
		}

	}
	
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值