#include <iostream>
using namespace std;
class MaxHeap {
int *data;
int capacity, count;
bool isRoot(int n) {
return n == 1;
}
bool isLeaf(int n) {
return n > count / 2;
}
int root(int n) {
return n / 2;
}
int left(int n) {
return n * 2;
}
int right(int n) {
return n * 2 + 1;
}
int getMaxChild (int n) {
if (n * 2 == count)
return left(n);
return data[left(n)] > data[right(n)] ? left(n) : right(n);
}
void exchange(int *a, int i, int j) {
if (i == j)
return;
a[i] ^= a[j];
a[j] ^= a[i];
a[i] ^= a[j];
}
void swim(int n) {
if (isRoot(n))
return;
if (data[n] > data[root(n)]) {
exchange(data, n, root(n));
}
swim(root(n));
}
void sink(int n) {
if (isLeaf(n))
return;
int maxChild = getMaxChild(n);
if (data[n] >= data[maxChild])
return;
exchange(data, n, maxChild);
sink(maxChild);
}
public:
explicit MaxHeap(int capacity) : capacity(capacity), count(0) {
data = new int[capacity + 1];
}
MaxHeap(int *a, int size, int capacity) : data(a), capacity(capacity), count(size) {}
~MaxHeap() {
delete[] data;
}
MaxHeap(const MaxHeap&) = delete;
MaxHeap& operator=(const MaxHeap&) = delete;
bool insert(int value) {
if (isFull())
return false;
data[++count] = value;
swim(count);
return true;
}
bool popMax(int &value) {
if (isEmpty())
return false;
value = data[1];
data[1] = data[count--];
sink(1);
return true;
}
bool isEmpty() {
return count == 0;
}
bool isFull() {
return count == capacity;
}
int size() {
return count;
}
void makeHeap() {
for (int i = count / 2; i > 0; --i)
sink(i);
}
void sortHeap() {
for (int i = count; i > 0; --i) {
exchange(data, 1, i);
MaxHeap tmp(data, i - 1, capacity);
tmp.sink(1);
}
}
bool isMaxHeap() {
for (int i = 1; !isLeaf(i); ++i) {
if (data[i] < data[getMaxChild(i)])
return false;
}
return true;
}
};
bool test(MaxHeap &maxHeap) {
int a[] = {4,7,3,1,8,2,5,0,9,6};
int size = sizeof(a) / sizeof(*a);
if (!maxHeap.isEmpty()) {
cout << __LINE__ << " heap should empty" << endl;
return false;
}
for (int i = 0; i < size; ++i) {
if (!maxHeap.insert(a[i])) {
cout << __LINE__ << " insert failed" << endl;
return false;
}
if (maxHeap.size() != i + 1) {
cout << __LINE__ << " size = " << maxHeap.size() << ", but expect " << i + 1 << endl;
return false;
}
}
if (!maxHeap.isMaxHeap()) {
cout << __LINE__ << " should be heap" << endl;
return false;
}
int value;
for (int i = 0; i < size; ++i) {
if (!maxHeap.popMax(value)) {
cout << __LINE__ << " pop failed" << endl;
return false;
}
if (maxHeap.size() + i + 1 != size) {
cout << __LINE__ << " size = " << maxHeap.size() << ", but expect "
<< size - i - 1 << endl;
return false;
}
if (value + i != size - 1) {
cout << __LINE__ << " value = " << value << ", but expect "
<< size - i - 1 << endl;
return false;
}
}
if (maxHeap.popMax(value)) {
cout << __LINE__ << " heap should empty" << endl;
return false;
}
return true;
}
bool testMakeHeap() {
int a[] = {-1,4,7,3,1,8,2,5,0,9,6};
int size = sizeof(a) / sizeof(*a) - 1;
MaxHeap maxHeap(a, size, size);
maxHeap.makeHeap();
if (!maxHeap.isMaxHeap()) {
cout << __LINE__ << " should be heap" << endl;
return false;
}
maxHeap.sortHeap();
for (int i = 1; i <= size; ++i) {
cout << a[i] << ", ";
}
cout << endl;
for (int i = 1; i <= size - 1; ++i) {
if (a[i] > a[i + 1])
return false;
}
return true;
}
int main() {
MaxHeap maxHeap(100);
cout << boolalpha << test(maxHeap) << endl;
cout << boolalpha << testMakeHeap() << endl;
return 0;
}
堆实现优先队列,以及数组堆化和堆排序
最新推荐文章于 2022-12-12 17:24:14 发布