【问题标题】:Overloading set < operator重载集合 < 运算符
【发布时间】:2019-05-01 13:52:40
【问题描述】:

给定

struct node{
    int row;
    int cols;
    int cost;
}

我需要一个按路径成本排序的节点集,a==b 仅当行和列相等时。我的问题是如何重载 operator

【问题讨论】:

  • 如果您正在排序,则集合中不能有具有相同路径成本的不同节点。
  • 你能给我们举一些node的例子,以及你希望它们如何排序吗?
  • 例如,(3,2,3) (3,2,2) (4,3,2) (7,2,3) 将像 (3,2,2) 一样排序(4,3,2) (7,2,3)
  • @YunhaoLin 所以(3,2,3)(3,2,2) 在那里被评估为同一个节点,但是你如何决定(3,2,2)(4,3,2) 之间哪个先出现?
  • 取决于插入顺序

标签: c++ operator-overloading


【解决方案1】:

如果 a==b 则保存成本最低的那个

你不能使用 std::seta==b 意味着 a&lt;bb&lt;a 是假的,所以当 ab 有相同的 rowcols operator&lt; 必须返回 false 并且不考虑 cost

要获得预期的行为,您必须实现自己的set,而不仅仅是使用operator&lt; 进行排序/插入。

按路径成本排序

我想你的意思是按成本订购

使用 std::setoperator&lt; 我们可以想到:

  bool operator <(const node & rhs) const {
    // to satisfy a==b only if row and cols are equal
    if ((row == rhs.row) && (cols == rhs.cols))
      return false;

    return (cost < rhs.cost) ||
      ((cost == rhs.cost) &&
       ((row < rhs.row) || ((row == rhs.row) && (cols < rhs.cols))));
  }

但这是错误的,例如

#include <set>
#include <iostream>

struct node{
  int row;
  int cols;
  int cost;

  bool operator <(const node & rhs) const {
    // to satisfy a==b only if row and cols are equal
    if ((row == rhs.row) && (cols == rhs.cols))
      return false;

    return (cost < rhs.cost) ||
      ((cost == rhs.cost) &&
       ((row < rhs.row) || ((row == rhs.row) && (cols < rhs.cols))));
  }
};

int main()
{
  const node a[] = { {3,2,3} , {3,2,2}, {4,3,2}, {7,2,3}, {3, 2, 9} };
  std::set<node> s;

  for (size_t i = 0; i != sizeof(a)/sizeof(*a); ++i)
    s.insert(a[i]);

  for (auto x : s)
    std::cout << '(' << x.row << ' ' << x.cols << ' ' << x.cost << ')' << std::endl;

  return 0;
}

编译和执行:

pi@raspberrypi:/tmp $ g++ -pedantic -Wextra -Wall s.cc
pi@raspberrypi:/tmp $ ./a.out
(4 3 2)
(3 2 3)
(7 2 3)
(3 2 9)

set 包含 3 2 33 2 9,即使它们必须被视为相等。

operator&lt; 是错误的,因为在将 3 2 33 2 9 与其他值进行比较时它不一致:7 2 3 小于 3 2 9 但不小于 3 2 3

a==b 仅当 row 和 cols 相等时

暗示排序必须只考虑rowcols,但cost必须使用 p>

例如

#include <set>
#include <iostream>

struct node{
  int row;
  int cols;
  int cost;

  bool operator <(const node & rhs) const {
    return (row < rhs.row) || ((row == rhs.row) && (cols < rhs.cols));
  }
};

int main()
{
  const node a[] = { {3,2,3} , {3,2,2}, {4,3,2}, {7,2,3}, {3, 2, 9} };
  std::set<node> s;

  for (size_t i = 0; i != sizeof(a)/sizeof(*a); ++i)
    s.insert(a[i]);

  for (auto x : s)
    std::cout << '(' << x.row << ' ' << x.cols << ' ' << x.cost << ')' << std::endl;

  return 0;
}

编译和执行:

pi@raspberrypi:/tmp $ g++ -pedantic -Wextra -Wall s.cc
pi@raspberrypi:/tmp $ ./a.out
(3 2 3)
(4 3 2)
(7 2 3)
pi@raspberrypi:/tmp $ 

尊重预期的平等,但不涉及成本


来自 C++11(感谢@PaulMcKenzie 的评论):

  bool operator <(const node & rhs) const {
    return std::tie(row, cols) < std::tie(rhs.row, rhs.col);
  }

当需要考虑很多领域时非常实用

【讨论】:

  • 嗯,这也是我的第一个想法,但它只有在相似节点彼此相邻时才有效。例如,将节点 (3,2,9) 添加到数组的末尾不会看到它与 (3,2,3) 相同:ideone.com/OAxAmL
  • @scohe001 啊是的,其实就是说操作符
  • @scohe001 谢谢你,我编辑了我的答案......然后回到我给出的第一个版本,即使我改变了它......因为你^^
  • @bruno return (row &lt; rhs.row) || ((row == rhs.row) &amp;&amp; (cols &lt; rhs.cols)); -- 使用std::tie 无需弄清楚逻辑并自动为您执行级联逻辑。 return std::tie(row, cols) &lt; std::tie(rhs.row, rhs.col);
  • @PaulMcKenzie 是的,你是对的,C++11 的礼物之一,谢谢你的评论,我编辑了我的答案
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-06-11
  • 1970-01-01
  • 2014-10-29
  • 2012-04-03
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多