c++实现堆排序

概括(不想看后面晦涩的内容的话)(大根堆为例,小根堆同理):

  1. 拿到一串数,以宽度优先的方式生成一棵二叉树。
  2. 建堆:从最深的子树开始(从下往上),修改使得每一棵子树的根节点的值为子树中的最大值。(这样一来,这个大根堆的根节点就是整个堆的最大值)
  3. 排序:pop出堆的根(当前最大),将堆中最后一个数放在堆根处,然后从上往下修改,使得每棵子树的根节点仍然是子树中的最大值。重复这个过程,直到堆为空

在这里插入图片描述

堆排序虽然是在数组上进行排序, 但实际上它使用了层次遍历的二叉树的思想。

一、 排序的整体结构

void sort(int num) {
	build(num);
	for(int i = num-1; i > 0; i--) {
		int current = array[i];
		array[i] = array[0];
		insert(current, 0, i-1);
	}
}

构建堆 -> 从后往前将每个数插入到“合适”的位置上

二、主要函数: 插入函数 insert

void insert(int current, int low, int high) {
	int large = 2*low+1;       //array[large]是array[low]的左孩子
	while(large <= high) {
		if(large < high && array[large] < array[large+1])
			large++;           //找到array[low]的较大的那个孩子
		if(current > array[large])
			break;             //后面的值都太小了, 没有必要往下筛选了
		array[low] = array[large];
		low = large;
		large = 2*low+1;      //继续筛选, 为更小的分支找到根节点(领袖)
	}
	array[low] = current;     //在正确的位置插入current(current以下的数都比current小)
}

解释:
  参数current:要插入的值, low:插入范围的最低点(深度最小), high: 插入范围的最高点(深度最大)
函数实现的功能:
  将“以array[low]所在的节点为根,low至high之间的树”当中的最大的节点值换到根节点上,
  可以形象地理解为给这个分支找一个领袖

三、 用insert函数建堆

void build(int num) {
	for(int i = num/2-1; i >=0; i--)
		insert(array[i], i, num-1);
}

num/2-i: 最深节点的父节点
  通过在insert函数中的描述,我们可以看出, build的过程就是从底层到顶层一级一级找“领袖”的过程, 
  当for循环结束时,每一个节点都是以它为根的树当中的最大值了(领袖),这也就是我们所需要的堆

四、回过头来看排序sort函数

void sort(int num) {
	build(num);
	for(int i = num-1; i > 0; i--) {
		int current = array[i];
		array[i] = array[0];
		insert(current, 0, i-1);
	}
}

因为当前任意的节点都是以它为根的树的最大值,所以我们每次使用insert函数,就有一个大的数到了他本应该在的
位置,排序过的树就不再移动,所以参数high是i-1。我们不断地找到“剩余”的树当中的最大值放在最后, for循
环结束后,排序也就结束了。 

这样可能比较好理解

完整代码

#include <iostream>
using namespace std;

int array[100] = {3,5,4,2,1,8,7,9,6};

void insert(int current, int low, int high) {
	int large = 2*low+1;
	while(large <= high) {
		if(large < high && array[large] < array[large+1])
			large++;
		if(current > array[large])
			break;
		array[low] = array[large];
		low = large;
		large = 2*low+1;
	}
	array[low] = current;
}

void build(int num) {
	for(int i = num/2-1; i >=0; i--)
		insert(array[i], i, num-1);
}

void sort(int num) {
	build(num);
	for(int i = num-1; i > 0; i--) {
		int current = array[i];
		array[i] = array[0];
		insert(current, 0, i-1);
	}
}
int main() {
	int num;
	cin >> num;
	for(int i = 0; i < num; i++)
		cin >> array[i];
	sort(num);

	for(int i = 0; i < num; i++)
		cout << array[i] << " ";
}

例子

array 3 5 4 2 1 8 7 9 6

build 9 6 8 5 1 4 7 2 3

sort 1 2 3 4 5 6 7 8 9

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值