代码之家  ›  专栏  ›  技术社区  ›  conradlee

我应该如何比较成对的指针(用于排序谓词)

  •  0
  • conradlee  · 技术社区  · 15 年前

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

    pair<SomeClass*, SomeClass*>
    

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

    /*returns items sorted biggest first */
    
    bool sortPredicate (pair<SomeClass*, SomeClass*>two,  pair<SomeClass*, SomeClass*> one)
    {
      return ???;
    }
    

    有没有一些技巧可以用来快速比较成对的指针?

    编辑1:澄清

    最后 我只想对指针对的列表进行排序,以便所有重复项都彼此相邻 . 假设在某个类中没有可用于此目的的明确方法——我只有指针对,我希望找到所有相同的对(并行)。我以为有一种方法可以达到这个目的,但是如果你能想出一种更好的并行方法,请告诉我。

    编辑2:澄清

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

    4 回复  |  直到 14 年前
        1
  •  9
  •   Steve Jessop    15 年前

    这是一个奇特的C++,相同类型的任意指针不是(必然)与lt相比较,而是可比的。 std::less .

    不幸的是, operator< 对于 std::pair 定义如下: 运算符; 在组件上,不是 STD::少 .

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

    // "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 < rhs; 但这在形式上并不正确。如果指针的引用都是同一对象的子对象(例如,如果有一个巨大的数组,并且所有对都指向该数组的元素),那么 运算符; 对于指针是可以的,因此对于 std::pair<pointer,pointer> .

    如果您希望成对放置在相同的排序位置,如果并且仅当它们指向的对象排序相同时,则添加额外的取消引用:

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

    如果允许的话,您可能还会添加对空指针的检查。当然,如果您知道某个类实际上是类类型,而不是指针类型,那么您不需要使用 STD::少 在上面的版本中,只需定义 运算符; 对于某些类和:

    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的第一次和第二次调用中都会重复执行一些空检查。如果你那么在意,看看编译器会用它做什么。

        2
  •  4
  •   rlbond    15 年前

    假设类具有比较运算符:

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

    如果只想比较指针地址,请使用 std::greater<T> :

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

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

        3
  •  0
  •   Maciej Hehl    15 年前

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

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

    我对你的班级一无所知,如果有什么自然规律的话,那么很难猜测你想如何分类。在评论中你写道最大的项目应该是第一个。我想班上应该有接线员。这个怎么样?

    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);
        }
    
    }
    

    编辑: 好的,THX用于澄清。这个怎么样?

    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
  •  0
  •   phimuemue    15 年前

    你应该定义一个 operator< 在你的双人课上。我想你们两个 item1 item2 . 所以:

    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));
      }
    };
    

    此解决方案假定项已定义 < 以及 == 运算符。

    我想我没有遇到你真正想要的,但我建议超载 < , > = 成对类中的运算符。