【数据结构】实现大小堆也叫二叉堆(类似c++中的优先队列)

二叉堆:

是一种特殊的堆,依赖于完成完全二叉树和向量实现的。分为最大堆和最小堆。



最大堆:父节点的键值总是大于或等于任何一个子节点的键值。


最小堆:父节点的键值总是小于或等于任何一个子节点的键值。



存储:二叉树一般用数组来存储表示,在下面的实现中使用了STL中的vector。根节点在数组中的位置是0,第n个位置的左孩子下标为n*2+1,右孩子为2*n+2 ,当前孩子存在的前提是计算后下标要小于数组总个数。而用孩子结点的下标c,可以计算出双亲的下标(c-1)/2。


基本操作:可以进行插入结点,移除最小的结点,和返回最小的结点,返回当前堆中元素个数。


代码:这个是用模板参数实现,传入函数对象生成大小堆,默认小堆:

#ifndef _HEAP_H_
#define  _HEAP_H_
#include <cassert>
#include <vector>
#include <iostream>
using namespace std;

// 仿函数小堆调用 
template <class T>
class Less
{
public:
	bool operator()(const T& left, const T& right)
	{
		return left <= right;
	}
};
// 仿函数大堆调用
template <class T>
class Greater
{
public:
	bool operator()(const T& left, const T& right)
	{
		return left > right;
	}
};

	 
		

// 模板参数的大小堆

template <class T, class Compare = Less<T>>
class Heap
{
public:
	Heap(){}
	Heap(const T arr[] , int size)
	{
		for (int i=0; i<size; ++i)
		{
			_heap.push_back(arr[i]);
		}
		int last = (size - 2)/2; 
		for (int i=last; last>=0; --last)
		{
			_AdjustDown(last, size);
		}
	}
	void Insert(const T data)
	{
		_heap.push_back(data);
		_AdjustUp(_heap.size());
	}

	T& Top()
	{
		assert(!_heap.empty());

		return _heap[0]; 
	}
	const T& Top()const
	{
		assert(!_heap.empty());

		return _heap[0]; 
	}
	void Remove()
	{
		int size = _heap.size();
		if (size > 1)
		{
			std::swap(_heap[0], _heap[size-1]);
			_heap.pop_back();
			_AdjustDown(0, _heap.size());
		}
		else
		{
			_heap.pop_back();
		}
	}
private:
	void _AdjustUp(int size)
	{
		int child = size - 1;
		int parent = (child-1)/2;
		while (child != 0)
		{
			// 孩子小于父亲
			if (Compare()(_heap[child], _heap[parent]))
			{
				std::swap(_heap[child], _heap[parent]);
				child = parent;
				parent = (child - 1 )/2;
			}
			else
			{
				break;
			}
		}
	}
	void _AdjustDown(int root, int size)
	{
		int child = root*2 + 1;
		int parent = root;

		while (child < size)
		{
			if (child+1 < size && Compare()(_heap[child+1], _heap[child]) )
			{
				child += 1;
			}
			// 小 less 
			if (Compare()(_heap[child], _heap[parent]))
			{
				std::swap(_heap[child], _heap[parent]);
				parent = child;
				child = child *2 + 1;
			}
			else
			{
				break;
			}
		}
	}
private:
	vector<T> _heap;
};
#endif _HEAP_H_

这个是用模板的模板参数实现:

#ifndef _HEAP_H_
#define  _HEAP_H_
#include <cassert>
#include <vector>
#include <iostream>
using namespace std;

// 仿函数小堆调用 
template <class T>
class Less
{
public:
	bool operator()(const T& left, const T& right)
	{
		return left <= right;
	}
};
// 仿函数大堆调用
template <class T>
class Greater
{
public:
	bool operator()(const T& left, const T& right)
	{
		return left > right;
	}
};


// 模板的模板参数 大小堆
template<class T, template<class> class Compare = Less>
class Heap
{
public:
	Heap(){}
	Heap(const T arr[], int size)
	{
		for (int i=0; i<size; ++i)
		{
			_heap.push_back(arr[i]);
		}
		int root = (size - 2)/2;
		for (int i=root; i>=0; --i)
		{
			_AdjustDown(i, size);
		}
	}

	void Insert(const T& data)
	{
		_heap.push_back(data);
		_AdjustUp(_heap.size());
	}

	void Remove()
	{
		if (!_heap.empty())
		{
			if (_heap.size()>1)
			{
				std::swap(_heap[0], _heap[_heap.size()-1]);
				_heap.pop_back();
				_AdjustDown(0, _heap.size());
			}
			else
			{
				_heap.pop_back();
			}
		}
	}
	T& Top()
	{
	assert(!_heap.empty());

	return _heap[0]; 
	}
	const T& Top()const
	{
	assert(!_heap.empty());

	return _heap[0]; 
	}
private:
	void _AdjustUp(int size)
	{
		int child = size-1;
		int  parent= (child-1)/2;
		while (child != 0)
		{
			if (Compare<T>()(_heap[child], _heap[parent]))
			{
				std::swap(_heap[child], _heap[parent]);
				child = parent;
				parent = (child-1)/2;
			}
			else
			{
				break;
			}
		}
	}
    void _AdjustDown(int root, int size)
	{
		int parent = root;
		int child = root*2 + 1;

		while (child < size)
		{
			if (child+1 < size && Compare<T>()(_heap[child+1],_heap[child]) )
			{
				child  = child+1;
			}
			if (Compare<T>()(_heap[child], _heap[parent]))
			{
				std::swap(_heap[child], _heap[parent]);
				parent = child;
				child = child*2 + 1;
			}
			else
			{
				break;
			}
		}
	}

	private:
	vector<T> _heap;
};
#endif _HEAP_H_



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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值