2018-910-六

题目

众数指在一组数据中出现次数最多的数,例如若数据集合是{1,2,9,5,9,6,9},则其众数是9;若数据集合是{1,8,9,5,9,8,6,8,9},由于8和9都出现了3次,则其众数是8和9。请设计一个有效的算法,在10万个顺序存储的数据元素集合(无序存储)中找出众数,并分析所设计算法的时间复杂度。

代码来源

算法思路参考了博客
https://blog.csdn.net/liujian20150808/article/details/50637554
在此感谢作者

广告

若有同学需要桂林电子科技大学数据结构考研真题和答案解析(个人制作)或指定参考书《算法与数据结构》第三版张乃孝PDF等资料的欢迎交流(QQ((肆+壹)幺幺)&微信(月球不太圆)15577498906)

算法思路

通过快速排序对数据集合进行排序,然后遍历数据集合,将数据集合中的每个数据的个数记录下来。然后通过记录的数据找到数据中出现次数最多的数。将出现次数最多的数存入链表中,返回。
答案:算法的时间复杂度为O(nlog2n)。
通过快速排序对数据集合进行排序,快速排序的时间复杂度为O(nlog2n)。然后遍历数据集合,将数据集合中的每个数据的个数记录下来,数据只被遍历一次,时间复杂度为O(n)。然后通过记录的数据找到数据中出现次数最多的数,数据只被遍历一次,时间复杂度为O(n)。最后将出现次数最多的数存入链表中,返回,数据只被遍历一次,时间复杂度为O(n)。总体的时间复杂度为O(nlog2n)+O(3n)。

代码

#include <iostream>
#include <bits/stdc++.h>
using namespace std; 
/* run this program using the console pauser or add your own getch, system("pause") or input loop */
//找众数
#define MAXNUM 1000000
typedef int DataType;
struct SeqList{
   int MAX_NUM=MAXNUM;
   int n;      //n是当前取105
   DataType *element;
};
struct node
{
    int value;
    int length;
    struct node * next;
};
struct List
{
	DataType element;
    struct List * next;
};
int Partition(int a[], int low, int high)
{
    int key = a[low];
    while(low<high)
    {
        while(low<high && a[high] >= key) --high;
        a[low] = a[high];
        while(low<high && a[low] <= key) ++low;
        a[high] = a[low];
    }
    a[low] = key;
    for(int i=0;i<8;i++)
       	cout<<a[i]<<" ";
    cout<<endl;
    return low;
}
void Qsort(int a[], int low, int high)
{
	int i;
    if(low < high)
    {
        int loc = Partition(a, low, high);
        Qsort(a, low, loc-1);
        Qsort(a, loc+1, high);
        
    }
}

struct List * findMode(SeqList *sList)
{
	/*
	通过快速排序将数组进行排序,
	这是为了减少重复遍历的次数,我们可以先将数组升序排序,
	然后只需遍历一遍数组,就可以记录每个数字出现的次数 
	*/
	Qsort(sList->element,0,sList->n-1); 
	int i,flag,temp=0;
	/*
	建立带头结点链表nodelist,储存数据集合中的每个数据的个数
	*/
	struct node * nodelist;
	struct node * s;
	//建立头结点 
	nodelist=(struct node *)malloc(sizeof(struct node));
	nodelist->next=NULL;
	/*
	记录每个数据的个数,具体方法是通过不断变化记录的标志flag而更新结构体数组的值
	*/
	flag=sList->element[0];
	for(i=0;i<sList->n;i++)
	{
		/*
		当flag不等于sList->element[i]时,说明数据发生了变化。这时可以记录下sList->element[i-1]的个数 
		*/
		if(sList->element[i]!=flag)
        {
        	flag = sList->element[i];
        	s=(struct node *)malloc(sizeof(struct node));
        	s->value=sList->element[i-1];
			s->length=i-temp;
			s->next=nodelist->next;
			nodelist->next=s;
            temp = i;
            flag=sList->element[i];
        }
        
	}
	/*
	这里需要注意的一个问题是,由于遍历到最后一个数无法再进行if判断便跳出循环,
	所以我们无法记录最后一个数字或者说是最后出现的数字的次数,所以在循环体外还要记录一下最后出现的数字的次数。
	*/
	s=(struct node *)malloc(sizeof(struct node));
    s->value=sList->element[i-1];
	s->length=i-temp;
	s->next=nodelist->next;
	/*
	通过记录的数据找到数据中s->length的最大值,即出现次数最高的数出现了多少次 
	*/ 
	nodelist->next=s;
	int max=0;	
	while(s!=NULL)
	{
		if(s->length>max)
		{
			max=s->length;			
		}
		s=s->next;
	}
	s=nodelist->next;
	/*
	找到出现次数最多的数,并用带头结点的链表modelist储存,最后将找到的结果返回 
	*/
	struct List * modelist;
	struct List * mode;
	modelist=(struct List *)malloc(sizeof(struct List));
	modelist->next=NULL;
	while(s!=NULL)
	{
		if(s->length==max)
		{
			mode=(struct List *)malloc(sizeof(struct List));
			mode->element=s->value;
			mode->next=modelist->next;
			modelist->next=mode;
		}
		s=s->next;
	}
	return modelist->next;
}
int main(int argc, char** argv) {
	struct SeqList * sList;
	sList=(struct SeqList *)malloc(sizeof(struct SeqList));
	sList->n=9;
	sList->element=(DataType *)malloc(sizeof(int)*sList->n);
	int a[9]={1,8,9,5,9,8,6,8,9};
	for(int i=0;i<sList->n;i++)
	{
		sList->element[i]=a[i];
	}
	struct List * modelist=findMode(sList);
	while(modelist!=NULL)
	{
		cout<<modelist->element<<" ";
		modelist=modelist->next;
	}
	return 0;
}

运行结果

除了最后一行其他的都是快排的中间过程,最后一行是输出的是数组中的众数。
在这里插入图片描述

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值