欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

数据结构:堆之相关操作

程序员文章站 2024-02-14 13:56:16
...

要求: 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;
}

  结果:

数据结构:堆之相关操作