首页 > 其他 > 详细

主元素算法

时间:2014-03-22 00:24:10      阅读:432      评论:0      收藏:0      [点我收藏+]

Q : 何为主元素:

T[0:n-1]n个元素的数组,对任意一个元素x,设S(x) = { i | T[i] = x }。当| S(x) | > n/2 时,称xT的主元素。

 

算法实现:

1、快排 判断中位数

2、分治思想 (分解、递归实现)

3、线性算法 (主元素个数大于n/2)

 

方法一:针对有序数组,若存在主元素,则主元素肯定是中位数。

思路:先对数组进行快速排序,然后求解有序数组的中位数,若中位数个数>n/2 (或者判断中位数与第一个、最后一个元素的关系),则中位数为主元素,否则不存在主元素。

分析:时间复杂度为Onlogn

代码实现:

#include <stdio.h>

#include <windows.h>

 

//利用快速排序的方法求中位数

void swap(int *a, int *b)

{

        int temp = 0;

        temp = *a; 

        *a = *b;

        *b = temp;

}

 

int partition(int *num, int start, int end)

{

        int x = num[end];

        int i = start-1;

        int j;

        for (j = start; j < end; j++) {

                if (num[j] <= x) {

                        i = i + 1;

                        swap(&num[i], &num[j]);

                }

        }

        swap(&num[i+1], &num[end]);

        return i+1;

}

 

void quicksort(int *num, int start, int end)

{

        if( start < end) {

                int mid = partition(num, start, end);

                quicksort(num, start, mid-1);

                quicksort(num, mid+1, end);

        }

}

 

int main()

{

        int i,n;

int num[10];

int index;

printf("please input the number of a[]:");

scanf("%d",&n);

printf("please input a[]:\n");

for(i=0;i<n;i++)

scanf("%d",&num[i]);

        quicksort(num, 0, n-1);

        for (i = 0; i < n; i++) {

                printf("%d\n", num[i]);

        }

if(n%2 == 0)

index=n/2-1;

        else 

index = n/2; //奇数n/2偶数n/2-1

//中位数与第一个或者最后一个数相同,则为主元素

        if (num[0] == num[index] || num[n-1] == num[index]) {

                printf("main element exits: index = %d element = %d\n", index, num[index]);

        }

        else {

                printf("main element not exits\n");

        }

Sleep(10000000);

}

 

方法二:分治法

思路:若中存在主元素,则将分为两部分后,的主元素也必为两部分中至少一部分的主元素,因此可用分治法。

将元素划分为两部分,递归地检查两部分有无主元素。具体算法如下:

a. 只含一个元素,则此元素就是主元素,返回此数。

b. 分为两部分T1 T2(二者元素个数相等或只差一个),分别递归调用此方法 求其主元素m1 m2

c. m1 m2 都存在且相等,则这个数就是的主元素,返回此数。

d. m1 m2 都存在且不等,则分别检查这两个数是否为的主元素,若有则返回 此数,若无则返回空值。

e. m1 m2 只有一个存在,则检查这个数是否为的主元素,若是则返回此数, 若否就返回空值。

f. m1 m2 都不存在,则 T 无主元素,返回空值。

分析:

代码实现:

#include <stdio.h>

#include <stdlib.h>

#include <malloc.h>

#include <windows.h>

 

typedef struct snode{

        int data;

        int count;

}*node;

 

int checkNum(int *num, int p, int q, int data)

{

        int count = 0;

        int i;

        for (i = p-1; i < q; i++) {

                if (num[i] == data) {

                        count++;

                }

        }

        return count;

}

 

node checkAnotherPart(int *num, int len, int p, int q, node nodec)

{

        nodec->count = checkNum(num, p, q, nodec->data) + nodec->count;  //统计左右两部分元素出现个数

        if (nodec->count > len/2) {   //如若大于n/2,则符合要求返回,否则返回空

                return nodec;

        }

        else {

                return NULL;

        }

}

 

