经典算法之堆排序

/************************
author's email:wardseptember@gmail.com
date:2017.12.5
堆排序
************************/
/*
堆是一种数据结构,可以把堆看成一棵完全二叉树,这棵树满足:任何一个非叶子
结点的值都不大于(或不小于)其左右孩子结点的值。若父亲大、孩子小,则这样的堆
叫做大顶推;若父亲小、孩子大,则这样的堆叫做小顶堆。
堆排序中最关键的操作是将序列调整为堆。整个排序的过程就是通过不断调整,完成一趟,则将
根节点调整到对应的位置,直到所有关键字调整完。
下面的代码以大顶堆为例。
*/
#include<iostream>
#define maxSize 11
using namespace std;
void move(int *a, int low, int high);
void heapSort(int *a, int n);//堆排序
void printArray(int *a, int n);//输出数组
void main() {
	int A[maxSize] = { 0,12,15,48,46,16,78,57,88,65,48 };/*构造一个一维数组,
	因为堆排序是对一棵完全二叉树排序 ,所以关键字的存储必须从1开始,令A[0]=0并且不用*/

	cout << "每躺的结果:"<<endl;
	heapSort(A, maxSize-1);
	cout << "简单选择排序结果为:" << endl;
	printArray(A, maxSize-1);
}

/*本函数完成在数组a[low]和a[high]的范围内对位置low上的结点进行调整*/
void move(int *a, int low, int high) {
	/*因为a[]中是一棵完全二叉树 ,所以关键字的存储必须从1开始*/

	int i = low, j = 2 * i;     //a[j]是a[i]的左孩子结点
	int temp = a[i];
	while (j <= high) {
		if (j < high&&a[j] < a[j + 1])//若右孩子较大,则把j指向右孩子
			++j;                      //j变为2*i+1
		if (temp < a[j]) {
			a[i] = a[j];              //将a[j]调整到双亲结点的位置上
			i = j;                    //修改i和j的值,以便继续向下调整
			j = 2 * i;
		}
		else
			break;
	}
	a[i] = temp;                     //被调整结点的值放入最终位置
}

/*堆排序函数*/
void heapSort(int *a, int n) {
	int i;
	int temp;
	for (i = n/2; i >= 1; --i)     //建立初始堆,使跟结点最大也就是a[1]最大
		move(a, i, n);
	for (i = n; i >= 2; --i) {       //进行n-1次循环,完成堆排序
		/*以下3句换出了根结点中的关键字,将其放入最终位置*/
		temp = a[1];
		a[1] = a[i];
		a[i] = temp;
		move(a, 1, i - 1);       //在减少了一个关键字的无序序列中进行调整


		/*下面这个循环是输出每躺的结果,可以删去*/
		for (int i = 1; i <= n; ++i)  //输出排序后的关键字
			cout << a[i] << " ";
		cout << endl;
	}
}
void printArray(int *a, int n) {
	for (int i = 1; i <=n; ++i)  //输出排序后的关键字
		cout << a[i] << " ";
	cout << endl;
}

以上如有错误,请立即指出,我立刻改正。

在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值