题目
众数指在一组数据中出现次数最多的数,例如若数据集合是{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;
}
运行结果
除了最后一行其他的都是快排的中间过程,最后一行是输出的是数组中的众数。