双端堆C++实现

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

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

template <typename T>
class DoubleEndHeap //T只提供小于,其余用运算符重载
{
public:
	bool isEmpty() { return _heap.size() == 1; }
	size_t getSize() { return _heap.size(); }
	T& _at(size_t index)
	{
		if (index >= _heap.size())
			return NULLVALUE;
		return _heap[index];
	}
	void insert(const T& key);
	bool removeMinValue(T& key);
	bool removeMaxValue(T& key);
	bool isDoubleEndHeap();
	bool changeValue(const T& value, size_t index);
	bool Delete(size_t index);
	DoubleEndHeap(const vector<T>& input, const T& Max_v, const T &Min_v);
	DoubleEndHeap(const T& N) :NULLVALUE(N)
	{
		_heap.push_back(N);
	}
private:
	T NULLVALUE;
	T Max_Value;
	T Min_Value;
	size_t max_node_for_min(size_t u);
	size_t min_node_for_max(size_t u);
	bool inMaxHeap(size_t u);
	void siftUpInMinHeap(size_t start, const set<size_t>& root);
	void siftUpInMaxHeap(size_t start, const set<size_t>& root);
	void compareAndAdjust(size_t left_in_min_heap, size_t right_in_max_heap);
	void adjustLeafAndFather(bool start_is_even, size_t leaf_start, size_t leaf_end, size_t father_start);
	size_t siftDownInMinHeap(size_t start);
	size_t siftDownInMaxHeap(size_t start);
	void processPairSubHeap(size_t left, size_t right, size_t length);
	bool isMinHeap(size_t u);
	bool isMaxHeap(size_t u);
	void process(size_t L, size_t R);
	vector<T> _heap;
};
template <typename T>
void DoubleEndHeap<T>::process(size_t L, size_t R)
{
	if (L << 1 > _heap.size())
	{
		if (R << 1 <= _heap.size())
		{
			if (_heap[(R << 1) - 1] > _heap[L - 1])
			{
				swap(_heap[(R << 1) - 1], _heap[L - 1]);
			}
			if ((R << 1) + 1 <= _heap.size())
			{
				if (_heap[R << 1] > _heap[L - 1])
				{
					swap(_heap[R << 1], _heap[L - 1]);
				}
			}
		}
	}
}

template <typename T>
bool DoubleEndHeap<T>::Delete(size_t index)
{
	if (index == 0 || index >= _heap.size())
	{
		cout << "Error,invaild index" << endl;
		return false;
	}

	if (inMaxHeap(index))
	{
		changeValue(Max_Value, index);
		removeMaxValue(Max_Value);
	}
	else
	{
		changeValue(Min_Value, index);
		removeMinValue(Min_Value);
	}
	return true;
}

