堆排序实现

堆排序的实现与优先队列相似。本文先给出堆排序代码,然后对其中要点进行解释,程序中的注释已经很详细了。接着,给出一个应用对排序的编程题(华为笔试题)。

实例:从小标0开始存放数据,利用数组实现大顶堆,从而实现堆排序。

#include <iostream>
using namespace std;

#define ElementType int 

void showFunc(ElementType a[], int N)
{
	for (int i = 0; i < N; i++)
		cout << a[i] << ' ';
	cout << '\n';
}
//堆有序函数:保证以i为根节点的树有序
void AdjustDown(ElementType arr[],int i,int N)
{
	int child;
	ElementType tmp;
	for (tmp = arr[i]; 2 * i + 1 < N; i = child)
	{
		child = 2 * i + 1;   //i节点的左子节点
		//i节点有两个子节点,选择其中元素值大的节点
		if (child != N - 1 && arr[child + 1] > arr[child])  
			child++;
		//父节点i与子节点比较,判断父节点是否需要下沉(另一种说法,是否在子节点中产生空穴)。
		if (tmp < arr[child])  //因为使用赋值方法,故每次父节点与子节点值相同,故这里必须与原子节点tmp比较。
			arr[i] = arr[child];  //使用赋值的方法产生空穴。
		else
			break;
	}
	arr[i] = tmp;
}
//将元素按大顶堆进行存储
void MakeHeap(ElementType arr[], int N)
{
	int i = 0;
	for (i = N / 2 - 1; i >= 0; i--)  //从最后一个叶子节点N-1的父节点N / 2 - 1开始构造堆(从小标0开始存储的数组)
		AdjustDown(arr, i, N);
}

void swap(ElementType *a, ElementType *b)
{
	ElementType tmp;
	tmp = *a;
	*a = *b;
	*b = tmp;
}
//升序排列函数
void HeapSort(ElementType arr[], int len)
{
	int i = 0;
	MakeHeap(arr, len);
	for (i = len - 1; i >= 0; i--)
	{
		swap(&arr[i], &arr[0]);
		AdjustDown(arr,0,i);
	}
}

int main()
{
	int len = 10;
	ElementType *a;
	a = (ElementType *)malloc(len*sizeof(ElementType));
	for (int i = 5; i >0; i--)
		a[5-i] = i;
	for (int i = 0; i <len; i++)
		a[5 +i] = i+10;

	cout << "数组原序列为: ";
	showFunc(a,len);

	cout << "堆有序后的数组序列为: ";
	MakeHeap(a, len);
	showFunc(a, len);

	cout << "升序排列的数组序列为: ";
	HeapSort(a,len);
	showFunc(a, len);

	//free(a);
	system("pause");
	return 0;
}

注释:

1、构造堆

将数据存放在数组中,将数组构建为大顶堆。

void MakeHeap(ElementType arr[], int N)
{
	int i = 0;
	for (i = N / 2 - 1; i >= 0; i--)  //从最后一个叶子节点N-1的父节点N / 2 - 1开始构造堆(从小标0开始存储的数组)
		AdjustDown(arr, i, N);
}
主要思路就是从最后一个二叉树构建堆。若数据从小标[0]开始存放,那可第k个结点的父结点为(k-1)/2,其结点为2k+1和2k+2。据此,最后一个叶子结点的父节点即最后一个二叉树的下标为N/2-1,N表示数据总个数。


2、排序

将大顶堆对顶数据与最后一个数据进行交换,此时,最后一个数据就是整个数据中的最大值;

经过交换后,其余数据可能已经不是堆有序的,需要重新调整,具体方法是对判断堆顶元素是否需要“下沉”,注意此时不需要考虑最后一个元素;

如此循环,得到堆排序后的数据。

for (i = len - 1; i >= 0; i--)
	{
		swap(&arr[i], &arr[0]);
		AdjustDown(arr,0,i);
	}


实例:

问题描述:输入一串以逗号分隔的字符串,将最够一个字符作为优先级,将其按优先级输出。
输入:b2,a1,a3,c5,m4
输出:c5,m4,a3,b2,a1

#include <string>
#include <iostream>
#include <vector>
#include <sstream>
using namespace std;

void AdjustDown(vector<string> &V, int i, int N)
{
	int child;
	string tmp;
	char tmpCh, LeftCh, RightCh;
	tmp = V[i];
	tmpCh = tmp[tmp.size() - 1];
	for (; 2 * i + 1 < N; i = child)
	{
		child = 2 * i + 1;
		if (child != N - 1)
		{
			LeftCh = V[child][V[child].length() - 1];
			RightCh = V[child + 1][V[child + 1].length() - 1];
			if (RightCh > LeftCh)
				child++;
		}

		if (tmpCh < V[child][V[child].length() - 1])
			V[i] = V[child];
		else
			break;
	}
	V[i] = tmp;
}

int main()
{
	string str;
	vector<string> V;

	getline(cin, str);        //因为最后一个字符没有逗号,直接使用getline(cin, str,',')读不到最后一个
	istringstream is(str);

	while (getline(is, str, ','))
	{
		V.push_back(str);
	}
	cout << "原始序列:" << endl;
	for (int i = 0; i < V.size(); ++i)
		cout << V[i] << endl;
	//构建大顶堆
	for (int i = V.size() / 2 - 1; i >= 0; i--)  
		AdjustDown(V, i, V.size());
	cout << "大顶堆堆序列:" << endl;
	for (int i = 0; i < V.size(); ++i)
		cout << V[i] << endl;	
	//堆排序
	for (int i = V.size() - 1; i >= 0; i--) 
	{
		string tmp;
		tmp = V[0];
		V[0] = V[i];
		V[i] = tmp;
		AdjustDown(V, 0, i);
	}
	cout << "排序后的序列:" << endl;
	for (int i = V.size(); i >=0; i--)
		cout << V[i] << endl;

	system("pause");
	return 0;
}




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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值