way:看上去好像就是加了个indexMap记录节点在数组heap中的下标,然后就是可以查到某个元素是否在堆里并且可以进行位置的调整,普通的堆是没法知道元素是不是在的,只能弹堆顶元素,插入到堆尾这样子。如果觉得heapSize有点混淆的话,可以heapSize处理之后再去做操作,不用++,--搞得不明白。知道方法的实现过程就好啦,swap在交换时同步修改indexMap,remove把remove的元素和最后的交换,要remove的元素在最后,再调整在 i 位置处的end元素就可以了。heapInsert和heapify和普通堆相比都多了index参数。
成员: vector<Node *> heap, map<Node *, int> indexMap, int heapSize, comp对象比较函数(我没用,可以根据情况看要不要)。
方法:构造,bool isEmpty,int size,bool contains,Node * top,void push(Node * node),Node * pop,void remove(Node * node),void resign(Node *node),void heapInsert(int index),void heapify(int index),void swap(int i, int j),vector<Node *> getAllElements。
#include<iostream>
#include<vector>
#include<map>
using namespace std;
typedef int T;
struct Node
{
T val;
Node(T val)
{
this->val = val;
}
};
//这回不限制大小了哈哈哈
class MyMaxHeap
{
private:
vector<Node*>heap;
map<Node*, int>indexMap;
int heapSize;
public:
MyMaxHeap()
{
heapSize=0;
}
bool isEmpty()
{
return heapSize==0;
}
int size()
{
return heapSize;
}
bool contains(Node *node)
{
return indexMap.count(node)>0;
}
Node *top()
{
if(isEmpty()) return nullptr;
return heap[0];
}
void push(Node *node)
{
heap.push_back(node);
heapSize++;
indexMap[node]= heapSize-1;
heapInsert(heapSize-1);
}
//这个swap函数在交换的同时把indexMap也悄悄的交换了
void swap(int i, int j)
{
Node *a = heap[i];
Node *b = heap[j];
indexMap[a]=j;
indexMap[b]=i;
heap[i]=b;
heap[j]=a;
}
void heapInsert(int index)
{
//从index位置开始向上浮动
int fa = (index-1)/2;
while(heap[index]->val > heap[fa]->val)
{
swap(index, fa);
index = fa;
fa = (index-1)/2;
}
}
Node *pop()
{
//要删除堆顶的元素
Node *del = heap[0];
//最后一个元素
//Node *end = heap[heapSize-1];
//交换之后要删除的数在堆尾,堆尾的元素在0位置处待处理
swap(0, heapSize-1);
//先处理要删除的元素
heap.pop_back();
indexMap.erase(del);
heapSize--;
//再处理在0位置的元素
heapify(0);
return del;
}
void heapify(int index)
{
int left = 2*index+1;
//从index位置开始往下沉
while(left < heapSize)
{
int maxChild = (left+1<heapSize && heap[left+1]->val > heap[left]->val)? left+1:left;
if(heap[index]->val > heap[maxChild]->val)
{
break;
}
swap(index, maxChild);
index = maxChild;
left = 2*index+1;
}
}
void remove(Node *node)
{
Node *end = heap[heapSize-1];
int i = indexMap[node];
//交换要移除的元素和最后一个元素的位置
swap(i, heapSize-1);
//此时要移除的元素在最后,最后一个元素在i位置上
//处理要移除的元素
heap.pop_back();
indexMap.erase(node);
heapSize--;
//处理在i位置上的元素
resign(end);
}
void resign(Node *node)
{
int index = indexMap[node];
//可能往上浮
heapInsert(index);
//也可能往下沉
heapify(index);
}
vector<Node *>getAllElements()
{
return heap;
}
};
int main()
{
MyMaxHeap heap;
vector<Node*>nodes;
nodes.push_back(new Node(1));
nodes.push_back(new Node(2));
nodes.push_back(new Node(3));
nodes.push_back(new Node(4));
nodes.push_back(new Node(5));
nodes.push_back(new Node(6));
for(auto node:nodes)
{
heap.push(node);
}
cout<<"堆顶元素是"<<endl;
cout<<heap.top()->val<<endl;
cout<<"移除元素6"<<endl;
heap.remove(nodes[5]);
cout<<"堆顶元素是"<<endl;
cout<<heap.top()->val<<endl;
cout<<"移除元素5"<<endl;
heap.remove(nodes[4]);
cout<<"堆顶元素是"<<endl;
cout<<heap.top()->val<<endl;
system("pause");
return 0;
}
可以和普通大根堆对比着看实现过程。手写堆(大根堆)-CSDN博客