一 概述
在顺序表L=(a1,a2,...,an-1)中,若存在ap1=ap2=...=apm=x,且m > n/2(0<=pk<n,1<=k<=m),则称x为A的主元素。其中p为主元素在顺序表中出现的位置,而m为主元素在顺序表中出现的次数。
如L = (0,4,4,3,4,7,4,4),则主元素为4;而L = (0,4,4,3,4,1,5,7)中不存在主元素。
二 算法思想
算法的策略是从前向后扫描数组元素,标记出一个可能成为主元素的元素Main。然后进行计数,确认Main是否为主元素。
算法的设计步骤:
- 选取候选的主元素,依次扫描所给数组中的每个整数,将第一个遇到的整数保存到Temp中,记录Main出现的次数为1;若下一个整数仍等于Main,则计数count加1,否则计数count减1;当计数减至0是,将下一个整数保存到Temp中,并重新计数count为1,开始新一轮的计数,即从当前位置开始重复上述过程,直到扫描完全部的表元素。
- 再次扫描顺序表,统计temp中元素出现的次数sum,若sum大于n/2,则temp中的元素为主元素;否则,序列中不存在主元素。
三 算法实现
#include<iostream>//输入头
using namespace std;//标准输入输出
typedef int Status;
typedef int ElemType;
#define MAXSIZE 100
#define ERROR -1
#define OK 0
typedef struct {
ElemType *elem;
int length;
}SqList;
Status init_Queue(SqList &L){
L.elem = new ElemType[MAXSIZE]; //初始化最大长度的顺序表
if(!L.elem){
return ERROR; //初始化失败
}
L.length = 0; //初始时数据表为空
return OK;
}
int mainNum(SqList &L) {
ElemType temp = L.elem[0];
int count = 1,sum = 0,i;
for(i = 1; i < L.length; i++) {
if(temp == L.elem[i]) {
count++;
}else if(count > 0) {
count--;
}else{
temp = L.elem[i];
count = 1;
}
}
if (count > 0){
for(i = 0; i < L.length; i++) {
if(temp == L.elem[i]) {
sum++;
}
}
}
if(sum < L.length/2){
temp = -1;
}
return temp;
}
int main(){
SqList L;
cout<<"1.初始化顺序表!\n";
cout<<"2.输入8个不同的数字!\n";
cout<<"3.顺序表L中的主元素!\n";
cout<<"0.退出!"<<endl<<endl;
int elect = -1;
while(elect !=0){
cout<<"请选择你的后续操作:";
cin>>elect;
switch(elect){
case 1:
if(!init_Queue(L)){
cout<<"初始化顺序表成功!"<<endl;
}else{
cout<<"初始化顺序表失败!"<<endl;
}
break;
case 2:
cout<<"请输入8不同数字:" ;
for(int i = 0; i < 8; i++){
cin>>L.elem[i];
L.length = 8;
}
break;
case 3:
if(mainNum(L) == -1){
cout<<"顺序表L中不存在主元素且返回值为:"<<mainNum(L)<<endl;
}else{
cout<<"顺序表L中的主元素:"<<mainNum(L)<<endl;
}
break;
}
}
return 0;
}
顺序表中存在主元素的结果:
顺序表中不存在主元素的结果:
四 算法的时间复杂度和空间复杂度分析
时间复杂度:根据顺序查找的时间复杂度分析,该算法的时间复杂度为O(n);
空间复杂度:根据算法本地工作空间复杂度,该算法的所需的辅助空间为常量,所以该算法的空间复杂度为O(1);