我有一系列结构,我会跟踪给定文本中每个唯一单词的次数:
struct List {
char word[20];
int repeat;
};
现在我需要对此进行排序:
as 6
a 1
appetite 1
angry 1
are 2
and 4
...
对此:
a 1
as 6
and 4
are 2
angry 1
appetite 1
...
(按字母顺序,我的意思是只用第一个字母) 到目前为止,我已经想出了这个:
for (i = 0; i < length - 1; i++) {
min_pos = i;
for (j = i + 1; j < length; j++) // find min
if (array[j].word[0] < array[min_pos].word[0]) {
min_pos = j;
}
swap = array[min_pos]; // swap
array[min_pos] = array[i];
array[i] = swap;
}
此代码非常适合按字母顺序排序,但我无法编写正确的代码来按字母顺序和长度分类。
答案 0 :(得分:6)
制作比较器功能。
将operator<
添加到List
:
bool operator<(const List &lhs) const {
if(word[0] != lhs.word[0]) {
return word[0] < lhs.word[0];
}
return strlen(word) < strlen(lhs.word);
}
现在使用此运算符进行排序,使用您喜欢的任何算法。
答案 1 :(得分:1)
使用元组词典比较运算符
不写这种情况的简单方法是
#include <tuple>
然后可以使用std::tie
:
std::tie(array[j].word[0], array[j].repeat) < std::tie(array[min_pos].word[0], array[min_pos].repeat)
这是有效的,因为std::tie
创建了一个对其参数进行左值引用的元组。 (这意味着std::tie
需要变量。如果您想比较函数std::make_tuple
或std::forward_as_tuple
的结果会更好)
std::tuple
有operators
按字典顺序比较lhs和rhs,即比较第一个元素,如果它们是等价的,则比较第二个元素,如果它们是等价的,则比较第三个元素,依此类推。
以上描述也是如何比较超值的想法。
答案 2 :(得分:1)
您可以将lambda传递给sort
来执行此操作:
sort(begin(array), end(array), [](const auto& lhs, const auto& rhs){ return *lhs.word < *rhs.word || *lhs.word == *rhs.word && (strlen(lhs.word) < strlen(rhs.word) || strlen(lhs.word) == strlen(rhs.word) && strcmp(lhs.word, rhs.word) < 0); });
答案 3 :(得分:1)
其他人指出,有更快,更清洁的方式进行排序。但是,如果您想要使用自己的选择排序,那么您只需要对代码进行一些更改。
将交换逻辑本身的“我需要交换”逻辑分开。然后代码变得更清晰,并且更清楚在哪里添加额外的检查。
我这里只复制了内循环。你想用这个替换现有的内循环。我不清楚你为什么需要swap_pos
和min_pos
,所以我只留下了语义。
for (j = i + 1; j < length; j++) { // find min
// first, determine whether you need to swap
// You want to swap if the first character of the new word is
// smaller, or if the letters are equal and the length is smaller.
bool doSwap = false;
if (array[j].word[0] < array[min_pos].word[0]) {
doSwap = true;
}
else if (array[j].word[0] == array[min_pos].word[0] &&
strlen(array[j].word) < array[min_pos].word) {
doSwap = true;
}
// do the swap if necessary
if (doSwap) {
swap_pos = j;
swap = array[min_pos]; // swap
array[min_pos] = array[i];
array[i] = swap;
}
}
为了更清楚地说明必要的逻辑变化,我故意避免进行主要的样式更改或简单的优化。