最小最大堆的C++实现

最小最大堆是一种双端优先队列,用完全二叉树的二叉堆结构存放关键字,该数据结构的详细介绍见
数据结构(C语言版) Ellis Horowitz Sartaj Sahni Susan Anderson-Freed 著 李建中 张岩 李治军译
机械工业出版社 p274-p278
这里仅给出C++实现

#include <iostream>
#include <vector>
#include <algorithm>
#include <random>
#include <ctime>
#include <utility>
using namespace std;

template <typename T>
struct MaxMin
{
	T Max;
	T Min;
	bool isMinMaxHeap;
	MaxMin(const T& Max, const T& Min, bool i) :Max(Max), Min(Min), isMinMaxHeap(i) {}
	MaxMin() = default;
};

template <typename T>
class MinMaxHeap //T只提供小于,其余用运算符重载
{
public:
	size_t getSize() { return _heap.size(); }
	T& _at(size_t index)
	{
		if (index >= _heap.size())
			return NULLVALUE;
		return _heap[index];
	}
	bool isEmpty() { return _heap.empty(); }
	bool isMinLevel(size_t i);
	void insert(const T &key);
	bool removeMinValue(T& key);
	bool removeMaxValue(T& key);
	bool changeValue(const T &key, size_t index);
	bool Delete(size_t index);
	MaxMin<T> isMinMaxHeap(size_t cur, bool isMinlevel);
	MinMaxHeap(const vector<T>& input, const T &v);
	bool natureMaintain()
	{
		if (isEmpty())
			return true;
		return isMinMaxHeap(0, true).isMinMaxHeap;
	}
private:
	T Min_value;
	T NULLVALUE;
	pair<size_t, bool> insert_adjust(bool isMinmiumLevel, size_t cur, const T& key);
	static bool less(const T& left, const T& right, bool d)
	{
		if (d)
		{
			return left < right;
		}
		else
		{
			return left > right;
		}
	}

	static bool lessEqual(const T& left, const T& right, bool d)
	{
		return less(left, right, d) || left == right;
	}
	void insertToHeapRootEmpty(size_t root, T key, bool d);
	vector<T> _heap;
};

template <typename T>
bool MinMaxHeap<T>::Delete(size_t index)
{
	if (index >= _heap.size())
	{
		cout << "Error,invaild index" << endl;
		return false;
	}
	changeValue(Min_value, index);
	removeMinValue(Min_value);
	return true;
}

template <typename T>
bool MinMaxHeap<T>::changeValue(const T& key, size_t index)
{
	if (key < Min_value)
	{
		cout << "invaild value" << endl;
		return false;
    }

	if (index >= _heap.size())
	{
		cout << "Error,invaild index" << endl;
		return false;
	}

	if (_heap[index] == key)
		return true;

	bool atMinlevel = isMinLevel(index);
	if (atMinlevel && _heap[index] < key || (!atMinlevel) && _heap[index] > key)
	{
		auto _pair = insert_adjust(atMinlevel, index + 1, key);
		insertToHeapRootEmpty(index, _heap[index], atMinlevel);
		insertToHeapRootEmpty(_pair.first - 1, key, _pair.second);
	}
	else
	{
		insert_adjust(atMinlevel, index + 1, key);
		if (index == 0)
			_heap[0] = key;
	}
	return true;
}

template <typename T>
MinMaxHeap<T>::MinMaxHeap(const vector<T>& input, const T& v):_heap(input), Min_value(v)
{
	for (auto run = input.cbegin(); run != input.cend(); ++run)
	{
		if (*run < Min_value)
		{
			cout << "Error,invaild value" << endl;
			exit(-1);
		}
	}

	size_t left_most = 1;
	size_t k = 0;
	for (; (left_most << 1) <= _heap.size(); left_most <<= 1) ++k;

	left_most >>= 1;
	bool in_Min_level;
	if (k % 2 == 1)
		in_Min_level = true;
	else
		in_Min_level = false;
	for (size_t run = _heap.size() >> 1; run > 0; --run)
	{
	    insertToHeapRootEmpty(run - 1, _heap[run - 1], in_Min_level);
		if (run == left_most)
		{
			in_Min_level = !in_Min_level;
			left_most >>= 1;
		}
	}
}

template <typename T>
bool MinMaxHeap<T>::isMinLevel(size_t i)
{
	size_t l = i + 1;
	size_t run = 1;
	bool isMinLevel = true;
	while ((run = run << 1) <= l)
	{
		if (isMinLevel)
		{
			isMinLevel = false;
		}
		else
		{
			isMinLevel = true;
		}
	}
	return isMinLevel;
}