template <typename T>
bool DoubleEndHeap<T>::changeValue(const T& value, size_t index)  //index是数组下标
{  
	if (value < Min_Value || value > Max_Value)
	{
		cout << "Error,invaild value" << endl;
		return false;
	}

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

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

	if (inMaxHeap(index))
	{
		if (_heap[index] > value)
		{
			_heap[index] = value;
			size_t down_point_in_max_heap = siftDownInMaxHeap(index + 1);
			size_t corr_point_in_min_heap = min_node_for_max(down_point_in_max_heap - 1) + 1;
			if (_heap[corr_point_in_min_heap - 1] > _heap[down_point_in_max_heap - 1])
			{
				swap(_heap[corr_point_in_min_heap - 1], _heap[down_point_in_max_heap - 1]);
			    set<size_t> _set({ 2 });
				siftUpInMinHeap(corr_point_in_min_heap, _set);
			}
			process(down_point_in_max_heap, corr_point_in_min_heap);
		}
		else
		{
			_heap[index] = value;
			set<size_t> _set({ 3 });
			siftUpInMaxHeap(index + 1, _set);
		}
	}
	else
	{
		if (_heap[index] < value)
		{
			_heap[index] = value;
			size_t down_point_in_min_heap = siftDownInMinHeap(index + 1);
			size_t corr_point_in_max_heap = max_node_for_min(down_point_in_min_heap - 1) + 1;

			bool flag = false;
			if (_heap[corr_point_in_max_heap - 1] < _heap[down_point_in_min_heap - 1])
			{
				swap(_heap[corr_point_in_max_heap - 1], _heap[down_point_in_min_heap - 1]);
				flag = true;
			}

			process(corr_point_in_max_heap, down_point_in_min_heap);
			if (flag)
			{
				set<size_t> _set;
				_set.insert(3);
				siftUpInMaxHeap(corr_point_in_max_heap, _set);
			}
		}
		else
		{
			_heap[index] = value;
			set<size_t> _set{2};
			siftUpInMinHeap(index + 1, _set);
		}
	}
	return true;
}
template <typename T>
DoubleEndHeap<T>::DoubleEndHeap(const vector<T>& input, const T& Max_v, const T& Min_v):_heap(1), Max_Value(Max_v), Min_Value(Min_v)
{ 
	for (auto run = input.cbegin(); run != input.cend(); ++run)
	{
		if (*run < Min_Value || *run > Max_Value)
		{
			cout << "Error,invaild value" << endl;
			exit(-1);
		}
	}
	_heap.insert(_heap.end(), input.begin(), input.end());

	if (_heap.size() <= 2) 
		return;
	size_t left_most = 2, k = 1;
	while ((left_most << 1) <= _heap.size())
	{
		left_most <<= 1;
		++k;
	}
	size_t lowest_layer_node_num = 1ULL << k;
	size_t lowest_layer_node_min_in_heap = _heap.size() - left_most + 1;

	size_t mid;

	if (lowest_layer_node_min_in_heap <= (lowest_layer_node_num >> 1) || lowest_layer_node_min_in_heap != lowest_layer_node_num)
	{
		if (lowest_layer_node_min_in_heap <= (lowest_layer_node_num >>= 1))
		{
			adjustLeafAndFather(false, left_most, _heap.size(), left_most - (lowest_layer_node_num >> 1));
		}
		else
		{
			processPairSubHeap(left_most, left_most + lowest_layer_node_num, lowest_layer_node_min_in_heap - lowest_layer_node_num);
			if (_heap.size() % 2 == 0)
				adjustLeafAndFather(true, left_most + lowest_layer_node_min_in_heap - lowest_layer_node_num, left_most + lowest_layer_node_num - 1, _heap.size() >> 1);
			else
				adjustLeafAndFather(false, left_most + lowest_layer_node_min_in_heap - lowest_layer_node_num, left_most + lowest_layer_node_num - 1, (_heap.size() >> 1) + 1);
		}
		left_most >>= 1;
	}
	lowest_layer_node_num >>= 1;
	mid = left_most + lowest_layer_node_num;

	while (left_most != mid)
	{
		processPairSubHeap(left_most, mid, lowest_layer_node_num);
		left_most >>= 1;
		mid >>= 1;
		lowest_layer_node_num >>= 1;
	}
}

template <typename T>
void DoubleEndHeap<T>::processPairSubHeap(size_t left, size_t right, size_t length)
{
	for (size_t length_run = 1; length_run <= length; ++length_run)
	{
		compareAndAdjust(left, right);
		++left;
		++right;
	}
}

template <typename T>
void DoubleEndHeap<T>::compareAndAdjust(size_t left_in_min_heap, size_t right_in_max_heap)
{
	{
		size_t down_point_in_max_heap = siftDownInMaxHeap(right_in_max_heap);
		size_t corr_point_in_min_heap = min_node_for_max(down_point_in_max_heap - 1) + 1;
		if (_heap[corr_point_in_min_heap - 1] > _heap[down_point_in_max_heap - 1])
		{
			swap(_heap[corr_point_in_min_heap - 1], _heap[down_point_in_max_heap - 1]);
			if (corr_point_in_min_heap != left_in_min_heap)
			{
				set<size_t> _set({ left_in_min_heap * 2, left_in_min_heap * 2 + 1 });
				siftUpInMinHeap(corr_point_in_min_heap, _set);
			}
		}

		process(down_point_in_max_heap, corr_point_in_min_heap);
	}
	size_t down_point_in_min_heap = siftDownInMinHeap(left_in_min_heap);
	size_t corr_point_in_max_heap = max_node_for_min(down_point_in_min_heap - 1) + 1;
	bool flag = false;
	if (_heap[corr_point_in_max_heap - 1] < _heap[down_point_in_min_heap - 1])
	{
		swap(_heap[corr_point_in_max_heap - 1], _heap[down_point_in_min_heap - 1]);
		flag = true;
	}
	process(corr_point_in_max_heap, down_point_in_min_heap);

	if (flag)
	{
		set<size_t> _set;
		_set.insert(right_in_max_heap);
		siftUpInMaxHeap(corr_point_in_max_heap, _set);
	}
}

