分治法求数组众数

1.设计思想

        首先利用快排的partition进行划分,在分区的同时统计与pivot相等的元素的个数n(重数),如果n都大于pivot左右两边元素的个数,那它就是众数,否则选取比n大或等的分区采用同样的方法进行递归,并与原来的pivot和它的重数进行比较,选取大的,当递归结束后,众数以及它的重数就出来了。

2.c++实现
/*
    程序:求数组众数
    作者:Moyu
*/
#include<iostream>
#include<vector>

using namespace std;

/*
	函数:一次划分
	参数:A:数组  lo:下限  hi:上限  n的引用:轴值出现的次数
	返回值:轴值的位置 
*/
int Partition(vector<int> &A, int lo, int hi, int &n)
{
	n = 0;
	int pivot = A[lo];
	while(lo < hi){
		while(lo < hi && A[hi] >= pivot){
			if(A[hi] == pivot)
				++n;
			--hi;	
		}
		A[lo] = A[hi];
		while(lo < hi && A[lo] <= pivot){
			if(A[lo] == pivot)
				++n;
			++lo;
		}
		A[hi] = A[lo];
	}
	A[lo] = pivot;
	++n;
	return lo;
}
/*
	函数:求数组的众数
	参数: A:数组  lo:下限  hi:上限  v:数组众数集合  n的引用:众数出现的次数
*/ 
void GetMode(vector<int> &A, int lo, int hi, vector<int> &v, int &n)
{
	//一次划分,并求轴值出现的次数 
	int num = 0;
	int m = Partition(A,lo,hi,num);
	//对左半部分求数组众数 
	vector<int> vl;
	int numl = 0;
	if(num <= m - lo)
		GetMode(A,lo,m-1,vl,numl);
	//对右半部分求数组众数 
	vector<int> vr;
	int numr = 0;
	if(num <= hi - m)
		GetMode(A,m+1,hi,vr,numr);
	//整合	
	if(num >= numl && num >= numr){
		n = num;
		if(num == numl)
			v.insert(v.end(),vl.begin(),vl.end());
		if(num == numr)
			v.insert(v.end(),vr.begin(),vr.end());
		v.push_back(A[m]);
	}
	else if(numl >= num && numl >= numr){
		n = numl;
		if(numl == num)
			v.push_back(A[m]);
		if(numl == numr)
			v.insert(v.end(),vr.begin(),vr.end());
		v.insert(v.end(),vl.begin(),vl.end());
	}
	else if(numr >= num && numr >= numl){
		n = numr;
		if(numr == numl)
			v.insert(v.end(),vl.begin(),vl.end());
		if(numr == num)
			v.push_back(A[m]);
		v.insert(v.end(),vr.begin(),vr.end());
	}
}
int main()
{
	vector<int> A = {1, 4, 2, 9, 8, 11, 16, 6, 7, 7};
	cout << "数组:";
	for(auto i : A)
		cout << i << " ";
	cout << endl; 
	vector<int> v;
	int n;
	GetMode(A,0,A.size()-1,v,n);
	if(v.size() == A.size())//若所有值皆为众数,则无众数 
		cout << "不存在众数!!!" << endl;
	else{
		cout << "众数:";
		for(auto i : v)
			cout << i<< " ";
		cout << endl;
		cout << "重复次数:"; 
		cout << n << endl;
	}
	return 0;
}
3.结果与总结

运行截图


箴言录:

        合抱之木,生于毫末;九层之台,起于垒土;千里之行,始于足下。

猜你喜欢

转载自blog.csdn.net/u014296991/article/details/80846399