按字母顺序排列字符数组然后按长度排序

时间:2018-05-23 18:52:28

标签: c++ arrays sorting data-structures char

我有一系列结构,我会跟踪给定文本中每个唯一单词的次数:

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

此代码非常适合按字母顺序排序,但我无法编写正确的代码来按字母顺序和长度分类。

4 个答案:

答案 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_tuplestd::forward_as_tuple的结果会更好)

std::tupleoperators

  

按字典顺序比较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); });

Live Example

答案 3 :(得分:1)

其他人指出,有更快,更清洁的方式进行排序。但是,如果您想要使用自己的选择排序,那么您只需要对代码进行一些更改。

将交换逻辑本身的“我需要交换”逻辑分开。然后代码变得更清晰,并且更清楚在哪里添加额外的检查。

我这里只复制了内循环。你想用这个替换现有的内循环。我不清楚你为什么需要swap_posmin_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;
        }
    }

为了更清楚地说明必要的逻辑变化,我故意避免进行主要的样式更改或简单的优化。