template <typename T>
void DoubleEndHeap<T>::adjustLeafAndFather(bool start_is_even, size_t leaf_start, size_t leaf_end, size_t father_start)
{
	bool is_even_pos = start_is_even;
	for (size_t run = leaf_start; run <= leaf_end; ++run)
	{
		if (_heap[run - 1] > _heap[father_start - 1])
			swap(_heap[run - 1], _heap[father_start - 1]);
		if (is_even_pos)
		{
			is_even_pos = false;
			++father_start;
		}
		else
		{
			is_even_pos = true;
		}
	}
}

template <typename T>
size_t DoubleEndHeap<T>::siftDownInMinHeap(size_t start)
{
	size_t sub = 2 * start;
	T temp = _heap[start - 1];
	while (sub <= _heap.size())
	{
		if (sub < _heap.size() && _heap[sub - 1] > _heap[sub])
			++sub;
		if (temp <= _heap[sub - 1])
			break;
		_heap[start - 1] = _heap[sub - 1];
		start = sub;
		sub *= 2;
	}
	_heap[start - 1] = temp; 
	return start;
}

template <typename T>
void DoubleEndHeap<T>::siftUpInMaxHeap(size_t start, const set<size_t> &root)
{
	T temp = _heap[start - 1];
	size_t father = start / 2;
	while (root.find(start) == root.end())
	{
		if (temp <= _heap[father - 1])
			break;
		_heap[start - 1] = _heap[father - 1];
		start = father;
		father /= 2;
	}
	_heap[start - 1] = temp;
}

template <typename T>
size_t DoubleEndHeap<T>::siftDownInMaxHeap(size_t start)
{
	size_t sub = 2 * start;
	T temp = _heap[start - 1];
	while (sub <= _heap.size())
	{
		if (sub < _heap.size() && _heap[sub - 1] < _heap[sub])
			++sub;
		if (temp >= _heap[sub - 1])
			break;
		_heap[start - 1] = _heap[sub - 1];
		start = sub;
		sub *= 2;
	}
	_heap[start - 1] = temp;  //针对具体情况,该操作不应立即执行
	return start;
}

template <typename T>
void DoubleEndHeap<T>::siftUpInMinHeap(size_t start, const set<size_t>& root)
{
	T temp = _heap[start - 1];
	size_t father = start / 2;
	while (root.find(start) == root.end())
	{
		if (temp >= _heap[father - 1])
			break;
		_heap[start - 1] = _heap[father - 1];
		start = father;
		father /= 2;
	}
	_heap[start - 1] = temp;
}

template <typename T>
bool DoubleEndHeap<T>::isDoubleEndHeap()
{
	if (_heap.size() <= 2)
		return true;
	if (isMinHeap(1) == false)
	{
		cout << "左子堆不是最小堆!" << endl;
		return false;
	}

	if (isMaxHeap(2) == false)
	{
		cout << "右子堆不是最大堆!" << endl;
		return false;
	}

	deque<size_t> work_queue_left;
	work_queue_left.push_back(1);
	deque<size_t> work_queue_right;
	work_queue_right.push_back(2);
	while (work_queue_left.empty() == false)
	{
		size_t cur = work_queue_left.front();
		if (work_queue_right.empty() == false)
		{
			size_t right = work_queue_right.front();
			work_queue_right.pop_front();
			if (_heap[cur] > _heap[right])
			{
				cout << "左子堆节点" << cur + 1 << "关键码不小于等于右子堆对应节点" << right + 1 << "的关键码" << endl;
				return false;
			}

			if (2 * (right + 1) <= _heap.size())
			{
				work_queue_right.push_back(2 * right + 1);
				if (2 * (right + 1) + 1 <= _heap.size())
				{
					work_queue_right.push_back(2 * (right + 1));
				}
			}
		}
		else
		{
			break;
		}

		work_queue_left.pop_front();
		if (2 * (cur + 1) <= _heap.size())
		{
			work_queue_left.push_back(2*cur + 1);
			if (2 * (cur + 1) + 1 <= _heap.size())
			{
				work_queue_left.push_back(2 * (cur + 1));
			}
		}
	}

	if (work_queue_left.empty())
	{
		return true;
	}

	size_t parent = max_node_for_min(work_queue_left.front()) + 1;
	parent -= 1;
	bool left_child;
	if (((work_queue_left.front() + 1) & 1) == 0)
	{
		left_child = true;
	}
	else
	{
		left_child = false;
	}
	while (work_queue_left.empty() == false)
	{
		size_t n = work_queue_left.front();
		work_queue_left.pop_front();
		if (_heap[n] > _heap[parent])
		{
			cout << "左子堆节点" << n + 1 << "关键码不小于等于右子堆对应节点" << parent + 1 << "的关键码" << endl;
			return false;
		}
		if (left_child == false)
		{
			left_child = true;
			++parent;
		}
		else
		{
			left_child = false;
		}
	}
	return true;
}

