优先级队列实现为单一链接,无法更新插入的指针转换
Priority Queue implemented as singly linked failing to update pointer refrence on insert
编辑的问题:如何将指针参考作为参数的同时插入链接列表中?我更新的代码如下:
注意:我有一个队列的副本,用于将给定节点插入正确的位置,但是我无论如何都没有看到以更新原始队列,因为没有办法链接以前的节点。
解决:工作优先级队列(FIFO) - 需要清洁
#define QUEUE_HEAD_INDICATOR 0.0
namespace
{
pq* create_node(float priority = 0, const string & text = "")
{
pq* q = new pq;
q->priority = priority;
q->text = text;
q->next = nullptr;
return q;
}
}
pq* init_priority_queue() {
return create_node(QUEUE_HEAD_INDICATOR);
}
void insert(pq* &queue, string text, float priority) {
if (!queue) return;
pq* prev = queue;
pq* cursor = queue->next;
int offset = 0;
if(prev->priority == 0.0 && prev->text == "") {
prev->priority = priority;
prev->text = text;
return;
}
if(!cursor) {
if(prev->priority > priority) {
pq* node = create_node(priority, text);
node->next = prev;
prev = node;
} else {
pq* node = create_node(priority, text);
prev->next = node;
}
} else {
while(cursor && cursor->priority < priority) {
prev = cursor;
cursor = cursor->next;
offset++;
}
pq* node = create_node(priority, text);
if(offset == 0) {
if(cursor->priority == (int)node->priority) {
node->next = prev->next;
prev->next = node;
queue = prev;
} else {
node->next = prev;
prev = node;
queue = prev;
}
} else if(!cursor) {
prev->next = node;
} else {
node->next = prev->next;
prev->next = node;
}
return;
}
}
string remove(pq* &queue) {
pq* prev = queue;
pq* cursor = queue->next;
if(!queue->next) {
string text = queue->text;
prev = NULL;
return text;
}
while(cursor->next) {
prev = cursor;
cursor = cursor->next;
}
prev->next = NULL;
string text = cursor->text;
return text;
}
这是结构的样子
struct pq {
float priority;
string text;
pq* next;
};
我需要在此处做一个假设: queue
是指向链接列表的头节点的指针的引用。这似乎是一个合理的假设,因为它在if(queue->next == NULL)
情况下使用的方式。
以下代码将覆盖指向头节点的指针,然后将每个节点泄漏。
while(queue->next && queue->next->key < priority) {
queue = queue->next; // bam! previous node leaked back at the caller
}
您可以使用头节点的副本,但是...有更好的方法来处理此操作。
我的建议是不要将指针传递给根节点。将指针传递到指针。通过使头部看起来完全像其他节点并消除大多数代码,可以处理头情况。由于我们总是保留一个指向上一个节点的next
的指针,因此我们可以轻松访问新节点的插入点和下一个节点。
您不能用参考来执行此技巧,因为无法重新分配引用。
示例:
#include <string>
#include <iostream>
// my best guess at what pq looks like
struct pq
{
pq* next;
std::string text;
float key;
};
void insert(pq ** queue, // cannot reseat ref, so pointer required
const std::string &text, // ref eliminates copy.
// const because we don't want to change
float priority) {
while((*queue) && // search while more queues
(*queue)->key < priority) // and priority is low
{
queue = &(*queue)->next;
}
*queue = new pq{*queue, // if queue is null, end of list, if not inserted in middle
text,
priority};
}
// Demo
int main()
{
pq * queue = NULL;
insert(&queue, "c", 5);
insert(&queue, "a", 1);
insert(&queue, "b", 2.5);
insert(&queue, "e", 10);
insert(&queue, "d", 7.5);
// print and clean-up.
while (queue)
{
std::cout << queue->text << std::endl;
pq * temp = queue; // temp so we don't lose queue
queue = queue->next;
delete temp; // release node
}
}
分配queue = new_node
分配了插入函数的参数,而不是链接列表中间的指针(这是上一个元素的next
成员变量)。
pq* qp = new pq;
insert(qp, "0.1", 0.1f);
// qp -> 0.1
insert(qp, "0.3", 0.3f);
// qp -> 0.1 -> 0.3
insert(qp, "0.2", 0.2f);
// qp -> 0.2 -> 0.3
// qp now points to the 0.2 element, leaving the 0.1 element inaccessible
您的功能也永远不会将第一个元素的优先级与要插入长度> 1的队列的元素的优先级。您的wir循环仅比较要插入的元素的优先级与第一个元素以外的元素的优先级。
相关文章:
- 从C++本机插件更新Vector3数组
- 使用C++库在Android项目中修改gradle中的cmake参数,用于插入指令的测试
- 有关插入适配器的错误。[错误]请求从 'back_insert_iterator<vector<>>' 类型转换为非标量类型
- QGraphicsPolygonItem在拖动时未更新QPolygonF坐标
- 尝试使用 EvtSetChannelConfigProperty() 函数更新最大事件日志文件大小时插入的错误值
- 如果存在 QSQLITE 数据库,则根据 qt 中的行值插入或更新
- 插入新元素时结束迭代器会获得更新
- 优先级队列实现为单一链接,无法更新插入的指针转换
- 二进制树c++插入和更新
- 蒙戈更新插入性能(C++)
- 将项目"更新插入"到映射<键、shared_ptr的正确方法<foo>>
- 选择在 Sqlite 数据库中有效,但插入和更新语句不起作用
- C++ 链表 - 插入节点函数不会更新函数范围之外的值
- 插入或更新地图
- 在提升::unordered_map中有效地插入或更新
- 如何检查对象属性更新是否存在 std::map 键,否则插入一个新键?
- 如何使用 ODBC API 将数据更新插入到 NVARCHAR 列中
- MongoDB 更新插入在锁定时不会更新
- 不使用 if 插入/更新 std::unordered_map 元素的最快方法是什么
- 如何避免在重复更新的情况下插入到select中的死锁情况