使用指针和比较器 C++ 的优先级队列

2023-11-21

我刚刚开始学习C++,有一半的时间我不知道我在做什么,花几个小时在Google上搜索并盲目地将代码放入我的项目中,这可能是一个基本问题,但我似乎做不到把它做好。

这是要求对于我的任务,我需要这些:

在边缘类中:

public:
bool operator()(Edge*, Edge*)

在图表类中:

private:
priority_queue<Edge*, vector<Edge*>, Edge> edges

我在声明优先级队列时遇到问题。细节:

如果我直接使用这些,边缘类会给我一个错误“必须有类的参数”,我知道我不能将两个指针重载到 bool 运算符中,所以这是我尝试过的:

在 Edge.cpp 中:

#include "Edge.h"
using namespace std;

Edge::Edge(Vertex* s, Vertex* d, double w)
{
    source = s;
    destination = d;
    weight = w;
}

double Edge::getWeight()
{
    return weight;
}

struct CompareWeight : public std::binary_function<Edge*, Edge*, bool>
{
    bool operator()(Edge* e1,Edge* e2)
    {
        double w1 = e1->getWeight();
        double w2 = e2->getWeight();

        if(w1>w2){
            return true;
        }
        else {
            return false;
        }
    }
};

^ 我什至不确定将结构放入类中是否正确,另外,因为我不知道在 Edge.h 文件中放入什么。

在 Edge.h 中:

#include "Vertex.h"
class Edge
{
    public:
        Edge(Vertex*, Vertex*, double);
        double getWeight();
        friend struct CompareWeight; // ??? does not seems right
    private:
        Vertex* source;
        Vertex* destination;
        double weight;
}

至于 Graph 类才是真正的问题所在,我什至无法在没有错误的情况下声明优先级队列。

在 Graph.h 中

#include "Vertex.h"
#include "Edge.h"
#include <vector>
#include <queue>

class Graph
{
    public:
        ...

    private:
        priority_queue<Edge*, vector<Edge*>, Edge> edges
        // This give pointer error: no match for call to '(Edge) (Edge*&, Edge*&)'
}

第二次尝试:

// same as above
private:
    priority_queue<Edge*, vector<Edge*>, CompareWeight> edges
    // This give error: 'CompareWeight' not declared in this scope

我不知道为什么第一个错误,但第二个错误我清楚地理解了,但我不知道如何修复它,我应该在 CompareWeight 前面放一些东西吗?我尝试了很多东西,没有任何效果。

任何帮助将不胜感激!否则我可能会不及格这门课程。 第一次在 stackoverflow 提问,如果我做错了什么,请告诉我。


您的实施要求bool operator()(Edge*, Edge*)作为常规member班级的Edge这是可能的,但很少这样做。

标准库算法的比较器有以下惯用风格:all其中必须提供正在处理的序列中所包含对象的严格弱排序:

  1. 独立函子类
  2. 独立式operator <超载
  3. 对象类成员operator <超载。
  4. 独立功能
  5. 静态类函数
  6. 静态类仿函数类
  7. 其他几个...

此列表中的第五 (5) 个内容与他们的指示最接近trying要做,但它是never实施为operator(). It is possible作为以下成员做 (1)Edge,但要做到这一点Edge类型必须支持默认构造。稍后我将解释如何做到这一点。在上面列出的选项中,对于此特定情况,性能(内联的可能性)和实现简便性的最佳候选者是(1)和(6)。如果您的队列实际持有Edge objects而不是Edge pointers(3) 将是一个自然的选择并且提供不错的性能。

有序容器和容器适配器(如优先级队列)的比较器的要点是比较其中保存的两个项目是否符合严格弱序。如果你不知道那是什么,看到这个链接。在实施中,归结为:如果,并且仅当 x < y return true,否则返回false。这意味着必须执行以下规定:

  • x < x总是返回false
  • if x < y回报true, then y < x must return false
  • if both x < y and y < x返回 false,则x is 相等的 to y

不小心将比较器编码为不遵守这些规则是一个常见的错误。谨防这一点。

无论如何,我离题了。这样做的一种方法正确地给定您的类定义并使用上面列表中的 (1) 是:

阶级边缘

class Edge
{
public:
    Edge(Vertex* src, Vertex* dst, double w)
        : source(src), destination(dst), weight(w)
    {
    };

    // note: const-ness
    double getWeight() const { return weight; }

    Vertex const* getSource() const { return source; }
    Vertex* getSource() { return source; }

