西电算法设计大作业
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
算法设计大作业寻找多数元素
班级:021151
学号:02115037
姓名:隋伟哲
(1)问题提出:
令A[1,2,…n]是一个整数序列,A中的整数a如果在A中出现的次数多余⎣n/2⎦,那么a称为多数元素。例如在序列1,3,2,3,3,4,3中,3是多数元素,
因为在7个元素中它出现了四次。有几个方法可以解决这个问题。蛮力方法是把每个元素和其他各个元素比较,并且对每个元素计数,如果某个元素的计数大于
⎣n/2⎦,就可以断定它是多数元素,否则在序列中就没有多数元素。但这样比较
的次数是n(n-1)/2=Θ(错误!未找到引用源。),这种方法的代价太昂贵了。比较有效的算法是对这些元素进行排序,并且计算每个元素在序列中出现了
多少次。这在最坏情况下的代价是Θ(n 错误!未找到引用源。).因为在最坏情况下,排序这一步需要Ω(n 错误!未找到引用源。)。另外一种方法是寻找中间元素,就是第⎡n/2⎤元素,因为多数元素在排序的序列中一定是中间元素。可以扫描这个序列来测试中间元素是否是多数元素。由于中间元素可以在Θ(n)时间内找到,这个方法要花费Θ(n)时间。
有一个漂亮的求解方法,它比较的次数要少得多,我们用归纳法导出这个算法,这个算法的实质是基于下面的观察结论。
观察结论:在原序列中去除两个不同的元素后,原序列的多数元素在新序列中还是多数元素。
这个结论支持下述寻找多数元素候选者的过程。将计数器置1,并令c=A[1]。从A[2]开始逐个扫描元素,如果被扫描的元素和c相等。则计数器加1,否则计数器减1.如果所有的元素都扫描完并且计数器的值大于0,那么返回c作为多数元素的候选者。如果在c和A[j](1 A[j+1,…n]上的过程调用candidate过程。算法的伪代码描述如下。(2)算法 Input: An array A[1…n] of n elements; Output: The majority element if it exists; otherwise none; 1. c←candidate(1); 2. count←0; 3. for j←1 to n 4. if A[j]=c then count←count+1; 5. end for; 6. if count>⎣n/2⎦ then return c; 7. else return none; candidate(m) 1. j←m; c←A[m]; count←1; 2. while j 3. j←j+1; 4. if A[j]=c then count←count+1; 5. else count←count-1; 6. end while; 7. if j=n then return c; 8. else return candidate(j+1); (3)代码 //Majority.cpp #include using namespace std; int Candidate(int *A, int n, int m); int Majority(int *A, int n); int main() { int n; cout << "please input the number of the array: "; cin >> n; int *A; A = (int *) malloc(n*sizeof(int) ); cout << "please input the array: "; for (int i = 0; i < n; i++) cin >> A[i]; if (Majority(A, n) != 'N') cout << "the majority is: " << Majority(A, n); else cout << "the majority element do not exist! "; free(A); cin.get(); cin.get(); return 0; } int Majority(int *A, int n) { int c = Candidate(A, n, 0), count = 0; for (int j = 0; j < n; j++) if (A[j] == c) count += 1; if (count > n / 2) return c; else return'N'; } int Candidate(int *A, int n, int m) { int j = m, c = A[m], count = 1; while (j < n && count>0) { j += 1; if (A[j] == c) count += 1; else count -= 1; } if (j == n) return c; else return Candidate(A, n, j + 1); } (4)运行结果 (5)设计实例 首先输入数据的个数n=7,然后依次读入n个数(1,3,2,3,3,4,3)。 1)现在开始进入程序。由于数组元素的下标是从0开始的,所以调用c = Candidate(A, n, 0);从第0个元素开始统计。首先令c=A[0]=1,count=1,j=0然后j=j+1=1,A[1]=3,且3!=c,count=count-1=0,判断if条件后,返还Candidate(A, n, j + 1)。 2)进入第二次递归调用, c = Candidate(A, n, 2), c=A[2]=2,count=1,j=2然后j=j+1=3,A[3]=3,且3!=c,count=count-1=0, 判断if条件后,返还Candidate(A, n, j + 1)。 3)进入第三次递归调用,c= Candidate(A, n, 4), c=A[4]=3,count=1,j=4然后j=j+1=5,A[5]=4,且4!=c, count=count-1=0, 判断if条件后,返还Candidate(A, n, j + 1)。 4)进入第四次递归调 c=Candidate(A, n, 6),c=A[6]=3,count=1,j=6,经过运算,判定if