改进C语言程序的性能

时间:2018-10-22 09:45:20

标签: c performance

我正在编写用于作业的程序,而我的程序目前仅慢30毫秒。但是,我不确定如何加快程序速度。我试图对循环中的某些函数进行预计算,但我不确定它是否有帮助...

该程序的目的是接收大量输入,并确定输入中的特定数字是否占多数,并在随后确定所有亚军。

示例输入可能是:1 2 2 2 1 0

程序将输出:

majority: 2
runner-up: 1
#include <stdio.h> 
#include <stdlib.h>

int majorityCheck (int length, int arrMajority[]);
int runnerCheck (int length, int arrRunner[]);

unsigned int var, x, y;

int majorityCheck(int length, int arr[]){ //checks for maj
    int var, x, y;
    for(x=0;x<length-1;x++){
        var=0;
        for(y=0;y<length-1;y++){
            if(arr[y]==arr[x]){
                var++;
            }
        }
        if(2*var>length-1){
            return arr[x];
        }
    }
    return -1;
}

int runnerCheck(int length, int arr[]){ //checks for runnerup
    for(x=0;x<length-1;x++){
        var=0;
        for(y=0;y<length-1;y++){
            if(arr[y]==arr[x]){
                var++; //var is just a random incrementing tool
            }
        }
        if(2*var<length-1 && 4*var>length-1){
            return arr[x];
        }
    }
    return -1;
}

int main(int argc, char *argv[])
{
    unsigned int input;
    int *list=malloc(sizeof(int));
    int size=1;
    int numRunner;

    while(scanf("%u", &input)){
        if(input==0){
            break;}
            list[size-1]=input;
            size++;
            list=(int*)realloc(list, size*sizeof(int));
        }

    int numMajority=majorityCheck(size, list);
    if(numMajority==(-1)){
        printf("majority: NONE");}
        else{
            numRunner=runnerCheck(size, list);

            if(numRunner==(-1)){
                printf("majority: %d\nrunner-up: NONE", numMajority);
                }else{
                    printf("majority: %d\nrunner-up: %d", numMajority, numRunner);
                }
            }
            return 0;
        }

5 个答案:

答案 0 :(得分:1)

这是您可以做的:

  1. 使用合并排序对数组进行排序。
  2. 遍历数组,一次比较两个元素。因此,首先将0与1相比较,然后将1与2相比较...检查元素n是否等于n-1。这样做时,确定每个数字显示多少次。如果看到一个新数字,则将其计数设置为1,如果与之匹配,则增加其计数。否则,请为下一个数字创建一个新计数。

因此,例如,考虑数组0, 1, 1。首先,您将查看值0(在索引0)并将其计数存储在某个位置。然后,将其与1(在索引1处)进行比较,看它们是否匹配。如果它们这样做,则增加0的计数,否则,将1的计数存储为1在另一个变量中。由于它们不匹配,因此您将创建一个变量,用于存储1的计数。现在,当比较索引1和2上的1时,重复此过程。您将最终得到保存01计数的变量。您可以通过它们查找大多数出现的排名。

如果您希望算法不仅能够处理两个最高计数,还可以使用包含数字及其计数的结构数组。

另一方面,如果您只知道两个数字,则可以跟踪四个变量(firstNumfirstCount,{{ 1}},secondNum)。

答案 1 :(得分:0)

好的,所以我基本上通过预先计算循环中的函数并使用#include <math.h>

解决了这个问题

由于某种原因使我的程序执行时间缩短了将近一秒钟。

答案 2 :(得分:0)

首先,您必须意识到两个函数majorityCheckrunnerCheck实际上是相同的。它们仅相差一行:单个if语句。简而言之,它们执行完全相同的工作,但在不同条件下返回期望值。

由于您只有两个期望值(多数和第二名),因此您可以肯定地想象将您的函数组合为一个可以返回这两个值的函数。您如何选择返回两个值?您可以返回代表一对int的结构,也可以在函数中添加“ out”参数。剩下的唯一部分是存储这些值,而不是直接从函数返回。这是一个例子。

