使用int counts[1000]; 之类的数组会将您可以跟踪的整数限制在[0, 999] 范围内(即大于或等于0,小于或等于999 )。这很好,只要您可以保证每个输入值都在此范围内(或以其他方式处理范围外的值)。
不需要嵌套循环;只需为您的当前值增加频率计数器,如果这个新计数超过它,则更新您的最大值。
当需要打印时:对于小范围,您可以完全扫描它以查找命中,
for (size_t i = 0; i < MAX_N; i++)
if (freq[i])
printf("Number %zu appears %d times\n", i, freq[i]);
或者如果性能是一个问题,您可以对数组进行排序,然后通过重置频率只打印一次每个值。同样,您必须注意有效范围之外的值。
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#define MAX_N 1000
int low_to_high(const void *p1, const void *p2) {
int a = *((int *) p1),
b = *((int *) p2);
return a == b ? 0 : a > b ? 1 : -1;
}
int main(void) {
int input[] = { 1, 2, 1, 4, 2, 4, -5, 2, 2, 3, 4, 2, 1000 };
size_t input_length = sizeof input / sizeof *input;
int freq[MAX_N] = { 0 };
int max_value, max_freq = INT_MIN;
for (size_t i = 0; i < input_length; i++) {
int value = input[i];
if (value >= MAX_N || value < 0) {
fprintf(stderr, "Stray value detected: %d\n", value);
continue;
}
if (++freq[value] > max_freq) {
max_freq = freq[value];
max_value = value;
}
}
qsort(input, input_length, sizeof *input, low_to_high);
for (size_t i = 0; i < input_length; i++) {
int value = input[i];
if (value >= MAX_N || value < 0) {
fprintf(stderr, "Stray value detected: %d\n", value);
continue;
}
if (freq[value]) {
printf("Number %d appears %d times\n", value, freq[value]);
freq[value] = 0;
}
}
printf("Most frequent: %d [%d]\n", max_value, max_freq);
}
stdout:
Number 1 appears 2 times
Number 2 appears 5 times
Number 3 appears 1 times
Number 4 appears 3 times
Most frequent: 2 [5]
stderr:
Stray value detected: -5
Stray value detected: 1000
Stray value detected: -5
Stray value detected: 1000
正如我们所见,使用 数组 会限制您可以支持的整数范围。 数组以外的数据结构可以为这个问题提供另一种解决方案。
一个建议是使用链表,这样您就可以支持带符号类型的整个范围(在本例中为[INT_MIN, INT_MAX])。
这里我们将我们的值添加到列表中,如果它没有被看到,则计数为1,否则我们增加现有的计数。
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
struct freq {
int value;
int count;
struct freq *next;
};
struct freq_list {
struct freq *head;
};
struct freq *freq_create(int value, struct freq *next) {
struct freq *node = malloc(sizeof *node);
node->value = value;
node->count = 1;
node->next = next;
return node;
}
int freq_list_increase(struct freq_list *list, int value)
{
if (!list->head || list->head->value > value)
list->head = freq_create(value, list->head);
else {
struct freq *node = list->head;
struct freq *last = NULL;
while (node && node->value < value) {
last = node;
node = node->next;
}
if (!node || node->value > value)
last->next = freq_create(value, node);
else
return ++node->count;
}
return 1;
}
int main(void) {
int array[] = { 1, 2, 1, 4, 2, 4, 2, 2, 3, 4, 2, -1, -1, -1273, 7473, 0, 0, -2000 };
size_t array_length = sizeof array / sizeof *array;
struct freq_list counts = { NULL };
int min = INT_MAX;
int max = INT_MIN;
for (size_t i = 0; i < array_length; i++) {
int val = freq_list_increase(&counts, array[i]);
if (val < min)
min = val;
if (val > max)
max = val;
}
for (struct freq *t = NULL, *n = counts.head; n; n = t) {
printf("%11d appears %11d times.", n->value, n->count);
if (n->count == min)
printf(" (MIN)");
if (n->count == max)
printf(" (MAX)");
putchar('\n');
t = n->next;
free(n);
}
}
输出:
-2000 appears 1 times. (MIN)
-1273 appears 1 times. (MIN)
-1 appears 2 times.
0 appears 2 times.
1 appears 2 times.
2 appears 5 times. (MAX)
3 appears 1 times. (MIN)
4 appears 3 times.
7473 appears 1 times. (MIN)
通过此实现,对您的输入进行预排序(从高到低)可能会带来性能优势。在任何情况下,此列表都会在构建时自行排序。在您的输入无法提前排序的情况下,这种副作用可能是可取的。