堆排序原理与C++实现

思路

1.建堆(大根堆为例)
(1)从倒数第一个非叶子节点开始,做下沉操作,直到根节点。
(2)下沉操作,对父节点和其儿子节点做比较,若父节点最大,则结束,否则就下沉,然后对发生变化的儿子节点做同样的下沉操作,直到叶子节点。
在这里插入图片描述
在这里插入图片描述
2.堆排序
(1)将根节点与最后一个叶子节点互换位置;
(2)对根节点做下沉操作。

C++实现

#include <iostream>
#include <vector>
#include <functional>
using namespace std;

/*下沉操作*/
template<class T>
void shiftDown(vector<T>& a, int i, int len, function<bool(const T&, const T&)>cmp) {
	int l = 2 * i + 1;
	int r = l + 1;
	int m = i;
	while(l < len) {
		if(!cmp(a[l], a[i]) && (r >= len || !cmp(a[l], a[r])) ) {
			m = l;
		}
		else if(r < len && !cmp(a[r], a[i]) && !cmp(a[r], a[l])) {
			m = r;
		}
		if(m != i) { //父节点不是最大的,发生交换
			swap(a[m], a[i]);
			l = 2 * m + 1;
			r = l + 1;
			i = m;
		}
		else {
			break;
		}
	}
}

/*建堆*/
template<class T>
void createHeap(vector<T>& a, int len, function<bool(const T&, const T&)>cmp) {
	for(int i = len / 2 - 1; i >= 0; --i) {
		shiftDown(a, i, len, cmp);
	}
}

/*删除堆顶元素*/
template<class T>
void popHeap(vector<T>& a, int len, function<bool(const T&, const T&)>cmp) {
	swap(a[0], a[len - 1]);
	shiftDown(a, 0, len - 1, cmp);
}

/*堆排序*/
template<class T>
void heapSort(vector<T>& a, int len, function<bool(const T&, const T&)>cmp) {
	createHeap(a, len, cmp);
	for(int i = len; i >= 2; --i) {
		popHeap(a, i, cmp);
	}
}

int main() {
	vector<int> a{0, 10, 1, 2, 0, 11, -3};
	heapSort<int>(a, a.size(), [](const int& l, const int& r) {
		return l < r;   //构建大根堆,输出升序序列
	});
	for(auto i : a) {
		cout << i << ' ';
	return 0;
}

运行结果:

-3 0 0 1 2 10 11

总结

  • 自底向上的建堆复杂度为O(n)
  • 堆排序的复杂度为O(nlogn)
  • 堆是原地排序,但不稳定
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值