索引堆
构建成堆之后
优化版
C++实现
index_max_heap.h
#ifndef INDEX_MAX_HEAP_H
#define INDEX_MAX_HEAP_H
#include <cassert>
#include "index0_none.h"
// 索引最大堆
template <typename Item>
class IndexMaxHeap
{
private:
Item *data;
int *indexes;
int *reverse;
int count;
int capacity;
void shiftUp(int index);
void shiftDown(int index);
void __print()
{
for (int i = INDEX_0_FLAG; i < count + INDEX_0_FLAG; i++)
std::cout << data[indexes[i]] << " ";
std::cout << std::endl;
}
public:
IndexMaxHeap(int capacity);
IndexMaxHeap(Item arr[], int arr_length);
~IndexMaxHeap();
int size();
bool isEmpty();
void insert(int i, Item item);
Item extractTop();
int extractTopIndex();
Item getTop();
Item getItem(int index);
void change(int index, Item newItem);
};
template <typename Item>
IndexMaxHeap<Item>::IndexMaxHeap(int capacity)
{
data = new Item[capacity + INDEX_0_FLAG];
indexes = new int[capacity + INDEX_0_FLAG];
reverse = new int[capacity + INDEX_0_FLAG];
for (int i = 0; i < capacity + INDEX_0_FLAG; i++)
{
reverse[i] = INDEX_0_FLAG - 1;
}
count = 0;
this->capacity = capacity;
}
template <typename Item>
IndexMaxHeap<Item>::IndexMaxHeap(Item arr[], int arr_length)
{
// TODO 待修复
data = new Item[arr_length + INDEX_0_FLAG];
indexes = new int[capacity + INDEX_0_FLAG]; // 如何初始化?
reverse = new int[capacity + INDEX_0_FLAG]; // 如何初始化?
capacity = arr_length;
for (int i = 0; i < arr_length; i++)
data[i] = arr[i];
count = arr_length;
for (int i = getNotLeaf(count); i >= INDEX_0_FLAG; i--)
this->shiftDown(i);
}
template <typename Item>
IndexMaxHeap<Item>::~IndexMaxHeap()
{
delete[] data;
delete[] indexes;
delete[] reverse;
}
template <typename Item>
int IndexMaxHeap<Item>::size()
{
return count;
}
template <typename Item>
bool IndexMaxHeap<Item>::isEmpty()
{
return count == 0;
}
// index 为插入索引,从0开始
template <typename Item>
void IndexMaxHeap<Item>::insert(int index, Item item)
{
if (count + INDEX_0_FLAG > capacity)
{
capacity = capacity * 2;
Item *dataNew = new Item[capacity + INDEX_0_FLAG];
int *indexesNew = new int[capacity + INDEX_0_FLAG];
int *reverseNew = new int[capacity + INDEX_0_FLAG];
for (int i = INDEX_0_FLAG; i < count + INDEX_0_FLAG; i++)
{
dataNew[i] = data[i];
indexesNew[i] = indexes[i];
reverseNew[i] = reverse[i];
}
delete data;
delete indexes;
delete reverse;
data = dataNew;
indexes = indexesNew;
reverse = reverseNew;
}
assert(index >= 0 && index < capacity);
index = index + INDEX_0_FLAG;
data[index] = item;
indexes[count + INDEX_0_FLAG] = index;
reverse[index] = count + INDEX_0_FLAG;
count++;
this->shiftUp(count - 1 + INDEX_0_FLAG);
// __print();
}
template <typename Item>
Item IndexMaxHeap<Item>::extractTop()
{
assert(count > 0);
Item heapTop = data[indexes[INDEX_0_FLAG]];
std::swap(indexes[INDEX_0_FLAG], indexes[count - 1 + INDEX_0_FLAG]);
reverse[indexes[INDEX_0_FLAG]] = INDEX_0_FLAG;
reverse[indexes[count - 1 + INDEX_0_FLAG]] = INDEX_0_FLAG - 1;
count--;
this->shiftDown(INDEX_0_FLAG);
// __print();
return heapTop;
}
template <typename Item>
int IndexMaxHeap<Item>::extractTopIndex()
{
assert(count > 0);
int heapTop = indexes[INDEX_0_FLAG] - INDEX_0_FLAG;
std::swap(indexes[INDEX_0_FLAG], indexes[count - 1 + INDEX_0_FLAG]);
reverse[indexes[INDEX_0_FLAG]] = INDEX_0_FLAG;
reverse[indexes[count - 1 + INDEX_0_FLAG]] = INDEX_0_FLAG - 1;
count--;
this->shiftDown(INDEX_0_FLAG);
// __print();
return heapTop;
}
template <typename Item>
Item IndexMaxHeap<Item>::getTop()
{
assert(count > 0);
return data[INDEX_0_FLAG];
}
template <typename Item>
Item IndexMaxHeap<Item>::getItem(int index)
{
return data[index + INDEX_0_FLAG];
}
template <typename Item>
void IndexMaxHeap<Item>::change(int index, Item newItem)
{
index = index + INDEX_0_FLAG;
data[index] = newItem;
// 找到indexes[k] = index , k 表示data[index]在堆中的位置
// 之后 shiftUp(k) 和 shiftDown(k)
// for (int k = INDEX_0_FLAG; k < count + INDEX_0_FLAG; k++)
// {
// if (indexes[k] == index)
// {
// shiftUp(k);
// shiftDown(k);
// }
// }
// 使用 reverse 数组的优化版
int rev = reverse[index];
shiftUp(rev);
shiftDown(rev);
}
template <typename Item>
void IndexMaxHeap<Item>::shiftUp(int index)
{
// 索引0位置是根节点
while (index > INDEX_0_FLAG && data[indexes[getParent(index)]] < data[indexes[index]])
{
std::swap(indexes[getParent(index)], indexes[index]);
reverse[indexes[getParent(index)]] = getParent(index);
reverse[indexes[index]] = index;
index = getParent(index); // 父节点
}
}
template <typename Item>
void IndexMaxHeap<Item>::shiftDown(int index)
{
// 左孩子节点索引 <= count 表示索引index节点有左孩子节点
while (getLeftChird(index) < count + INDEX_0_FLAG)
{
int temp = getLeftChird(index); // 初始化为左孩子节点
if (getRightChird(index) < count + INDEX_0_FLAG)
{
// 当有右孩子节点时
if (data[indexes[getRightChird(index)]] > data[indexes[getLeftChird(index)]])
{
temp = getRightChird(index);
}
}
if (data[indexes[index]] >= data[indexes[temp]])
{
break;
}
std::swap(indexes[temp], indexes[index]);
reverse[indexes[temp]] = temp;
reverse[indexes[index]] = index;
index = temp;
}
}
#endif // INDEX_MAX_HEAP_H
index_max_heap_test.cpp
#include <iostream>
#include "index_max_heap.h"
using namespace std;
void print(IndexMaxHeap<int> &indexHeap)
{
while (!indexHeap.isEmpty())
{
cout << indexHeap.extractTop() << " ";
}
cout << endl;
}
// g++ index_max_heap_test.cpp && ./a.out
int main()
{
IndexMaxHeap<int> indexHeap(10);
srand(time(NULL));
for (int i = 0; i < 15; i++)
indexHeap.insert(i, rand() % 100);
print(indexHeap);
indexHeap.insert(0, 5);
indexHeap.insert(1, 7);
indexHeap.insert(2, 1);
indexHeap.change(0, 100);
print(indexHeap);
return 0;
}