堆排序重要算法:向上向下调整算法

        stl中并没有堆这样一个类(但是有个priority_queue,这其实就是堆哦,stl跟大小比较相关的容器大都允许自定义比较函数哦,很不错的呢),但是在学习中我们可以模拟实现堆,把它封装为一个类,然后在运用当中调用它的各种接口,实现一次可以深入理解堆排序的原理和优势,使我们在面对各种问题的时候可以借助这个算法实现更好的优化。

        接下来就让我们看一下具体的实现过程:

       这里是头文件和命名空间的包函

#pragma once
#include <iostream>
#include <vector>
#include <assert.h>
using namespace std;

 

 

这里是模拟实现的堆数据结构        

 

template<class T, class Compare>
class Heap
{
public:
	Heap() //无参构造函数
	{}
	Heap(const T* a, size_t n)  //使用数组初始化堆
	{
		size_t i = 0;
		_a.reserve(n);
		for (i = 0; i < n; i++)
		{
			_a.push_back(a[i]);
		}
		int parent = (n - 1) / 2;
		for (parent; parent >= 0; parent--)
		{
			adjustdown(parent); //建堆需要实现的向下调整算法;
		}
	}
	void Push(const T& x)
	{
		_a.push_back(x);
		adjustup(_a.size()-1);    //这是向上调整算法
	}
	void Pop()
	{
		assert(_a.size());
		swap(_a[0],_a[_a.size()-1]);
		_a.pop_back();
		adjustdown(0);
	}
protected:
	void adjustup(int child)
	{
		assert(child < _a.size()&& child >0);
		Compare cmp;  //这里的cmp和下面向下调整算法得cmp都是一个仿函数类,用仿函数主要是为了实现代码的复用.
		int parent = (child - 1) / 2;
		while (child > 0)
		{
			if (cmp(_a[child] , _a[parent]))
			{
				swap(_a[child], _a[parent]);
				child = parent;
				parent = (parent - 1) / 2;
			}
			else
			{
				break;
			}
		}
	}
	void adjustdown(int parent)
	{
		Compare cmp;
		size_t child = parent * 2 + 1;
		while (child<_a.size())
		{
			if (child + 1 < _a.size() && cmp(_a[child + 1] , _a[child]))
				child++;
			if (cmp(_a[child],_a[parent]))
			{
				swap(_a[child], _a[parent]);
				parent = child;
				child = child * 2 + 1;
			}
			else
			{
				break;
			}
		}
	}
protected:
	vector<T> _a;
};

             代码中蕴含了很多算法,但是只有代码晦涩难懂。所以绘制了几幅图便于理解。

 

下面我们主要看一下adjustdown 和dijustup这两个函数的算法

              这里我们就将堆中的基本算法实现了。有了这个算法思路或者实例化后的结构我们就可以实现排序、topk问题等利用别的算法实现起来很麻烦的问题。而文章中建堆方式使用了向下调整算法建堆 , 而还可以使用向上调整法建堆哦 , 给个提示 , 这种建堆方式叫做插入法,看懂代码之后 , 有兴趣可以调用一下adjust_up函数建个堆试试哦,超级简单的几行代码。

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值