2013-12-22 1 views
4

문자열을 사용하면 문자열의 각 문자가 포함 된 개수를 계산 한 다음 가장 높은 순서에서 가장 낮은 순서로 정렬하려고합니다. 그런 다음 비슷한 숫자의 문자가있는 경우이를 사전 순으로 정렬해야합니다. 그래서 여기C++ : 문자열의 문자를 빈도 순으로 알파벳순으로 정렬

내가 지금까지 할 수 있었던 내용은 다음과 같습니다

  • 는 의 26 글자에 해당하는 크기 (26)의 int 배열을 만들어이 등장 번 의 수를 나타내는 개별 값으로 알파벳 문장
  • 은이 배열의 내용을 int의 벡터 쌍인 v와 char로 푸시했습니다. (int는 빈도, 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 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 pair 
    std::sort(v.begin(), v.end()); 

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

감사합니다!

* UPDATE : * 만세! StackOverflow에서 멋진 사람들의 반응 덕분에 마침내 내 문제를 해결할 수있었습니다.

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

using namespace std; 

struct Letters 
{ 
    Letters() : freq(0){} 
    Letters(char letter,int freq) { 
     this->freq = freq; 
     this->letter = letter; 
    } 
    char letter; 
    int freq; 
}; 

bool Greater(const Letters& a, const Letters& b) 
{ 
    if(a.freq == b.freq) 
     return a.letter < b.letter; 

    return a.freq > b.freq; 
} 

int main() { 

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

    vector<Letters> count; 
    int letters[26]= {0}; 

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

    for (int x = 0; x < 26; x++) { 
     if (letters[x] > 0) { 
      char c = x + 'a'; 
      count.push_back(Letters(c, letters[x])); 
     } 
    } 

    cout<<"\nUnsorted list..\n"; 
    for (int x = 0 ; x < count.size(); x++) { 
     cout<<count[x].letter<< " = "<< count[x].freq<<"\n"; 
    } 

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

    cout<<"\nSorted list according to frequency then alphabetically..\n"; 
    for (int x = 0 ; x < count.size(); x++) { 
     cout<<count[x].letter<< " = "<< count[x].freq<<"\n"; 
    } 

    system("pause"); 
    return 0; 
} 

및 샘플 출력 : 나는 기본적으로 그냥 @Oli를 따라

Enter a string: hello world 

Unsorted list.. 
d = 1 
e = 1 
h = 1 
l = 3 
o = 2 
r = 1 
w = 1 

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

다음의 경우 사람이 내 마지막 코드는 같은 배에 갇혀 수 있습니다 사람들의 미래를 참조하거나 관심입니다 이 가이드의 도움을 받아 맞춤형 비교기를 구현하는 Charlesworth의 조언은 A Function Pointer as Comparison Function입니다.

비록 내 코드가 더 효율적으로 만들 수 있다고 확신 하나? 아직도, 나는 결과에 꽤 만족한다. :)

다시 한번 감사드립니다!

+3

사용자 정의 * 비교기 *를 사용하여 정렬을 실행하여이 단계를 해결할 수 있습니다 (예제는 http://en.cppreference.com/w/cpp/algorithm/sort 참조). –

+0

당신은 @lli Charlesworth의지도

+0

도 사용할 수 있습니다. 힌트를 보내 주셔서 감사합니다. 정말 도움이되었습니다! – makki

답변

3

가장 높은 빈도와 가장 낮은 문자를 원하면 쉬운 방법은 빈도 값을 음수 값으로 저장 한 다음 정렬 후 음수로 만드는 것입니다. 보다 효율적인 방법은 정렬을 위해 사용되는 기능을 변경하는 것입니다,하지만 터치 까다 롭습니다 :

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()); 
5

당신은 두 단계로이 많이 단순화 수 :

  1. 먼저지도를 사용

    std::unordered_map<char,unsigned int> count; 
    
    for(char character : string) 
        count[character]++; 
    
  2. 를 사용하여 비교 기준으로 그 맵의 값 :

    문자열의 각 문자의 ocurences의 수를 계산하는
    std::sort(std::begin(string) , std::end(begin) , 
          [&](char lhs , char rhs) 
          { 
           return count[lhs] < count[rhs]; 
          } 
         ); 
    

Here은 ideone에서 실행중인 작동 예제입니다.

+1

이 예는 문자 발생에 의해 올바르게 계산되지만, 알파벳 순서로 정렬되지는 않습니다! – caps

관련 문제