int majorityRunnerUpCheck(int array[], int length, int* majority, int* runnerUp) {
    int count, i, j;
    *majority = -1;
    *runnerUp = -1;

    // Note: if you use '<' (less than), then you want "length", not "length-1"
    for (i = 0; i < length; i++) {
        count = 0;
        // Note: here as well
        for (j = 0; j < length; j++) {
            if (array[i] == array[j]) {
                count++;
            }
        }
        // Note: and here, too;
        // otherwise you could have a majority with 3 out of 6
        // (unless you do want that)
        // Also, length/2 conveys the meaning better than var*2 (or count*2)
        if (count > length/2) {
            // Store the majority
            *majority = array[i];
        }
        // Note: are you sure you need the runner-up occurences to be more than a
        // fourth of the input? I don't think that's the definition of a runner-up...
        else if (count < length/2 && count > length/4) {
            // Store the runner-up
            *runnerUp = array[i];
        }
    }

    // Make the return value useful: let it be the number of expected values
    // you got, that is 2 for both, 1 for a majority but no runner-up, and 0
    // for no majority.
    if (*majority != -1) {
        if (*runnerUp != -1) {
            return 2;
        }
        return 1;
    }
    return 0;
}

当然,这可以进一步改善。但这需要重新设计算法。这是我受计数排序启发而要做的。我假设您数组中的值介于0到100之间。如果不是这种情况,您仍然可以使用其他灵感,例如基数排序或哈希排序(计数排序,但使用哈希表而不是数组) ,甚至是桶排序...

int majorityRunnerUpCheck(int array[], int length, int* majority, int* runnerUp) {
    int counts[101] = {0};
    int i, r = 0;
    *majority = -1;
    *runnerUp = -1;

    for (i = 0; i < length; i++) {
        counts[array[i]]++;
        if (counts[array[i]] > length/2) {
            *majority = array[i];
            r+=2;
        } else if (counts[i] < length/2 && counts[i] > length/4) {
            *runnerUp = array[i];
            r++;
        }
    }

    return r != 0 ? r-1 : 0;
}

答案 3 :(得分:0)

除了所有答案外,如果我们具有数字范围,并且所有输入数字均为正,那么我们可以在linear时间内解决此问题。

我们将计算辅助数组中每个数字的出现,然后扫描辅助数组以获取majorityrunner-up元素。

在此示例中,我假设输入数字的范围是0-1000

  

此技术的缺点:

     

这可以线性运行,但是在空间复杂度方面,
  如果范围太高,则此技术的效率不高。我们   需要提前知道输入范围才能分配内存
  用于辅助阵列。如果所有元素都是唯一的,那么这   算法将给您任意两个随机数,除非您处理所有   正确的情况。

#include <stdio.h>

int main()
{
    int number,i;
    scanf("%d",&number);
    int num[number];

    for(i=0;i<number;i++)
        scanf("%d",&num[i]);

    //create an array of 1000 elements
    int size = 1000;
    int auxiliary[size];

    for(i=0;i<size;i++)
        auxiliary[i]=0; //initialize count with 0
    for(i=0;i<number;i++)
        auxiliary[num[i]]++;  //count the occurrence 

    int majority,runner_up;  

     majority = 0;
     runner_up = 0;  

    for(i=1;i<size;i++)
       {
            if(auxiliary[i]>auxiliary[majority])
            {
                majority = i;
            }

       }

   for(i=1;i<size;i++)
       {

            if(auxiliary[i]>auxiliary[runner_up] && i!=majority)
            {
                runner_up = i;
            }

       }   

       if(runner_up==0)
            {
                printf("MAJORITY>> %d",majority);
                return 0;
            }


      printf("MAJORITY >> %d , RUNNER UP>>%d",majority,runner_up);

    return 0;
}

答案 4 :(得分:0)

要正确地加快速度,首先要意识到您不需要存储数字,而是可以存储每个数字发生了多少次,并且只需很少的花费即可完成此操作({ {1}},malloc()或通过链表进行构建和迭代)。对于未经测试的原始示例:

realloc()