template <typename T>
pair<size_t, bool> MinMaxHeap<T>::insert_adjust(bool isMinmiumLevel, size_t cur, const T &key)
{
	if (cur == 1)
		return { 1, true };
	bool testMinLevel;
	if (_heap[cur / 2 - 1] < key)
	{
		testMinLevel = false;
	}
	else
	{
		testMinLevel = true;
	}

	size_t sub = cur;
	cur /= 2;
	while (cur > 0)   
	{
		if (isMinmiumLevel)
		{
			if (testMinLevel == false)
			{
				if (_heap[cur - 1] < key)
				{
					_heap[sub - 1] = _heap[cur - 1];
					sub = cur;
				}
				else
				{
					_heap[sub - 1] = key;
					break;
				}
			}
			else
			{
				if (cur / 2 == 0)
				{
					_heap[sub - 1] = key;
					return { sub, true };
				}
			}
			isMinmiumLevel = false;
		}
		else
		{
			if (testMinLevel == true)
			{
				if (_heap[cur - 1] > key)
				{
					_heap[sub - 1] = _heap[cur - 1];
					sub = cur;
				}
				else
				{
					_heap[sub - 1] = key;
					break;
				}
			}
			else
			{
				if (cur / 2 == 0)
				{
					_heap[sub - 1] = key;
					return { sub, false };
				}
			}
			isMinmiumLevel = true;
		}
		cur /= 2;
	}

	if (cur == 0)
	{
		_heap[sub - 1] = key;
		return { sub, isMinmiumLevel };
	}
	else
	{
		if (sub / 2 == cur)
			return { sub, isMinmiumLevel };
		else
			return { sub, testMinLevel };
	}
}

template <typename T>
void MinMaxHeap<T>::insert(const T &key)
{
	if (key < Min_value)
	{
		cout << "Error, invaild value" << endl;
		return;
	}
	if (_heap.empty())
	{
		_heap.push_back(key);
		return;
	}

	_heap.push_back(key);  
	size_t cur = _heap.size();
	bool isMinmiumLevel = isMinLevel(cur - 1);
	insert_adjust(isMinmiumLevel, cur, key);
}

template <typename T>
bool MinMaxHeap<T>::removeMaxValue(T& key)
{
	if (_heap.empty())
	{
		return false;
	}

	if (_heap.size() == 1)
	{
		key = _heap[0];
		_heap.pop_back();
		return true;
	}

	size_t max;
	max = 1;
	if (3 <= _heap.size() && _heap[2] > _heap[max])
	{
		max = 2;
	}

	key = _heap[max];
	if (max + 1 == _heap.size())
	{
		_heap.pop_back();
		return true;
	}

	T re_insert = _heap.back();
	_heap.pop_back();
	insertToHeapRootEmpty(max, re_insert, false);
	return true;

}

template <typename T>
bool MinMaxHeap<T>::removeMinValue(T& key)
{
	if (_heap.empty())
	{
		return false;
	}

	if (_heap.size() == 1)
	{
		key = _heap[0];
		_heap.pop_back();
		return true;
	}

	key = _heap[0];
	T re_insert = _heap.back();
	_heap.pop_back();
	insertToHeapRootEmpty(0, re_insert, true);
	return true;
}

template <typename T>
void MinMaxHeap<T>::insertToHeapRootEmpty(size_t root, T key, bool d)
{
	while (true)
	{
		size_t _root = root + 1;
		if (_root * 2 > _heap.size())
		{
			_heap[root] = key;
			break;
		}

		size_t left = _root * 2;
		size_t second_smallest_or_largest;
		if (2 * left <= _heap.size())
		{
			second_smallest_or_largest = 2 * left - 1;

			if (2 * left + 1 <= _heap.size() && less(_heap[2 * left], _heap[second_smallest_or_largest], d))
			{
				second_smallest_or_largest = 2 * left;
			}

			if (2 * (left + 1) <= _heap.size())
			{
				if (less(_heap[2 * left + 1], _heap[second_smallest_or_largest], d))
				{
					second_smallest_or_largest = 2 * left + 1;
				}

				if (2 * (left + 1) + 1 <= _heap.size() && less(_heap[2 * (left + 1)], _heap[second_smallest_or_largest], d))
				{
					second_smallest_or_largest = 2 * (left + 1);
				}
			}
			else
			{
				if (less(_heap[left], _heap[second_smallest_or_largest], d))
				{
					second_smallest_or_largest = left;
				}
			}
		}
		else
		{
			second_smallest_or_largest = left - 1;
			if (left + 1 <= _heap.size() && less(_heap[left], _heap[second_smallest_or_largest], d))
			{
				second_smallest_or_largest = left;
			}
		}

		if (lessEqual(key, _heap[second_smallest_or_largest], d))
		{
			_heap[root] = key;
			break;
		}

		if (second_smallest_or_largest + 1 == 2 * _root || second_smallest_or_largest == 2 * _root)
		{
			_heap[root] = _heap[second_smallest_or_largest];
			_heap[second_smallest_or_largest] = key;
			break;
		}

		_heap[root] = _heap[second_smallest_or_largest];
		size_t parent = (second_smallest_or_largest + 1) / 2;
		if (less(_heap[parent - 1], key, d))
		{
			swap(_heap[parent - 1], key);
		}
		root = second_smallest_or_largest;
	}
}

