最小最大堆是一种双端优先队列,用完全二叉树的二叉堆结构存放关键字,该数据结构的详细介绍见
数据结构(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;
}