c语言递归算法找众数,众数问题-递归和分治

博客围绕在给定数组中找出众数的问题展开。提出先排序,再用分治法计算求解的思路,并给出了分治法求解的C语言代码,包含快速排序、随机选择中位数排序等函数,通过递归调用实现众数查找。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

问题描述

给定一个数组,找出其中出现次数最多的那个元素(即众数)。

例如:

1 2 2 2 3 5

众数是: 2

算法思路:先排序  后用分治法计算求解

分治法求解代码如下:#include

#include

#include

using namespace std;

/*----------快速排序*/

int Partition(int *a , int l , int r)

{

int i = l , j = r+1;

int x = a[l];

while(true){

while(a[++i] < x && i < r);

while(a[--j] > x);

if(i >= j) break;

swap(a[i] , a[j]);

}

a[l] = a[j];

a[j] = x;

return j;

}

/*------------随机选择中位数排序*/

int RandomizedPartitiom(int *a , int l , int r)

{

srand(time(NULL));

int i = rand()%(r-l)+l;

swap(a[i] , a[l]);

return Partition(a , l , r);

}

/*----------------按中位数划分成两段*/

void split(int *a , int m , int l , int r , int *left , int *right)

{

int med = a[m];

*left = *right = m;

/*--------------------将 == 中位数的元素剔除:及 right-left+1 == 众数的个数*/

while(a[--(*left)] == med);

while(a[++(*right)] == med);

(*left)++;

(*right)--;

}

/*---------------分治法求解*/

void mode(int *a , int l , int r , int *largest , int *count)

{

int m = RandomizedPartitiom(a , l , r);//----查找中位数

int left , right;

split(a , m , l , r , &left , &right);//---按中位数分成2段

if(*largest < right-left+1){//-----保留众数个数最大值,及众数下标

*largest = right-left+1;

*count = m;

}

if(left-l > *largest) mode(a , l , left-1 , largest , count);//左边个数大于众数个数

if(r-right > *largest) mode(a , right+1 , r , largest , count);//右边个数大于众数个数

}

/*----------main()*/

int main()

{

int n;

cout<

cin>>n;

int a[n];

int largest = 0 , count = 0;

cout<

for(int i = 0 ; i < n ; i++)

cin>>a[i];

mode(&a[0] , 0 , n-1 , &largest , &count);

cout<

return 0;

}

/*

请输入集合S的元素个数n:

6

请输入元素:

1 2 2 2 3 5

众数是:2 重数是:3

Process returned 0 (0x0) execution time : 7.504 s

Press any key to continue.

*/

众数问题是数据挖掘领域的一个经典问题,它旨在出一组数值中出现次数最多的元素,也称为“模式”或“高频元素”。在C语言中,可以使用分治算法(Divide and Conquer)的思想来解决这个问题,比如使用哈希表(如数组或桶式结构)来辅助计算分治法通常包括三个步骤: 1. **分解**(Divide):将原始数组拆分成两个或更多的子数组,直到每个子数组只包含一个元素或者空数组。 2. **解决**(Conquer):对每个子数组分别众数。如果是单个元素的子数组,它的元素就是其自身的众数;对于空数组,没有众数。 3. **合并**(Combine):比较子数组众数,并选择出现最频繁的那个作为整个数组众数。如果所有子数组众数相等,则这个值就是原数组众数。 以下是简单的分治方法在C语言中求解众数的一个示例: ```c #include <stdio.h> int findMedian(int arr[], int low, int high) { if (low == high) return arr[low]; // 中间位置的索引 int mid = (low + high) / 2; // 分治:左边到左半部分的中位数,右边到右半部分的中位数 int leftMedian = (arr[mid] > arr[mid - 1]) ? mid : mid - 1; int rightMedian = (arr[mid] > arr[mid + 1]) ? mid : mid + 1; // 如果左中位数等于右中位数,则它们就是原数组的中位数 if (leftMedian != rightMedian) return (arr[leftMedian] > arr[rightMedian]) ? arr[leftMedian] : arr[rightMedian]; else // 如果有三个数相等,我们还需要遍历一次以确定众数 return findMedian(arr, low, mid - 1) || findMedian(arr, mid + 1, high); } // 主函数演示如何使用 int main() { int arr[] = {1, 2, 3, 3, 4, 4, 5}; int n = sizeof(arr) / sizeof(arr[0]); printf("The mode of the array is: %d\n", findMedian(arr, 0, n - 1)); return 0; } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值