★问题描述:
给定含有 n 个元素的多重集合 S,每个元素在 S 中出现的次数称为该元素的重数。多重集 S 中重数最大的元素称为众数。
例如,S={1,2,2,2,3,5}。多重集 S 的众数是 2,其重数为 3。
★编程任务:
对于给定的由 n 个自然数组成的多重集 S,编程计算 S 的众数及其重数。
★算法思想:
① 当接收到 n 个数据,首先将其存入一个数组;
② 然后将这些数据进行从小到大的排序;
③ 要知道用户输入的数据即使排列好之后,相邻的数据也可能不是按照差值为 1 来递增的(可能为 2,4,4,7……)
所以当出现相邻数据相等时,该如何来记录相同数据的个数呢。
因此在这里要用地址的差值来计算,数据不会像 1,2,3…… 这样来排序,但地址是这样子
所以只要设置两个指针来依次指向相邻数据的两个地址,当出现相同数据时,让前一个指针指向第一个重复的数据,
将后一个指针指向最后一个重复数据的之后一个数据(参考:2~7 有几个数? 答:7-2+1)
接着用后一个指针的地址,来减去第一个指针的地址,差值即为该重复数据的个数;
④ 用上一个步骤循环完所有数据后,将每一个重复数据的差值大小进行比较并保存,最后选择出最大的即可。
(注:令数组中最后一个有意义的数据为最大数 0*ffff,方便作为参考数,用以停止循环)
★C++ 代码如下(Visual Studio 2017 实现):
#include "stdafx.h"
#include <stdio.h>
#include <stdlib.h>
#include <algorithm>
#define Max 10
#define Inf 0xffff
using namespace std;
int record[Max];
int n;
int mode, num_quantity;
int main() {
printf("Please input the total number you like:\n");
scanf("%d", &n);
printf("Please input the numbers:\n");
for (int i = 0;i < n;i ++)
scanf("%d", &record[i]);
sort(record, record + n);
record[n] = Inf;
int *source = record, *target = record + 1;
num_quantity = 0;
while (*source != Inf) {
while (*target == *source && *target != Inf)
target ++;
int temp = target - source;
if (temp > num_quantity) {
num_quantity = temp;
mode = *source;
}
source = target;
target++;
}
printf("The mode is: %d\n", mode);
printf("And its count is: %d\n", num_quantity);
system("pause");
return 0;
}
