排序算法(三):堆排序

下面是我写的程序


这个程序不明白的是:双亲结点与孩子结点交换了数据,如果孩子结点并不是最大堆,也需要把孩子结点调成最大堆的情况,这个程序是怎么做的,我写这个程序时没有专门操作,但却对了,我并不知道是怎么做的



#include <stdio.h>

typedef int KeyType;

struct DataType
{
	KeyType key;
};

/*创建最大堆*/
void CreatHeap(struct DataType a[],int n)  //把数据 a[] 调成最大堆(从下向上), n 为数组中元素个数
{
	int i,j;
	int h = 0;        // h 为根结点下标
	struct DataType temp;   //定义一个临时变量
	
	//求第一个非叶结点的下标,结果保存在 j 中
	i = h;
	while(1)            
	{
		if(2 * i + 1 >= n -1)      //最后一个非叶结点,只有左子树
		{
			j = i;
			break;
		}
		else if(2 * i + 2 >= n -1)   //最后一个非叶结点,有左子树,和右子树
		{
			j = i;
			break;
		}
		
		i ++;
	}
	
	//交换数据,生成最大堆
	if(2 * j + 1 == n-1)      //最后一个非叶结点,只有左子树的情况
	{			
		if(a[j].key < a[2*j+1].key)    //最后一个非叶结点,只有左子树
		{
			temp = a[j];
			a[j] = a[2*j+1];
			a[2*j+1] = temp;
		}
		j = j -1;                       //其它非叶结点,既有左子树又有右子树
		for( ; j >= h; j--)
		{
			//双亲结点与最大孩子结点交换数据
			if(a[j].key < a[2*j+1].key  ||  a[j].key < a[2*j+2].key) 
			{
				if(a[2*j+1].key < a[2*j+2].key)
				{
					temp = a[j];
					a[j] = a[2*j+2];
					a[2*j+2] = temp;
				}
				else
				{
					temp = a[j];
					a[j] = a[2*j+1];
					a[2*j+1] = temp;
				}
			}
		}
	}
	
	else if(2 * j + 2 == n-1)            //最后一个非叶结点,有左子树,也有右子树的情况
	{
		for( ; j >= h; j--)
		{
			//双亲结点与最大孩子结点交换数据
			if(a[j].key < a[2*j+1].key  ||  a[j].key < a[2*j+2].key)
			{
				if(a[2*j+1].key < a[2*j+2].key)
				{
					temp = a[j];
					a[j] = a[2*j+2];
					a[2*j+2] = temp;
				}
				else
				{
					temp = a[j];
					a[j] = a[2*j+1];
					a[2*j+1] = temp;
				}
			}
		}
	}
}

/*堆排序算法*/
int HeapSort(struct DataType a[],int n)
{
	int i;
	struct DataType temp;       //定义一个临时变量
	
	for(i = n; i > 1; i--)  /*这个 i>1(最后还有一个元素时不用排序,少一步,效率高一些) 与 i>0 都成功*/
	{
		CreatHeap(a,i);             //使数组成为最大堆
		
		temp = a[0];          //堆顶 a[0] 元素(为最大元素)和当前最大堆的最后一个元素交换
		a[0] = a[i-1];
		a[i-1] = temp;
	}
	
	return 0;
}

/*测试程序*/
int main()
{
	int i;
	int n = 21;
	struct DataType test[21] = {1,16,45,87,23,5,9,34,10,6,26,64,5,7,89,6,24,100,4,7,19};
	HeapSort(test,n);       /*注意这个的参数及参数传递*/
	
	for(i = 0; i < n; i++)
	{
		printf(" %d ",test[i].key);
	}
	printf("\n");
	
	//system("pause");         //暂停
	
	return 0;
}


下面的是书上的例子


#include <iostream>
using namespace std;

typedef int KeyType;

struct DataType
{
	KeyType key;
};

/*创建最大堆*/
void CreatHeap(DataType a[],int n,int h)
{
	int i,j,flag;
	DataType temp;

	i = h;           // i 为要建堆的二叉树根结点下标
	j = 2 * i +1;    // j 为 i 的左孩子结点的下标
	temp = a[i];
	flag = 0;

	//没左右孩子中值较大者重复向下筛选
	while(j < n && flag != 1)
	{
		//寻找左、右孩子结点中的较大者,j 为其下标
		if(j < n-1 && a[j].key < a[j+1].key)  j++;

		if(temp.key > a[j].key)          // a[i].key > a[j].key
			flag = 1;                    //标记结束筛选条件
		else                             //否则把 a[j] 上移
		{
			a[i] = a[j];
			i = j;
			j = 2 * i +1;
		}
	}

	a[i] = temp;
}

/*初始化创建最大堆算法*/
void InitCreatHeap(DataType a[],int n)
{
	int i;

	for(i = (n-1)/2; i >= 0; i--)
		CreatHeap(a,n,i);
}

/*堆排序算法*/
void HeapSort(DataType a[],int n)
{
	int i;
	DataType temp;

	InitCreatHeap(a,n);       //初始化创建最大堆

	for(i = n-1; i > 0; i--)  //当前最大堆个数每次递减 1
	{
		//把堆顶 a[0] 元素和当前最大堆的最后一个元素交换
		temp = a[0];
		a[0] = a[i];
		a[i] = temp;

		CreatHeap(a,i,0);      //调整根结点满足最大堆
	}
}


/*测试程序*/
int main()
{
	int i;
	int n = 21;
	struct DataType test[21] = {1,16,45,87,23,5,9,34,10,6,26,64,5,7,89,6,24,100,4,7,19};
	HeapSort(test,n);       /*注意这个的参数及参数传递*/
	
	for(i = 0; i < n; i++)
	{
		printf(" %d ",test[i].key);
	}
	printf("\n");
	
	//system("pause");         //暂停
	
	return 0;
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值