template <typename T>
bool DoubleEndHeap<T>::isMaxHeap(size_t u)
{
	size_t cur = u + 1;
	if (2 * cur > _heap.size())
	{
		return true;
	}

	if (_heap[u] >= _heap[2 * cur - 1])
	{
		if (isMaxHeap(2 * cur - 1))
		{
			if (2 * cur + 1 <= _heap.size())
			{
				if (_heap[u] >= _heap[2 * cur])
				{
					if (isMaxHeap(2 * cur))
					{
						return true;
					}
					else
					{
						return false;
					}
				}
				else
				{
					cout << "节点" << cur << "关键码不大于等于子女节点关键码" << endl;
					return false;
				}
			}
			else
			{
				return true;
			}
		}
		else
		{
			return false;
		}
	}
	else
	{
		cout << "节点" << cur << "关键码不大于等于子女节点关键码" << endl;
		return false;
	}
}

template <typename T>
bool DoubleEndHeap<T>::isMinHeap(size_t u)
{
	size_t cur = u + 1;
	if (2 * cur > _heap.size())
	{
		return true;
	}

	if (_heap[u] <= _heap[2 * cur - 1])
	{
		if (isMinHeap(2 * cur - 1))
		{
			if (2 * cur + 1 <= _heap.size())
			{
				if (_heap[u] <= _heap[2 * cur])
				{
					if (isMinHeap(2 * cur))
					{
						return true;
					}
					else
					{
						return false;
					}
				}
				else
				{
					cout << "节点" << cur << "关键码不小于等于子女节点关键码" << endl;
					return false;
				}
			}
			else
			{
				return true;
			}
		}
		else
		{
			return false;
		}
	}
	else
	{
		cout << "节点" << cur << "关键码不小于等于子女节点关键码" << endl;
		return false;
	}
}

template <typename T>
bool DoubleEndHeap<T>::removeMaxValue(T& key)
{
	if (_heap.size() == 1)
		return false;

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

	key = _heap[2];
	size_t cur = 3;
	size_t temp = 2 * cur;
	T value = _heap.back();
	_heap.pop_back();
	while (temp <= _heap.size())
	{
		if (temp < _heap.size() && _heap[temp - 1] < _heap[temp])
		{
			++temp;
		}

		_heap[cur - 1] = _heap[temp - 1];
		cur = temp;
		temp *= 2;
	}
	_heap[cur - 1] = value;

	size_t max_cor_key_index = min_node_for_max(cur - 1);

	if ((max_cor_key_index + 1) * 2 <= _heap.size())
	{
		max_cor_key_index = 2 * max_cor_key_index + 1;
		if (max_cor_key_index + 2 <= _heap.size() && _heap[max_cor_key_index + 1] > _heap[max_cor_key_index])
		{
			max_cor_key_index = max_cor_key_index + 1;
		}
	}

	if (value >= _heap[max_cor_key_index])
	{
		set<size_t> _set{ 3 };
		siftUpInMaxHeap(cur, _set);
	}
	else
	{
		swap(_heap[cur - 1], _heap[max_cor_key_index]);
		set<size_t> _set{ 2 };
		siftUpInMinHeap(max_cor_key_index + 1, _set);
	}
	return true;
}

template <typename T>
bool DoubleEndHeap<T>::removeMinValue(T& key)
{
	if (_heap.size() == 1)
		return false;
	key = _heap[1];
	if (_heap.size() == 2)
	{
		_heap.pop_back();
		return true;
	}

	size_t cur = 2;
	size_t temp = 2 * cur;
	T value = _heap.back();
	_heap.pop_back();
	while (temp <= _heap.size())
	{
		if (temp < _heap.size() && _heap[temp - 1] > _heap[temp])
		{
			++temp;
		}

		_heap[cur - 1] = _heap[temp - 1];
		cur = temp;
		temp *= 2;
	}
	_heap[cur - 1] = value;

	if (_heap.size() <= 2)
	{
		return true;
	}

	size_t min_cor_key_index = max_node_for_min(cur - 1);
	if (value <= _heap[min_cor_key_index])
	{
		set<size_t> _set{ 2 };
		siftUpInMinHeap(cur, _set);
	}
	else
	{
		swap(_heap[cur - 1], _heap[min_cor_key_index]);
		set<size_t> _set{ 3 };
		siftUpInMaxHeap(min_cor_key_index + 1, _set);
	}
	return true;
}

