众数问题

来源:互联网 发布:振动检测软件 编辑:程序博客网 时间:2024/04/19 13:00

众数问题(盆友,这个程序的算法是错误的,你看出来了吗?)

  给定含有n个元素的多重集合S,每个元素在S中出现的次数称为该元素的重数。多重集S中重数最大的元素称为众数。例如,S={122235}  多重集S的众数是2,其重数为3  
 
对于给定的由n个自然数组成的多重集S,编程计算S的众数及其重数。

方法一:采用分治算法的思想

先由找一个基准元素X,把整数数组基于X进行划分

统计X出现的次数T

如果X左边数的个数 > T,向左递归

如果X右边数的个数 > T,向右递归

#include <stdio.h>#include <stdlib.h>#include <math.h>int Random(int p, int r){//返回 p 到 r 之间的随机整数return rand()%(r-p)+p;}void swap(int *a, int *b){//交换两个数的值*a = *a + *b;*b = *a - *b;*a = *a - *b;}//对数组按基准元素进行划分int Partition(int *nums, int p, int r){    int i = p, k = r+1;    int temp = nums[p];    while(1){        while(nums[++i] < temp);//从左向右扫描,寻找比基准元大的元素        while(nums[--k] > temp);//从右向左扫描,寻找比基准元小的元素        if(i >= k){break;}        swap(&nums[i], &nums[k]);    }    nums[p] = nums[k];    nums[k] = temp;    return k;//返回基准最终位置的下标}int RandomizedPartition(int *nums, int p, int r){    int i = Random(p,r);//随机选取数组中的一个元素为划分基准    swap(&nums[i], &nums[p]);    return Partition(nums, p, r);//对数组按基准元素进行划分}//计算指定元素连续出现的区域(即开始出现的下标和结束位置的下标)void countmodes(int *nums, int index, int *l_index, int *r_index){    int mode = nums[index];int left = index;int right = index;while(nums[--left] == mode);while(nums[++right] == mode);*l_index = left + 1;*r_index = right;}void findmode(int *nums, int p, int r, int *mode, int *count){    int pindex = RandomizedPartition(nums, p, r);//将数组按基准元素划分成两段,并得到基准元最终的位置下标int l_index, r_index;int mode_nums, l_nums, r_nums;//计算指定元素连续出现的区域(即开始出现的下标和结束位置的下标)    countmodes(nums, pindex, &l_index, &r_index);mode_nums = r_index - l_index + 1;//当前元素连续出现的次数l_nums = l_index - p;//左边还没算到的元素个数r_nums = r - r_index;//右边还没算到的元素个数if(mode_nums >= *count){*mode = nums[pindex];*count = mode_nums;}    if(l_nums > mode_nums) findmode(nums, p, l_index-1, mode, count);    if(r_nums > mode_nums) findmode(nums, r_index+1, r, mode, count);return;}int main(){int n, i, mode, count=0, nums[100];scanf("%d",&n);//数组元素的个数,要小于100for(i=0; i<n; i++)//接收输入的数组元素的值{  scanf("%d",&nums[i]);}    findmode(nums, 0, n-1, &mode, &count);printf("The mode is: %d\n", mode);printf("The numbers of mode is: %d\n", count);return 0;}

  这个算法的问题出在这:

  if(l_nums > mode_nums) findmode(nums, p, l_index-1, mode, count);  if(r_nums > mode_nums) findmode(nums, r_index+1, r, mode, count);
  如果当前计算出某数 X 的个数 mode_nums 大于l_nums,那么算法就不会对左侧的元素再进行处理,而此时左侧的 l_nums 个元素可能还包含有元素 X,这样会导致算法不能正确算出整个数组中 X 的个数。解决此问题的方法:先对数组排序好序,再用分治法计算众数。


 

原创粉丝点击