template <typename T>
MaxMin<T> MinMaxHeap<T>::isMinMaxHeap(size_t cur, bool isMinlevel)
{
	size_t _cur = cur + 1;
	if (2 * _cur > _heap.size())
	{
		return MaxMin<T>(_heap[cur], _heap[cur], true);
	}

	MaxMin<T> temp;
	temp.isMinMaxHeap = false;
	MaxMin<T> result = isMinMaxHeap(2 * _cur - 1, isMinlevel ? false : true);
	if (result.isMinMaxHeap)
	{
		if (2 * _cur + 1 <= _heap.size())
		{
			MaxMin<T> result2 = isMinMaxHeap(2 * _cur, isMinlevel ? false : true);
			if (result2.isMinMaxHeap)
			{
				if (isMinlevel)
				{
					if (_heap[cur] <= result.Min && _heap[cur] <= result2.Min)
					{
						return MaxMin<T>(max(result.Max, result2.Max), _heap[cur], true);
					}
					else
					{
						cout << "节点" << _cur << "不是其子树中的最小值" << endl;
					}
				}
				else
				{
					if (_heap[cur] >= result.Max && _heap[cur] >= result2.Max)
					{
						return MaxMin<T>(_heap[cur], min(result.Min, result2.Min), true);
					}
					else
					{
						cout << "节点" << _cur << "不是其子树中的最大值" << endl;
					}
				}
			}
		}
		else
		{
			if (isMinlevel)
			{
				if (_heap[cur] <= result.Min)
				{
					return MaxMin<T>(result.Max, _heap[cur], true);
				}
				else
				{
					cout << "节点" << _cur << "不是其子树中的最小值" << endl;
				}
			}
			else
			{
				if (_heap[cur] >= result.Max)
				{
					return MaxMin<T>(_heap[cur], result.Min, true);
				}
				else
				{
					cout << "节点" << _cur << "不是其子树中的最大值" << endl;
				}
			}
		}
	}
	return temp;
}

int main()
{
	const int N = 10000;
	vector<int> input(N);
	for (int j = 0; j < N; ++j)
	{
		input[j] = j + 1;
	}
	shuffle(input.begin(), input.end(), default_random_engine());
	MinMaxHeap<int> obj(input, -200000);

	for (; obj.isEmpty() == false;)
	{
		size_t j;
		if (obj.getSize() == 1)
		{
			j = 1;
		}
		else
		{
			j = rand() % obj.getSize() + 1;
		}

		cout << "删除下标" << j << "元素" << endl;
		obj.Delete(j - 1);
		if (obj.natureMaintain())
		{
			cout << "最小最大堆性质维持" << endl;
		}
		else
		{
			cout << "最小最大堆性质破坏!" << endl;
			exit(-1);
		}
	}

	/*const int N = 10000;
	for (size_t i = 1; i <= N; ++i)
	{
		vector<int> input(i);
		for (int j = 0; j < i; ++j)
		{
			input[j] = j + 1;
		}
		shuffle(input.begin(), input.end(), default_random_engine(time(nullptr)));

		MinMaxHeap<int> _heap(input, -1);
		if (_heap.natureMaintain())
		{
			cout << "最小最大堆性质维持" << endl;
		}
		else
		{
			cout << "最小最大堆性质破坏" << endl;
			exit(-1);
		}
	}*/


	for (const auto& run : input)
	{
		cout << "插入" << run << endl;
		obj.insert(run);
		if (obj.natureMaintain())
		{
			cout << "最小最大堆性质维持" << endl;
		}
		else
		{
			cout << "最小最大堆性质破坏" << endl;
			exit(-1);
		}
	}

	for (size_t i = 1; i <= N; ++i)
	{
		size_t j;
		if (obj.getSize() == 1)
		{
			j = 1;
		}
		else
		{
			j = rand() % obj.getSize() + 1;
		}

		for (int run = -20; run <= 20; ++run)
		{
			cout << "将下标" << j << "元素" << "增加" << run << endl;
			obj.changeValue(obj._at(j - 1) + run, j - 1);
			if (obj.natureMaintain())
			{
				cout << "增加后最小最大堆性质维持" << endl;
			}
			else
			{
				cout << "增加后最小最大堆性质破坏!" << endl;
				exit(-1);
			}
			obj.changeValue(obj._at(j - 1) - run, j - 1);
			if (obj.natureMaintain())
			{
				cout << "恢复后最小最大堆性质维持" << endl;
			}
			else
			{
				cout << "恢复后最小最大堆性质破坏!" << endl;
				exit(-1);
			}

		}
	}

	/*while (_heap.isEmpty() == false)
	{
		int key;
		_heap.removeMinValue(key);
		cout << "移除最小值" << key << endl;
		if (_heap.natureMaintain())
		{
			cout << "最小最大堆性质维持" << endl;
		}
		else
		{
			cout << "最小最大堆性质破坏" << endl;
			exit(-1);
		}
	}

	/*while (_heap.isEmpty() == false)
	{
		int key;
		_heap.removeMaxValue(key);
		cout << "移除最大值" << key << endl;
		if (_heap.natureMaintain())
		{
			cout << "最小最大堆性质维持" << endl;
		}
		else
		{
			cout << "最小最大堆性质破坏" << endl;
			exit(-1);
		}
	}*/
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值