前几篇博客介绍了数据结构堆以及堆排序,但是前面用到的堆有以下不足
(1)在构建堆时,需要首先将数组元素放入堆中,然后通过交换操作(ShiftDown)将合适的元素放入合适的位置,以满足堆的性质,当数组元素是整数之类比较简单的数据类型时,没什么问题,但是当数组元素特别复杂时,如每一个元素都是一个含有十万字文章的字符串时,交换操作就会消耗很大的资源,但是这种也可以通过计算机强大的软硬件能力来解决。
(2)第二个问题相对来讲就比较致命,在构建堆时,会将数组元素的索引改变,这样再想找到数组原来的索引时就很困难了,如下图所示原来数组中元素15对应的索引为1,但是构建完堆之后(下面第二张图),元素15对应的索引变为8了
索引堆(Index Heap)就是为了解决上面的两个问题提出来的
索引堆将索引(index)和数据(data)分开存储,真正表征堆的数组是由索引构建成的(下图中的index),
将上图数组构建成索引堆后,如下图
可以看出data数组内的元素没有变化,变化的是index数组
堆顶索引index为10,那么10对应的data中的元素是62,10的左节点为索引9, 9对应的data中的元素为41,10的右节点为索引7,7对应的data中的元素为28 …
下面是最大索引堆的构造函数
#include <iostream>
#include <algorithm>
#include <string>
#include <ctime>
#include <cmath>
#include <cassert>
#include <typeinfo>
using namespace std;
template<typename Item>
class IndexMaxHeap{
private:
Item *data;
int *indexes;
int count;
int capacity;
void ShiftUp(int k){
while (data[indexes[k/2]] < data[indexes[k]] && k > 1){
swap(indexes[k/2], indexes[k]);
k /= 2;
}
}
void ShiftDown(int k){
while (k <= count/2){
int j = 2*k; //此轮循环中,data[k]和data[j]交换位置
if (data[indexes[j]] < data[indexes[j+1]] && j + 1 <= count)
j += 1;
if (data[indexes[k]] >= data[indexes[j]])
break;
swap(indexes[j], indexes[k]);
k = j;
}
}
public:
IndexMaxHeap(int capacity){
data = new Item[capacity + 1];
indexes = new int[capacity + 1];
count = 0;
this->capacity = capacity