【问题标题】:How should I compare pairs of pointers (for sort predicate)我应该如何比较指针对(用于排序谓词)
【发布时间】:2010-04-23 15:08:45
【问题描述】:

我有一个 STL 容器,里面装满了以下数十亿个对象

pair<SomeClass*, SomeClass*>

我需要以下形式的一些功能

/*returns items sorted biggest first */

bool sortPredicate (pair<SomeClass*, SomeClass*>two,  pair<SomeClass*, SomeClass*> one)
{
  return ???;
}

有什么技巧可以用来快速比较指针对吗?

编辑 1:澄清

最后我只想对指针对列表进行排序,使所有重复项彼此相邻。假设 SomeClass 中没有明确的方法可用于此目的——我只有指针对,我想找到所有相同的对(并行)。我认为排序可以解决问题,但如果您能想到更好的并行方法,请告诉我。

编辑 2:澄清

修复了我的代码(排序谓词的参数错误——它们应该是对的)。

【问题讨论】:

  • 你能不能更具体一点 sortPredicate 应该返回什么?你能举个简单的例子吗(可能是int* 什么的?)
  • 我希望能够使用指向任意类的指针来做到这一点。指针是每个对象的唯一标识符,因此它们应该用于确定两对这些对象是否重复。
  • 好吧,我很困惑。我不知道你想要完成什么。您可能需要考虑提供输入和预期输出的示例。
  • 我很困惑。为什么不直接使用默认排序?这将按指针地址对指针对进行排序。
  • 你想要所有重复的对象相邻,还是所有重复的指针

标签: c++ stl sorting


【解决方案1】:

C++ 的一个怪癖是,相同类型的任意指针不能(必然)与 std::less 可比。

不幸的是,std::pairoperator&lt; 是根据组件上的operator&lt; 定义的,而不是std::less

因此,假设您希望两对落在相同的排序位置当且仅当它们指向相同的两个对象时,您需要:

// "less than"
template<typename T>
bool lt(const T &lhs, const T &rhs) {
    return std::less<T>()(lhs, rhs);
}

typedef std::pair<SomeClass*, SomeClass*> mypair;

bool sortPredicate(const mypair &lhs, const mypair &rhs) {
    return lt(lhs.first, rhs.first) 
        || (!lt(rhs.first, lhs.first) && lt(lhs.second, rhs.second));
 }

在您可以命名的几乎任何系统上,它都应该编译为与return lhs &lt; rhs; 相同的代码,但这在形式上是不正确的。如果指针的引用都是同一对象的子对象(例如,如果您有一个巨大的数组并且所有对都指向该数组的元素),那么 operator&lt; 对于指针来说是可以的,因此对于 @987654329 来说是可以的@。

如果您希望配对落在相同的排序位置当且仅当它们指向的对象排序相同,那么您需要添加额外的取消引用:

bool sortPredicate(const mypair &lhs, const mypair &rhs) {
    return lt(*lhs.first, *rhs.first) 
        || (!lt(*rhs.first, *lhs.first) && lt(*lhs.second, *rhs.second));
 }

如果允许的话,也许您还会添加对空指针的检查。当然如果你知道 SomeClass 确实是类类型,而不是指针类型,那么就不需要在上面的版本中使用std::less,只需为 SomeClass 定义operator&lt; 并:

inline bool lessptr(const SomeClass *lhs, const SomeClass *rhs) {
    if (lhs == 0) return rhs != 0;
    if (rhs == 0) return false;
    return *lhs < *rhs;
}

bool sortPredicate(const mypair &lhs, const mypair &rhs) {
    return lessptr(lhs.first, rhs.first) 
        || (!lessptr(rhs.first, lhs.first) && lessptr(lhs.second, rhs.second));
 }

您可能会也可能无法优化这一点,因为在第一次和第二次调用lessptr 时都会执行一些重复的空检查。如果你那么在意,看看编译器是怎么处理它的。

【讨论】:

  • 让我猜猜 - 这个:"lhs.second
  • +1 提到 std::less 保证了指针的总顺序。但是 std::less 是一个类模板,而不是一个函数。而不是less(lhs,rhs),你必须写std::less&lt;SomeClass*&gt;()(lhs,hrs),不是吗?
【解决方案2】:

假设你的类有比较运算符:

bool sortPredicate (SomeClass *two,  SomeClass *one)
{
  return *two > *one;
}

如果只想比较指针地址,使用std::greater&lt;T&gt;

sort(container.begin(), container.end(), std::greater<SomeClass *>());

编辑:好的,我真的不知道你现在想做什么,你最近的编辑。如果您只想查找重复项,为什么不直接使用默认排序?

【讨论】:

  • 这里不比较指针,而是使用SomeClass的运算符
  • 这个问题有点模糊。在代码中它写着/*returns items sorted biggest first */,所以我假设他想比较这些类。但是,我添加了一个实际比较指针的解决方案。
  • @Danvil:我认为(未说出口的)一点是,在排序时比较指针通常没有意义。
  • 谁知道呢,但现在 conradlee 可以决定他需要什么。
  • 我试图在我上次修订的问题中澄清这一点。我的问题现在清楚了吗?
【解决方案3】:

如果我理解正确,您的谓词应具有以下签名

bool sortPredicate(pair<SomeClass*, SomeClass*>& lhs, pair<SomeClass*, SomeClass*>& rhs);

我对 Your 类以及它是否有任何自然顺序一无所知,因此很难猜测您想如何对其进行排序。在评论中您写道,最大的项目应该是第一位的。我假设该类有

bool sortPredicate(pair<SomeClass*, SomeClass*>& lhs, pair<SomeClass*, SomeClass*>& rhs)
{
    if(!(*(lhs.first) < *(rhs.first) || *(rhs.first) < *(lhs.first))) // If there is == operator use it.
    {
        return *(rhs.second) < *(lhs.second);
    }
    else
    {
        return *(rhs.first) < *(lhs.first);
    }

}

编辑:好的谢谢澄清。这个怎么样?

bool sortPredicate(pair<SomeClass*, SomeClass*>& lhs, pair<SomeClass*, SomeClass*>& rhs)
{
    if(lhs.first == rhs.first)
    {
        return rhs.second < lhs.second;
    }
    else
    {
        return rhs.first < lhs.first;
    }
}

【讨论】:

    【解决方案4】:

    你应该在你的pair类上定义一个operator&lt;。我假设您的配对持有item1item2。所以:

    template <class T>
    class pair{
    private:
      T item1;
      T item2
    public:
      // [...] other stuff goes here
      // here the comparing
      bool operator<(pair p){
        return (item1 < p.item1 || (item1 == p.item1 && item2 < p.item2));
      }
    };
    

    此解决方案假定项目已定义 &lt;== 运算符。

    我想我没有满足您的确切要求,但我建议在您的 pair 类中重载 &lt;&gt;== 运算符。

    【讨论】:

    • 你知道 STL 中有std::pair 对吗?而且STL的对operator&lt;和你定义的一样。
    • @KennyTM:实际上,std::pairoperator&lt; 略有不同,它避免使用==
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-09-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多