    Vertex const* getDestination() const { return destination; }
    Vertex* getDestination() { return destination; }

private:
    Vertex* source;
    Vertex* destination;
    double weight;
};

类 CmpEdgePtrs

struct CmpEdgePtrs
{
    bool operator()(const Edge* lhs, const Edge* rhs) const
    {
        return lhs->getWeight() < rhs->getWeight();
    }
};

类图

class Graph
{
    // rest of class stuff

private:
    priority_queue<Edge*, vector<Edge*>, CmpEdgePtrs> edges;
};

老实说,这是对共享智能指针的使用的尖叫,但我把它留给你了。上面的代码很有可能在实现优先级队列逻辑的标准库算法中的整个使用位置内联比较器,因此考虑到指针容器的约束,这样的性能将很有可能达到最佳。


完成分配的要求

This can完全在课堂上完成Edge,因为它毕竟只是一个类类型。作为优先级队列适配器的模板参数传递的第三种类型公开了bool operator(),没有什么可以阻止你只是做一个例子Edge为你做那件事。这很奇怪,但它仍然可以通过一些修改来工作:

首先,移动bool operator()(const Edge*, const Edge*) const to the Edge类,声明为 public。其次,提供一个默认构造函数Edge,因为在创建仿函数来执行比较时,优先级队列的内部算法将需要它。

class Edge
{
public:
    // regular parameterized construction
    Edge(Vertex* src, Vertex* dst, double w)
        : source(src), destination(dst), weight(w)
    {
    };

    // ADDED: allows parameterless initialization
    Edge() 
        : source(), designation(), weight() 
    {}

    // note: const-ness
    double getWeight() const { return weight; }

    Vertex const* getSource() const { return source; }
    Vertex* getSource() { return source; }

    Vertex const* getDestination() const { return destination; }
    Vertex* getDestination() { return destination; }

    // ADDED: used when an instance of `Edge` is used as comparator functor
    bool operator ()(const Edge* lhs, const Edge* rhs) const
    {
        return lhs->weight < rhs->weight;
    }

private:
    Vertex* source;
    Vertex* destination;
    double weight;
};


class Graph
{
    // rest of class stuff

private:
    // NOTE: uses Edge-type as the functor type that will
    //  deliver the comparison of Edge pointers.
    priority_queue<Edge*, vector<Edge*>, Edge> edges;
};

This is 极不寻常,但好处是允许函子直接访问成员变量Edge对象被比较,而不是通过公共 getter 和 setter 或必须与比较器成为好友。但它有一个缺点。没有什么可以阻止某人besides构建容器适配器Edge不指定来源、目的地和重量的对象。

简而言之,这样做没有什么好处,并且不正确使用使这项工作所需的代码可能会出现问题,为此,我会推荐第一个选项。

