【问题标题】:Switch input for sorting algorithm切换排序算法的输入
【发布时间】:2017-09-26 15:24:26
【问题描述】:

我在下面写了一个插入排序:

int i, j;
Book temp;
for (j = 1; j < books.size(); j++) { 
    temp = books[j]; 
    i = j - 1; 
    while (i >= 0) {
        if (temp.getAuthor().compare(books[i].getAuthor()) > 0) {
            break; 
        }
        books[i +1] = books[i];
        i--;
    }
    books[i + 1] = temp;

}

我希望能够以某种方式对其进行更改,以便我可以使用不同的因素运行它。

temp.getAuthor 也有 .getTitle.getYear 无论如何都可以调整此代码,因此我也可以根据用户的选择运行它们。我正在研究模板,但不确定我是否在正确的区域?

【问题讨论】:

  • 你熟悉函数指针吗?
  • 可以用c++11编译吗?

标签: c++ algorithm sorting vector insertion


【解决方案1】:

正如@Beta 提到的,function pointer 可以在这里使用:

bool cmpAuthor(const Book &a, const Book &b) {
    return a.getAuthor().compare(b.getAuthor()) > 0;
}
// And so as cmpTitle and cmpYear

int i, j;
Book temp;

// a function pointer named "funCompare"
// and should point to a function with 2 "const Book &" args
// like cmpAuthor
bool(* funCompare)(const Book &, const Book &);

// Point funCompare to the compare function you need
funCompare = cmpAuthor; // or funCompare = cmpTitle;

for (j = 1; j < books.size(); j++) {
    temp = books[j];
    i = j - 1;
    while (i >= 0) {
        // if (temp.getAuthor().compare(books[i].getAuthor()) > 0) {
        if (funCompare(temp, books[i])) {
            break;
        }
        books[i + 1] = books[i];
        i--;
    }
    books[i + 1] = temp;

}

更新:

受@llya 的启发,您还可以扩展Book(或者如果可以的话,只编辑源代码)并创建一个接受如下关键参数的比较函数:

bool compare(const Book & a, string key) {
    if (key == "author")
        return getAuthor().compare(a.getAuthor()) > 0;
    if (key == "title")
        return getTitle().compare(a.getTitle()) > 0;
    // ...
}

而用法是这样的:

if (temp.compare(books[i], "author")) {
    break;
}

【讨论】:

    【解决方案2】:

    作为@Ilya 的补充,如果您能够使用 c++11,您可以将简单的比较 lambdas 传递给std::sort

    auto sort_by_author = [] (const Book& left, const Book& right) -> bool {
        left.getAuthor().compare(right.getAuthor()) > 0;
    };
    auto sort_by_title = [] (const Book& left, const Book& right) -> bool {
        left.getTitle().compare(right.getTitle()) > 0;
    };
    auto sort_by_year = [] (const Book& left, const Book& right) -> bool {
        left.getYear() < right.getYear();
    };
    

    然后像这样使用它

    std::sort(books.begin(), books.end(), sort_by_author);
    print(books) // some abstract printing function
    
    std::sort(books.begin(), books.end(), sort_by_year);
    print(books) // some abstract printing function
    
    std::sort(books.begin(), books.end(), sort_by_title);
    print(books) // some abstract printing function
    

    【讨论】:

      【解决方案3】:

      首先,不要使用这么慢的排序算法实现(O(N^2) 很慢)。我建议这样做:

      1) 通过比较运算符扩展Book类:

      bool operator<(const Book& rhs)
      {
          return getAuthor().compare(rhs.getAuthor()) < 0;
      }
      

      2) 调用标准排序函数:

      std::sort(books.begin(), books.end());
      

      在它之后,您可以扩展operator&lt; 以考虑Book 的其他属性(不要忘记std::sort 需要严格的弱排序比较)。

      另一种方式(万一无法修改类Book):

      1) 创建函数

      bool Greater(const Book& left, const Book& right)
      {
          return left.getAuthor().compare(right.getAuthor()) > 0;
      }
      

      2) 并这样称呼它:

      std::sort(books.begin(), books.end(), Greater);
      

      在这种情况下,您将扩展函数 Greater 以支持 Book 的其他属性。

      【讨论】:

      • 虽然信息是正确的,但不是所要求的。他们想学习如何让自己的代码更可重用。不学习如何调用标准库排序。
      • @NirFriedman 感谢您指出这一点!从我的角度来看,我展示了如何使他们的代码更具可重用性(将所有比较逻辑放在一个函数中)。但我同意你的观点,std::sort 上的迁移在这里并不是绝对必要的。
      猜你喜欢
      • 1970-01-01
      • 2020-12-11
      • 1970-01-01
      • 2011-07-14
      • 2015-09-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-03-31
      相关资源
      最近更新 更多