数据结构:堆之相关操作

要求: 1.0 实现大小堆 2.0 用堆实现优先级队列  3.0  堆排序

1.0 大小堆的实现:

     0.0 vector的相关操作为堆带来了方便,所以底层数据用Vector。

    1.0 既然能用大小堆实现队列,那么堆就应该满足队列的特点:先进先出。 

        所以堆的pop()函数应该是堆顶弹出

   2.0 为了减少代码量,用仿函数实现一个bool类型的operator()重载,在比较时就不需要写两份代码。

        child+1和child比较,他们中的最大值或者最小值和parent比较,大于parent 交换(大堆),小于parent交换(小堆)

  3.0  注意:建堆的时候是向下调整执行push()操作时是需要向上调整的。


2.0 用堆实现优先级队列 

     优先级队列即把堆再封装了一遍,没难度。注意成员变量是堆就可以了。

       pop(),push(),top(),show()。

3.0  堆排序

     1.0 堆的排序只需要把排序函数封装在heap类里即可。

     2.0 原理:类似于冒泡排序,每次把堆顶换下来(最大值或者最小值)

         注意:每换一次,都需要固定从堆顶开始向下调整一次,调整时需要注意:循环条件size-1 

                   否则的话堆底的最值就会被调整回去。

        所以,向下调整函数需要重新写一个,多一个变量size,外层循环控制交换次数以及保留有序的尾部数据。

具体实现:

#include<iostream>
#include<vector>
#include<assert.h>
using namespace std;
//利用仿函数实现()的重载
template<class T>
struct Greater
{
	bool operator()(const T& l, const T& r)
	{
		return l > r;
	}
};
template<class T>
struct Less
{
	bool operator()(const T& l, const T& r)
	{
		return l < r;
	}
};
//堆的创建
template<class T,class compare = Less<T>>
class Heap
{
public:
	Heap()
	{}
	Heap(T* a, int size)
	{
		assert(a);
	    _a.reserve(size);   //change capacity to n (at least)
		for (int i = 0; i <size;++i)
		{
			_a.push_back(a[i]);
		}
		//向下调整法,从倒数第一个非叶子结点
		for (int j = (size - 2) / 2; j >= 0; --j)
		{
			AdjustDown(j);
		}
	}
	void push(const T& x)
	{
		_a.push_back(x);
		AdjustUp(_a.size()-1);
	}
	void pop()
	{
		assert(!_a.empty());
		swap(_a[0], _a[_a.size()-1]);
		_a.pop_back();
		AdjustDown(0);
	}
	size_t Size()
	{
		return _a.size();
	}
	const T& top()const
	{
		assert(!_a.empty());
		return _a[0];
	}
	bool empty()
	{
		return _a.size()== 0;
	}
	void show_heap()
	{
		for (size_t i = 0; i < _a.size(); ++i)
		{
			cout << _a[i] << " ";
		}
		cout << endl;
	}
	//升序调整(基础大堆)
	void ascending_AdjustDown(int parent, int size)
	{
		int child = parent * 2 + 1;
		while (child<size)
		{
			if (child + 1 <size && _a[child + 1]>_a[child])   //约束child+1
			{
				child++;
			}
			if (_a[child]>_a[parent])//升序排序
			{
				swap(_a[child], _a[parent]);
				parent = child;
				child = parent * 2 + 1;
			}
			//父节点不用换
			else
				break;
		}
	}
	//堆的升序排序
	void Heap_Sort(int size)
	{
		for (int i = (size - 2) / 2; i >= 0; --i)
		{
			ascending_AdjustDown(i, size);
		}
		for (int i = 0; i < size; ++i)
		{
			swap(_a[0], _a[size - 1 - i]);
			ascending_AdjustDown(0, size - i - 1);
		}
	}
protected:
	void AdjustDown(int parent)
	{
		int child = parent * 2 + 1;
		compare com;
		while (child<_a.size())
		{
			if (child + 1 < _a.size() && com(_a[child + 1], _a[child]) )   //约束child+1
			{
				child++;
			}
			if (com(_a[child], _a[parent]))
			{
				swap(_a[child], _a[parent]);
				parent = child;
				child = parent * 2 + 1;
			}
			//父节点不用换
			else
				break;
		}
	}
	void AdjustUp(int child)
	{
		int parent = (child - 1) / 2;
		compare com;
		while (child>0)
		{
			if (com(_a[child], _a[parent]))
			{
				swap(_a[child], _a[parent]);
				child = parent;
				parent = (child - 1) / 2;
			}
			else
				break;
		}
	}
protected:
	vector<T> _a;
};
//优先级队列
template<class T, class compare = Less<T>>
class PriorityQueue
{
public:
	PriorityQueue(T* a, int size)
		:hpp(a, size)
	{}
	const T& _top()const
	{
		return hpp.top();
	}
	void _push(const T& x)
	{
		hpp.push(x);
	}
	void _pop()
	{
		hpp.pop();
	}
	void _show_PriorityQueue()
	{
		hpp.show_heap();
	}
private:
	Heap<T, compare> hpp;
};
//堆排序测试
	void Heap_sortTest()
	{
		int arr[10] = { 12, 15, 48, 1, 5, 56, 79, 54, 45, 21 };
		Heap<int, Less<int> > hp(arr, sizeof(arr) / sizeof(arr[0]));
		int size = hp.Size();
		hp.Heap_Sort(size);
		hp.show_heap();
	}
//大小堆测试
void Heap_Test()
{
	int arr[10] = { 12, 15, 48, 1, 5, 56, 79, 54, 45, 21 };
	Heap<int, Less<int> > hp(arr, sizeof(arr) / sizeof(arr[0]));
	cout << hp.Size() <<endl;
	hp.show_heap();

	hp.pop();
	hp.show_heap();

	hp.push(22);
	hp.show_heap();

	hp.top();
	cout << hp.empty() << endl;
	hp.show_heap();
	cout << hp.Size() << endl;
}
void PriorityQueue_Test()
{
	int arr[10] = { 12, 15, 48, 1, 5, 56, 79, 54, 45, 21 };
	PriorityQueue<int, Less<int> > hp1(arr, sizeof(arr) / sizeof(arr[0]));
	hp1._push(25);
	hp1._show_PriorityQueue();
	hp1._pop();
	cout<<hp1._top()<<endl;
	hp1._show_PriorityQueue();
}
int main()
{
	cout <<"大小堆测试"<< endl;
	Heap_Test();
	cout << "优先级队列测试" << endl;
	PriorityQueue_Test();
	cout << "堆排序测试" << endl;
	Heap_sortTest();
	system("pause");
	return 0;
}

  结果:


猜你喜欢

转载自blog.csdn.net/WhiskyCocktail/article/details/79557905
今日推荐