构建具有堆的优先级队列
Building a priority queue with a heap
如果堆基于数组并提取根,则我使用的代码假设重新洗牌节点,以便维护堆属性。
根据我的理解,数组和堆并不完全相同,但似乎在代码中,构建堆只是重新排列数组,以便它包含堆属性。这是创建堆的标准方法吗?是否有必要填充另一个数组,而不仅仅是更改它所基于的数组?
我很难理解这个概念,因为当我使用函数 extract-max
删除根时,除非我从数组中弹出元素,否则数组的大小保持不变。堆应该更小,但发生的所有情况是向上移动以替换根的节点由数组中的零指示,并且不会被删除。
如果我确实保留了堆基本上是服从堆属性的数组的结构,如何删除不应再成为堆一部分的节点?在我的代码中,打印数组时,此节点由0
表示。
#include <iostream>
#include <deque>
#include "print.h"
#include "random.h"
int parent(int i)
{
return (i - 1) / 2;
}
int left(int i)
{
if(i == 0)
return 1;
else
return 2*i;
}
int right(int i)
{
if(i == 0)
return 2;
else
return 2*i + 1;
}
void max_heapify(std::deque<int> &A, int i, int heapsize)
{
int largest;
int l = left(i);
int r = right(i);
if(l <= heapsize && A[l] > A[i])
largest = l;
else
largest = i;
if(r <= heapsize && A[r] > A[largest])
largest = r;
if(largest != i) {
exchange(A, i, largest);
max_heapify(A, largest, heapsize);
}
}
void build_max_heap(std::deque<int> &A)
{
int heapsize = A.size() - 1;
for(int i = (A.size() - 1) / 2; i >= 0; i--)
max_heapify(A, i, heapsize);
}
int heap_extract_max(std::deque<int> &A, int heapsize)
{
if(heapsize < 0)
throw std::out_of_range("heap underflow");
int max = A.front();
//A.pop_front();
A[0] = A[heapsize--];
//A.pop_back();
max_heapify(A, 0, heapsize);
return max;
}
int main(int argc, const char * argv[])
{
std::deque<int> B = deq(7);
print(B);
build_max_heap(B);
print(B);
std::cout << "Extract max ->t" << heap_extract_max(B, B.size()) << std::endl;
print(B);
std::cout << "Extract max ->t" << heap_extract_max(B, B.size()) << std::endl;
print(B);
return 0;
}
输出:
79 92 86 29 27 42 6
92 86 79 29 27 42 6
Extract max -> 92
86 79 42 29 27 0 6
Extract max -> 86
79 42 27 29 0 0 6
您的heap_extract_max
函数正在丢弃std::deque
中的最后一个元素。
int heap_extract_max(std::deque<int> &A, int heapsize)
{
if(heapsize < 0)
throw std::out_of_range("heap underflow");
int max = A.front(); // Get a copy of the first element
A[0] = A[heapsize--]; // Copy the last element to the first element
// and reduce the heap size, effectively
// discarding the last element.
max_heapify(A, 0, heapsize);
return max;
}
在此之后,如果需要,可以安全地使用std::deque
上的pop_back()
从容器中删除该元素。
所以。我更改了max-heapify
以将索引返回到应删除的节点。
int max_heapify(std::deque<int> &A, int i, int heapsize)
{
int largest;
int l = left(i);
int r = right(i);
if(l <= heapsize && A[l] > A[i])
largest = l;
else
largest = i;
if(r <= heapsize && A[r] > A[largest])
largest = r;
if(largest != i) {
exchange(A, i, largest);
int j = max_heapify(A, largest, heapsize);
return j;
}
return i;
}
然后我删除了heap_extract_max
中的元素
int heap_extract_max(std::deque<int> &A, int heapsize)
{
if(heapsize < 0)
throw std::out_of_range("heap underflow");
int max = A.front();
A[0] = A[heapsize--];
int i = max_heapify(A, 0, heapsize);
A.erase(A.begin() + i);
return max;
}
我得到 11 个元素的输出:
79 10 61 99 28 12 51 96 13 37 83
99 96 83 79 37 61 51 10 13 28 12
Extract max -> 99
96 83 61 79 37 12 51 10 13 28
Extract max -> 96
83 79 61 51 37 12 10 13 28
我最初真的认为,在将最后一个元素的值记录到根中后,我只能弹出最后一个元素,然后重新组织堆,但它并不合作。因此,另一种方法是在重新组织堆后删除节点位置。
回到原始代码:
我意识到问题出在哪里。我需要在使用变量索引数组之前递减堆大小,而不是之后。然后我可以按照我想要的方式弹出最后一个元素。
int heap_extract_max(std::deque<int> &A, int heapsize)
{
if(heapsize < 0)
throw std::out_of_range("heap underflow");
int max = A.front();
A[0] = A[--heapsize];
A.pop_back();
max_heapify(A, 0, heapsize);
//int i = max_heapify(A, 0, heapsize);
//A.erase(A.begin() + i);
return max;
}
相关文章:
- C++优先级队列,按对象的唯一指针的特定方法升序排列
- 按对象的特定方法按升序排列的C++优先级队列
- 使用2个键的cpp-stl::优先级队列排序不正确
- 为什么我需要C++中不同的排序格式来对这个USACO代码上的数组和优先级队列进行排序
- 打印优先级队列
- 带自定义比较器的最小优先级队列
- 优先级队列自定义比较器
- 排序数组优先级队列
- 更改运行时优先级队列的排序功能
- 优先级队列构造函数的工作
- 实现优先级队列
- 优先级队列功能比较
- 在C++中打印对的优先级队列的所有值时出现问题
- 使用堆的优先级队列,具有相同键的值不遵循 FIFO(先进先出)
- 为什么某些 STL 容器(堆栈、队列、优先级队列)不支持迭代器?
- 是否可以使用简单队列创建优先级队列
- 如何在 c++ 中创建对的优先级队列.这会弹出具有最小值的元素.默认的弹出最大值
- Cython中带有自定义比较器的优先级队列
- 优先级队列比较器[C++].
- asio::io_service 具有多个线程的优先级队列处理