template <typename T>
void DoubleEndHeap<T>::insert(const T& key)
{
	if (key < Min_Value || key > Max_Value)
	{
		cout << "Error,invaild value" << endl;
		return;
	}

	_heap.push_back(key);
	if (_heap.size() > 2)
	{
		if (inMaxHeap(_heap.size() - 1))
		{
			size_t min_cor_key_index = min_node_for_max(_heap.size() - 1);
			if (_heap[min_cor_key_index] <= _heap.back())
			{
				set<size_t> _set{ 3 };
				siftUpInMaxHeap(_heap.size(), _set);
			}
			else
			{
				swap(_heap[min_cor_key_index], _heap.back());
				set<size_t> _set{ 2 };
				siftUpInMinHeap(min_cor_key_index + 1, _set);
			}
		}
		else
		{
			size_t max_cor_key_index = max_node_for_min(_heap.size() - 1);
			if (_heap[max_cor_key_index] >= _heap.back())
			{
				set<size_t> _set{ 2 };
				siftUpInMinHeap(_heap.size(), _set);
			}
			else
			{
				swap(_heap[max_cor_key_index], _heap.back());
				set<size_t> _set{3};
				siftUpInMaxHeap(max_cor_key_index + 1, _set);
			}
		}
	}
}

template <typename T>
size_t DoubleEndHeap<T>::max_node_for_min(size_t u)
{
	size_t _u = u + 1;
	size_t k = 1;
	while (k << 1 <= _u)
	{
		k <<= 1;
	}
	k >>= 1;
	_u = _u + k;
	if (_u > _heap.size())
	{
		return _u / 2 - 1;
	}
	return _u - 1;
}

template <typename T>
size_t DoubleEndHeap<T>::min_node_for_max(size_t u)
{
	size_t _u = u + 1;
	size_t k = 1;
	while (k << 1 <= _u)
	{
		k <<= 1;
	}
	k >>= 1;
	_u = _u - k;
	return _u - 1;
}

template <typename T>
bool DoubleEndHeap<T>::inMaxHeap(size_t u)
{
	size_t cur = u + 1;
	while (true)
	{
		if (cur == 3)
		{
			return true;
		}

		if (cur == 2)
		{
			return false;
		}
		cur /= 2;
	}
}

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());
	DoubleEndHeap<int> obj(input, 200000, -200000);

	for (;obj.isEmpty() == false;)
	{
		size_t j = rand() % (obj.getSize() - 1) + 1;
		if (j == 1)
			j = 2;
		cout << "删除下标" << j << "元素" << endl;
		obj.Delete(j - 1);
		if (obj.isDoubleEndHeap())
		{
			cout << "双端堆性质维持" << endl;
		}
		else
		{
			cout << "双端堆性质破坏!" << endl;
			exit(-1);
		}
	}

	/*vector<int> input{16, 12, 12, 13, 14, 15};

	DoubleEndHeap<int> obj(input);

	if (obj.isDoubleEndHeap())
	{
		cout << "双端堆性质维持" << endl;
	}
	else
	{
		cout << "双端堆性质破坏!" << endl;
		exit(-1);
	}*/

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

		if (obj.isDoubleEndHeap())
		{
			cout << "双端堆性质维持" << endl;
		}
		else
		{
			cout << "双端堆性质破坏!" << endl;
			exit(-1);
		}
	}*/

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

	for (size_t i = 1; i <= N; ++i)
	{
		size_t j = rand() % (obj.getSize() - 1) + 1;
		if (j == 1)
			j = 2;
		for (int run = -20; run <= 20; ++run)
		{
			cout << "将下标" << j << "元素" <<"增加" << run << endl;
			obj.changeValue(obj._at(j - 1) + run, j - 1);
			if (obj.isDoubleEndHeap())
			{
				cout << "增加后双端堆性质维持" << endl;
			}
			else
			{
				cout << "增加后双端堆性质破坏!" << endl;
				exit(-1);
			}
			obj.changeValue(obj._at(j - 1) - run, j - 1);
			if (obj.isDoubleEndHeap())
			{
				cout << "恢复后双端堆性质维持" << endl;
			}
			else
			{
				cout << "恢复后双端堆性质破坏!" << endl;
				exit(-1);
			}

		}
	}

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

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值