首先按频率对字符串中的字符进行排序,然后按字母顺序排序

新手上路,请多包涵

给定一个字符串,我试图计算字符串中每个字母的出现次数,然后将它们的频率从高到低排序。然后,对于出现次数相似的字母,我必须按字母顺序对它们进行排序。

到目前为止,这是我能够做到的:

  • 我创建了一个 int 大小为 26 的数组,对应于字母表中的 26 个字母,其各个值表示它在句子中出现的次数
  • I pushed the contents of this array into a vector of pairs, v , of int and char ( int for the frequency, and char 为实际字母)
  • 我使用 std::sort(v.begin(), v.end()); 对这个向量对进行了排序

在显示频率计数时,我只是使用了一个从最后一个索引开始的 for 循环来从最高到最低显示结果。但是,对于那些频率相似的字母,我遇到了问题,因为我需要它们按字母顺序显示。我尝试使用嵌套 for 循环,内循环从最低索引开始,并使用条件语句检查其频率是否与外循环相同。这似乎可行,但我的问题是我似乎无法弄清楚如何控制这些循环以避免冗余输出。要理解我在说什么,请查看此示例输出:

 Enter a string: hello world

Pushing the array into a vector pair v:
d = 1
e = 1
h = 1
l = 3
o = 2
r = 1
w = 1

Sorted first according to frequency then alphabetically:
l = 3
o = 2
d = 1
e = 1
h = 1
r = 1
w = 1
d = 1
e = 1
h = 1
r = 1
d = 1
e = 1
h = 1
d = 1
e = 1
d = 1
Press any key to continue . . .

正如你所看到的,如果不是因为不正确的 for 循环带来的冗余输出,它会很好。

如果您可以就我的问题提出更有效或更好的实现,那么我将非常感激,只要它们不是太复杂或太高级,因为我只是一个 C++ 初学者。

如果你需要查看我的代码,这里是:

 #include <iostream>
#include <string>
#include <vector>
#include <algorithm>

using namespace std;

int main() {
    cout<<"Enter a string: ";
    string input;
    getline(cin, input);

    int letters[26]= {0};

    for (int x = 0; x < input.length(); x++) {
        if (isalpha(input[x])) {
            int c = tolower(input[x] - 'a');
            letters[c]++;
        }
    }

    cout<<"\nPushing the array into a vector pair v: \n";
    vector<pair<int, char> > v;

    for (int x = 0; x < 26; x++) {
        if (letters[x] > 0) {
            char c = x + 'a';
            cout << c << " = " << letters[x] << "\n";
            v.push_back(std::make_pair(letters[x], c));
        }
    }

    // Sort the vector of pairs.
    std::sort(v.begin(), v.end());

    // I need help here!
    cout<<"\n\nSorted first according to frequency then alphabetically: \n";
    for (int x = v.size() - 1 ; x >= 0; x--) {
        for (int y = 0; y < x; y++) {
            if (v[x].first == v[y].first) {
                cout << v[y].second<< " = " << v[y].first<<endl;
            }
        }
        cout << v[x].second<< " = " << v[x].first<<endl;
    }

    system("pause");
    return 0;
}

原文由 makki 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 910
2 个回答

如果您想要最高频率然后最低字母,一种简单的方法是存储频率的负值,然后在排序后将其取反。一种更有效的方法是更改用于排序的函数,但这有点棘手:

 struct sort_helper {
   bool operator()(std::pair<int,char> lhs, std::pair<int,char> rhs) const{
     return std::make_pair(-lhs.first,lhs.second)<std::make_pair(-rhs.first,rhs.second);
   }
};
std::sort(vec.begin(),vec.end(),sort_helper());

原文由 Yakk - Adam Nevraumont 发布,翻译遵循 CC BY-SA 3.0 许可协议

您可以通过两个步骤简化很多:

  1. 首先使用一个映射来统计字符串中每个字符出现的次数:
    std::unordered_map<char, unsigned int> count;

   for( char character : string )
       count[character]++;

  1. 使用该映射的值作为比较标准:
    std::sort( std::begin( string ) , std::end( string ) ,
              [&]( char lhs , char rhs )
              {
                  return count[lhs] < count[rhs];
              }
            );

是在 ideone 运行的一个工作示例。

原文由 Manu343726 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题