在结构中按频率对数组中的字母进行排序

Sorting letters in an array by frequency in within a struct

我正在尝试按字符串中的频率对字母进行排序。如果两个或多个字母出现频率相同,则出现频率相同的字母按字母顺序排序。

这是我到目前为止设法得到的

void get_text_statistics(const char *text, size_t len, statistics_t *data)
{
    *data = (statistics_t)
        {
            .sentences          = count_sentences(text, len),
            .words              = count_words(text, len),
            .most_freq_chars    = {/*something needs to be here*/}
        }

        get_letter_frequencies(text, len, &data -> freq[0], &data -> max_freq)
}

如您所见,我的问题是尝试按频率对字符串中的字母进行排序。我尝试查找一些教程,但找不到与此特定示例类似的内容。这是相关的结构。

typedef struct statistics
{
    char_counts_t char_info;
    int sentences;
    int words;
    int freq[26];
    int max_freq;
    char most_freq_chars[27];
} statistics_t;

早些时候,我设法实现了这个功能,这可能会有所帮助。

void get_letter_frequencies(const char *text, size_t len, int freq[26], int *max_freq)
{

    for (int i = 0; i < 26; i++)
        freq[i] = 0;

    for (int i = 0; i < len; i++) {
        if ((text[i] >= 97) && (text[i] <= 122))
            freq[text[i] - 97]++;

    *max_freq = 0;
    for (int i = 0; i < 26; i++)
        if (*max_freq < freq[i])
            *max_freq = freq[i];
}

我该怎么做? TIA

p.s:count_sentencescount_words是计算字符串中的句子和单词的函数。

我想到的一个解决方案是创建一个包含字符和频率的结构,并使用 qsort 和自定义比较函数进行排序。这样频率限制就是INT_MAX.

一种更 hacky 的方法是对整数数组进行排序,对于每个毒药使用 freq*128 + ('a' + i),使用 greater 进行正常的整数数组排序,然后使用 [=14= 获取字符]

希望对你有帮助=]

#include <stdio.h>      /* printf */
#include <stdlib.h>     /* qsort */
#include <string.h>     /* strlen */

typedef struct freq_pair {
  char c;
  int freq;
} freq_pair_t;

typedef struct statistics {
  char_counts_t char_info;
  int sentences;
  int words;
  int freq[26];
  int max_freq;
  char most_freq_chars[26]; // You don't need 27 spaces here
} statistics_t;

void get_letter_frequencies(const char* text, size_t len, int freq[26], int* max_freq) {
  for (int i = 0; i < 26; i++) {
    freq[i] = 0;
  }

  for (int i = 0; i < len; i++) {
    if ((text[i] >= 'a') && (text[i] <= 'z')) {
      freq[text[i] - 'a']++;
    }
  }

  *max_freq = 0;
  for (int i = 0; i < 26; i++) {
    if (*max_freq < freq[i]) {
      *max_freq = freq[i];
    }
  }
}

int compare(const void* a, const void* b) {
  freq_pair_t* pa = (freq_pair_t*)a;
  freq_pair_t* pb = (freq_pair_t*)b;

  if (pa->freq > pb->freq) {
    return -1;
  }

  if (pa->freq == pb->freq) {
    if (pa->c < pb->c) {
      return -1;
    }
    if (pa->c > pb->c) {
      return 1;
    }

    return 0;
  }

  if (pa->freq < pb->freq) {
    return 1;
  }
}

void get_text_statistics(const char* text, size_t len, statistics_t* data) {
  *data = (statistics_t){
      .sentences = count_sentences(text, len),
      .words = count_words(text, len),
      /* Do not init most_freq_chars here, let it for after you calc all the frequencies */
  };

  get_letter_frequencies(text, len, &data->freq[0], &data->max_freq);
  freq_pair_t freq_pairs[26];

  for (int i = 0; i < 26; i++) {
    freq_pairs[i].freq = data->freq[i];
    freq_pairs[i].c = 'a' + i;
  }

  qsort(freq_pairs, 26, sizeof(freq_pair_t), compare);
  for (int i = 0; i < 26; i++) {
    data->most_freq_chars[i] = freq_pairs[i].c;
  }
}

int main() {
  char* s = "quero mudar o mundo, cruzar os ceus sem nada temer";
  statistics_t data;
  get_text_statistics(s, strlen(s), &data);

  for (int i = 0; i < 26; i++) {
    printf("%c ", data.most_freq_chars[i]);
  }
  printf("\n");

  for (int i = 0; i < 26; i++) {
    printf("%c-%d ", 'a' + i, data.freq[i]);
  }
  printf("\n");
}