祝你好运

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用指针和比较器 C++ 的优先级队列 的相关文章

  • 查找哪些页面不再与写入时复制共享

    假设我在 Linux 中有一个进程 我从中fork 另一个相同的过程 后forking 因为原始进程将开始写入内存 Linux写时复制机制将为进程提供与分叉进程使用的不同的唯一物理内存页 在执行的某个时刻 我如何知道原始进程的哪些页面已被写
  • 如何在 Android NDK 中创建新的 NativeWindow 而无需 Android 操作系统源代码?

    我想编译一个 Android OpenGL 控制台应用程序 您可以直接从控制台启动 Android x86 运行 或者从 Android x86 GUI 内的 Android 终端应用程序运行 这个帖子 如何在 Android NDK 中创
  • 为什么要序列化对象需要 Serialized 属性

    根据我的理解 SerializedAttribute 不提供编译时检查 因为它都是在运行时完成的 如果是这样 那么为什么需要将类标记为可序列化呢 难道序列化器不能尝试序列化一个对象然后失败吗 这不就是它现在所做的吗 当某些东西被标记时 它会
  • 使用post方法将多个参数发送到asp.net core 3 mvc操作

    使用 http post 方法向 asp net mvc core 3 操作发送具有多个参数的 ajax 请求时存在问题 参数不绑定 在 dot net 框架 asp net web api 中存在类似的限制 但在 asp net mvc
  • 对齐 GridView 中的行值

    我需要在 asp net 3 5 中右对齐 gridview 列中的值 我怎样才能做到这一点
  • 显示异常时的自定义错误消息:从客户端检测到潜在危险的 Request.Form 值

    我在我的 Web 应用程序中使用 ASP NET 的登录控件 当发生此异常时 我想在标签上显示一种有趣的错误类型System Web HttpRequestValidationException A potentially dangerou
  • JSON 数组到 C# 列表

    如何将这个简单的 JSON 字符串反序列化为 C 中的列表 on4ThnU7 n71YZYVKD CVfSpM2W 10kQotV 这样 List
  • 暂停下载线程

    我正在用 C 编写一个非常简单的批量下载程序 该程序读取要下载的 URL 的 txt 文件 我已经设置了一个全局线程和委托来更新 GUI 按下 开始 按钮即可创建并启动该线程 我想要做的是有一个 暂停 按钮 使我能够暂停下载 直到点击 恢复
  • C 语言中 =+(等于加)是什么意思?

    我碰到 与标准相反 今天在一些 C 代码中 我不太确定这里发生了什么 我在文档中也找不到它 In ancientC 版本 相当于 它的残余物与最早的恐龙骨头一起被发现 例如 B 引入了广义赋值运算符 使用x y to add y to x
  • Azure 事件中心 - 按顺序接收事件

    我使用下面的代码从 Azure Event Hub 接收事件 https learn microsoft com en us azure event hubs event hubs dotnet framework getstarted s
  • C# 中条件编译符号的编译时检查(参见示例)?

    在 C C 中你可以这样做 define IN USE 1 define NOT IN USE 1 define USING system 1 system 1 IN USE 进而 define MY SYSTEM IN USE if US
  • 将构建日期放入“关于”框中

    我有一个带有 关于 框的 C WinForms 应用程序 我使用以下方法将版本号放入 关于 框中 FileVersionInfo GetVersionInfo Assembly GetExecutingAssembly Location F
  • 当“int”处于最大值并使用 postfix ++ 进行测试时,代码定义良好吗?

    示例 未定义行为的一个示例是整数溢出的行为 C11dr 3 4 3 3 int溢出是未定义的行为 但这是否适用于存在循环的以下内容 并且不使用现在超出范围的副作用i 特别是 这是否后缀增量规格帮助 结果的值计算在副作用之前排序 更新操作数的
  • 当我“绘制”线条时,如何将点平均分配到 LineRenderer 的宽度曲线?

    我正在使用线条渲染器创建一个 绘图 应用程序 现在我尝试使用线条渲染器上的宽度曲线启用笔压 问题在于 AnimationCurve 的 时间 值 水平轴 从 0 标准化为 1 因此我不能在每次添加位置时都在其末尾添加一个值 除非有一个我不知
  • 在类的所有方法之前运行一个方法

    在 C 3 或 4 中可以做到这一点吗 也许有一些反思 class Magic RunBeforeAll public void BaseMethod runs BaseMethod before being executed public
  • 是否可以有一个 out ParameterExpression?

    我想定义一个 Lambda 表达式out范围 有可能做到吗 下面是我尝试过的 C Net 4 0 控制台应用程序的代码片段 正如您在 procedure25 中看到的 我可以使用 lambda 表达式来定义具有输出参数的委托 但是 当我想使
  • 运算符“==”不能应用于“int”和“string”类型的操作数

    我正在编写一个程序 我想到了一个数字 然后计算机猜测了它 我一边尝试一边测试它 但我不断收到不应该出现的错误 错误是主题标题 我使用 Int Parse 来转换我的字符串 但我不知道为什么会收到错误 我知道它说 不能与整数一起使用 但我在网
  • WinRT 定时注销

    我正在开发一个 WinRT 应用程序 要求之一是应用程序应具有 定时注销 功能 这意味着在任何屏幕上 如果应用程序空闲了 10 分钟 应用程序应该注销并导航回主屏幕 显然 执行此操作的强力方法是在每个页面的每个网格上连接指针按下事件 并在触
  • 带重定向标准流的 C# + telnet 进程立即退出

    我正在尝试用 C 做一个 脚本化 telnet 项目 有点类似于Tcl期望 http expect nist gov 我需要为其启动 telnet 进程并重定向 和处理 其 stdin stdout 流 问题是 生成的 telnet 进程在
  • Googletest:如何异步运行测试?

    考虑到一个包含数千个测试的大型项目 其中一些测试需要几分钟才能完成 如果按顺序执行 整套测试需要一个多小时才能完成 通过并行执行测试可以减少测试时间 据我所知 没有办法直接从 googletest mock 做到这一点 就像 async选项

随机推荐