node checkMaster(int *num, int p, int q)

{

        node nodetmp = (node)malloc(sizeof(node));

        node nodea = (node)malloc(sizeof(node)); 

        node nodeb = (node)malloc(sizeof(node));

//递归结束条件

        if (p == q) {

                nodetmp->data = num[p-1];

                nodetmp->count = 1;

                return nodetmp;

        }

        int len = q - p + 1;        //待检查数组长度(未必是从头开始:-p)

        int mid = p + len / 2;      //找数组中间位置(未必是从头开始:+p)

        nodea = checkMaster(num, p, mid-1);  //左半部分递归求解主元素

        nodeb = checkMaster(num, mid, q);    //右半部分递归求解主元素

        if (nodea == NULL && nodeb == NULL) { //两部分都不存在主元素,则返回空

                return NULL;

        }

        if (nodea == NULL && nodeb != NULL) { //左半部分存在,右半部分不存在时,检查左半部分主元素是否合格

                return checkAnotherPart(num, len, p, mid-1, nodeb);

        }

        if (nodea != NULL && nodeb == NULL) { //左半部分不存在,右半部分存在时,检查右半部分主元素是否合格

                return checkAnotherPart(num, len, mid, q, nodea);

        }

        if (nodea != NULL && nodeb != NULL) { //左右两部分都存在主元素

                if (nodea->data == nodeb->data) { //左右两部分的主元素相同,直接返回

                        nodea->count = nodea->count + nodeb->count;

                        return nodea;

                }

                else { //左右两部分的主元素不同,分别检查其是否为原数组的主元素

                        node nodec = checkAnotherPart(num, len, p, mid-1, nodeb); 

                        if (nodec != NULL) {

                                return nodec;

                        }

                        else {

                                return checkAnotherPart(num, len, mid, q, nodea);

                        }

                }

        }

}

 

int main()

{

int i,n,num[50];

printf("please input the number of num[]:");

scanf("%d",&n);

printf("please input num[]:\n");

for(i=0;i<n;i++)

scanf("%d",&num[i]);

        node masterNode = checkMaster(num, 1, n);

if(masterNode == NULL)

printf("the main elemer not exist! \n");

else

printf("num = %d count = %d\n", masterNode->data, masterNode->count);

Sleep(10000000);

}

 

方法三:主元素个数 > n/2 ,所以主元素的个数减去其它元素的个数仍然大于0

思路:假定a[0]为主元素mainE,主元素与其它元素的差值为dif,初值为1;然后进行比较,如果下一个元素与mainE相同,则++dif,否则--dif,若为0,则令后继元素为mainE且dif1

分析:时间复杂度为:O(n)  线性

代码实现:

#include <stdio.h>

#include <stdlib.h>

#include <windows.h>

 

int mainElement(int a[], int n)

{

int mainE = a[0];

int dif = 1;

int i =1;

int count;

while(i < n)

{

if(a[i] == mainE)

{

++dif;

}

else

{

--dif;

if(!dif)

{

mainE = a[i+1];

++i;

dif = 1;

}

}

++i;

}

 

//统计mainE的个数,判断mainE是否是主元素

count = 0;

for (i = 0; i < n; i++) {

if (a[i] == mainE) {

count++;

}

}

if (count > n/2) {

return mainE;

}

return 0;

}

 

void main()

{

int a[10];

int i,n,mainE;

printf("please input the number of a[]:");

scanf("%d",&n);

printf("please input a[]:\n");

for(i=0;i<n;i++)

scanf("%d",&a[i]);

mainE=mainElement(a,n);

if (mainE != 0) 

        printf("main element is %d\n", mainE);

    else 

        printf("main element not exits\n");

Sleep(100000);

}

 

主元素算法,布布扣,bubuko.com

主元素算法

原文:http://www.cnblogs.com/xymqx/p/3616832.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!