在很多语言中,都有优先队列或者堆的的容器可以直接使用去创建大根堆或小根堆。但是在面试中,面试官更倾向于让更面试者自己实现一个堆。所以建议大家掌握堆的实现方法,尤其要搞懂「建堆」、「调整」和「删除」的过程。
优先队列
//less 表示按照递减插入元素
priority_queue<int, vector<int>, less<int>> s;
//greater 表示按照递增插入元素
priority_queue<int, vector<int>, greater<int>> s;
实现堆的方法:
ps:在看代码之前,要确保自己能演算大根堆和小根堆的实现过程。这样才好理解代码
大根堆
// i 为第一个非叶子节点的下标
void MaxHeapify(vector<int> &a,int i, int heapsize)
{
//l为i的左孩子 r为i的右孩子 largest是中间变量与左右孩子进行比较
int l = i*2+1, r = i*2+2, largest = i;
if(l < heapsize && a[l] > a[largest])
largest = l;
if(r < heapsize && a[r] > a[largest])
largest = r;
//如果largest与原来i相比发生了变化,则进行调整
if(largest != i)
{
swap(a[i], a[largest]);
MaxHeapify(a,largest,heapsize);
}
}
//构建大根堆 从最后一个非叶子节点向上
void buildMaxHeap(vector<int>& a, int heapsize)
{
for(int i = heapsize/2;i >= 0;--i)
MaxHeapify(a,i,heapsize);
//这下面是根据题目的需求添加或省略
for(int i = heapsize-1; i >= 1;i--)
{
//将当前最大的放置到数组末尾
swap(a[0],a[i]);
//将未完成的排序部分继续进行堆排序
MaxHeapify(a,0,i);
}
}
int main()
{
vector<int> a = {输入一组序列};
buildMaxHeap(a,a.size());
for(int i=0;i < a.size();i++)
{
cout<<a[i]<<' ';
}
return 0;
}
小根堆
void MinHeapify(vector<int>&a,int i,int heapsize)
{
//找到当前节点的左孩子
int l = 2*i+1;
int temp = a[i];
while(l < heapsize)
{
//确保与父节点交换的是最大的孩子
if(l+1<heapsize && a[l] < a[l+1]) ++l;
if(temp > a[l]) break;
else{
a[i] = a[l];
i = l;
l = 2*i+1;
}
}
a[i] = temp;
}
void buildMaxHeap(vector<int>& a, int heapsize)
{
for(int i = heapsize/2-1;i >= 0;--i)
MinHeapify(a,i,heapsize);
for(int i = n-1; i>= 1; --i)
{
swap(a[0], a[i]);
MinHeapify(a,0,i);
}
}