数据结构--大小堆

如果有一个关键码的集合K = {k0,k1, k2,…,kn-1},把它的所有元素按完全二叉树 的顺序存储方式存储在一个一维数组中,并满足:Ki <= K2*i+1 且 Ki<= K2*i+2  (Ki >= K2*i+1 且 Ki >= K2*i+2) i = 0,1,2…,则称这个堆为最小堆(或最大堆)。


最大堆和最小堆是二叉堆的两种形式。

最大堆:根结点的键值是所有堆结点键值中最大者,且每个结点的值都比其孩子的值大。

最小堆:根结点的键值是所有堆结点键值中最小者,且每个结点的值都比其孩子的值小。



这样我们就能根据图大小堆的规则构建大小堆了


我们根据数组arr 最终要创建这样一个树


下面图示流程是 创建 最小堆的过程 





其实看懂了上面的流程,最小堆的代码也就出来了。


下面把 最大堆的代码就直接放在这了,当然还有一些操作,如:插入、删除、堆顶元素之类的 

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

//Use a vector create Heap
template <class T >
class HeapGeater
{
public:
	HeapGeater()
	{}
	HeapGeater(const T arr[], size_t size) //size is Elem_count
	{
		assert(arr);
		//push data
		_heap.resize(size);
		for (size_t index = 0; index < size; index++)
		{
			//_heap.push_back(arr[index]);
			_heap[index] = arr[index];
		}
		size_t Root = size / 2 - 1; // the last Leef_Node of Root
		for (int index = Root; index >= 0; index--)
		{
			_AdjustDown(index);
		}
	}
	bool Empty()
	{
		return _heap.empty();
	}
	size_t Size()
	{
		return _heap.size();
	}

	T& Top()const
	{
		assert(!Empty());
		return _heap[0];
	}
	const T&Top()
	{
		assert(!Empty());
		return _heap[0];
	}
	
	void Insert(const T& data)
	{
		assert(!Empty());
		T tmp = _heap[Size() - 1];
		_heap.push_back(data);
		if (data > tmp)
		{
			int  Root = Size() / 2 - 1; // the last Leef_Node of Root
			for (int index = Root ; index > 0; index--)
			{
				AdjustUp(index);
			}
		}
	}

	void Remove(const T& data)
	{
		assert(!Empty());
		_heap[0] = _heap[Size() - 1];
		_heap.resize(Size()-1 );

	   int Root = Size() / 2 - 1; // the last Leef_Node of Root
		for (int index = Root; index >= 0; index--)
		{
			_AdjustDown(index);
		}
	}

protected:
	void  _AdjustDown(size_t  Root)//adjust to Max_heap
	{
		size_t Child = Root * 2 + 1;// find the LeftChild
		while (Child < _heap.size())
		{
			// find Max  between left_elem and right_elem
			if ((Child + 1 < _heap.size()) && _heap[Child + 1] > _heap[Child])
			{
				//std::swap(_heap[Child + 1], _heap[Child]);
				Child = Child + 1;
			}
			//confirm The root is MAx
			if (_heap[Child] > _heap[Root])
			{
				std::swap(_heap[Child], _heap[Root]);
				Root = Child;
				Child = Child*2 + 1;
			}
			else
			{
				break;
			}
		}//end  while
	}
	void AdjustUp(int Root)
	{
		int child = Size() - 1; //Find the inserted data 
		while ( Root >= 0 && _heap[Root] < _heap[child])
		{
			swap(_heap[Root], _heap[child]);	
			child = Root;
			Root = (Root - 1) / 2;		
		}
	}
private:
	std::vector<T> _heap;
};


/********Test Code**********/
void test_heapGeater()
{
	int arr[] = { 1, 2, 3, 4, 5, 6, 7, 8 };
	HeapGeater<int>  ap(arr,8);
	cout <<"****************" << endl;

	cout<< ap.Size()<<endl;
	ap.Insert(99);
	cout << ap.Top() << endl;
	cout << ap.Size() << endl;
	ap.Remove(8);
	cout << ap.Top() << endl;
	cout << ap.Size() << endl;
}




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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值