实现运算符<! - ? - >的最佳方法是什么

时间:2011-08-29 03:25:37

标签: c++

很抱歉,如果这是一个愚蠢的问题,但这是我很好奇的事情。

我根据姓氏,名字,中间名重载了我的排序算法的less-than运算符。我意识到这里没有对错,但我很好奇哪种风格在其他程序员中更好或更受欢迎。

bool CPerson::operator<(const CPerson& key) const
{
    if (m_Last < key.m_Last)
        || ( (m_Last == key.m_Last) && (m_First < key.m_First) )
        || ( (m_Last == key.m_Last) && (m_First == key.m_First) && (m_Middle < key.m_Middle) )
        return true;
    return false;
}

bool CPerson::operator<(const CPerson& key) const
{
    if (m_Last < key.m_Last)
        return true;
    else if ( (m_Last == key.m_Last) && (m_First < key.m_First) )
        return true;
    else if ( (m_Last == key.m_Last) && (m_First == key.m_First) && (m_Middle < key.m_Middle) )
        return true;
    else
        return false;
}

bool CPerson::operator<(const CPerson& key) const
{
    if (m_Last < key.m_Last)
        return true;

    if (m_Last == key.m_Last)
        if (m_First < key.m_First)
            return true;

    if (m_Last == key.m_Last)
        if (m_First == key.m_First)
            if (m_Middle < key.m_Middle)
                return true;

    return false;
}

6 个答案:

答案 0 :(得分:4)

我更喜欢:

bool CPerson::operator<(const CPerson& key) const
{
    if (m_Last == key.m_Last) {
        if (m_First == key.m_First) {
            return m_Middle < key.m_Middle;
        }
        return m_First < key.m_First;
    }
    return m_Last < key.mLast;
}

很好而且系统化,很明显如何添加新成员。


因为这些是字符串,所以重复比较可能是不必要的低效率。根据David Hamman的建议,这里的版本只对每个字符串进行一次比较(最多):

bool CPerson::operator<(const CPerson& key) const
{
    int last(m_Last.compare(key.m_Last));
    if (last == 0) {
        int first(m_First.compare(key.m_First));
        if (first == 0) {
            return m_Middle < key.m_Middle;
        }
        return first < 0;
    }
    return last < 0;
}

答案 1 :(得分:2)

您的所有实现都基本相同,并且对于人名的排序顺序的任何合理定义都是错误的。你的算法将Jonathan Abbott Zyzzyk置于Jonathan Zuriel Aaron之前。

如果出现以下情况,您想要的是A人的姓名少于B人的姓名:

  • 人A的姓氏小于B人或
  • 的姓氏
  • 这两个姓氏相同
    • 人A的名字小于人B的第一个名字或
    • 两个人的名字相同,人A的中间名小于人B的中间名。

是否将此实现为单个布尔表达式而不是分阶段的if / else序列是个人偏好。我的偏好是单个布尔表达式;对我来说,逻辑表达式比杂乱的if / else序列更清晰。但显然我很奇怪。大多数人更喜欢if / else结构。

根据请求进行修改
作为单个布尔表达式,

bool Person::operator< (const Person& other) const {
  return (last_name < other.last_name) ||
         ((last_name == other.last_name) &&
          ((first_name < other.first_name) ||
           ((first_name == other.first_name) &&
            (middle_name < other.middle_name))));
}

答案 2 :(得分:0)

我找到了第一个最难读的三个(尽管它们都不太难),第一个有不必要的括号。第二个是我个人的偏好,因为第三个似乎太长而且冗长。

这确实是主观的。

答案 3 :(得分:0)

我通常会像这样写一个比较函数:

bool whatever::operator<(whatever const &other) { 

    if (key1 < other.key1)
        return true;

    if (other.key1 < key1)
        return false;

    // compare the second key item because the first ones were equal.
    if (key2 < other.key2) 
        return true;

    if (other.key2 < key2)
       return false;

    // repeat for as many keys as needed

    // for the last key item, we can skip the second comparison:
    if (keyN < other.keyN)
        return true;

    return false; // other.keyN >= keyN.
}

答案 4 :(得分:0)

沿着略微不同的方式,所有的解决方案(包括我的第一个答案)倾向于两次比较名称,一次是少于和另一次是平等。由于sort最多只是一个N * logN算法,因此在对大型名称列表进行排序时效率非常重要,而这些重复比较效率相当低。 string::compare方法提供了绕过此问题的机制:

bool Person::operator< (const Person& other) const {
  int cmp = last_name.compare (other.last_name);
  if (cmp < 0) {
     return true;
  } else if (cmp == 0) {
    cmp = first_name.compare (other.first_name);
    if (cmp < 0) {
      return true;
    } else if (cmp == 0) {
      cmp = middle_name.compare (other.middle_name);
      if (cmp < 0) {
        return true;
      }
    }
  }
  return false;
}

根据请求进行修改
省略。

上述布尔版本将导致未定义的行为或将使用三元运算符的多个嵌入式用法。考虑到我对毛茸茸的布尔表达式的偏爱,这很难看。对不起,Mankarse。

答案 5 :(得分:0)

我喜欢将其减少为已经实现了这种词典排序的元组。例如,如果你有提升,你可以写:

bool Person::operator< (const Person& Rhs) const
{
  return boost::tie(m_Last, m_First, m_Middle) < boost::tie(Rhs.m_Last, Rhs.m_First, Rhs.m_Middle);
}