2013-01-09 97 views
1

我有以下问题:提高C程序的计算速度

鉴于2个N号的文件,如

file1.dat:1,2,3,4,5,6,7 ,8,9,0

File2.DAT的:2,5,4,7,6,9,8,1,0,3

我想知道有多少时间连续的两个数字的顺序第一个文件在第二个文件中发生了变化(包含相同的数字)。例如,在文件1中,我们开始寻找1和2,在第二个文件2中找到1,因此订单发生了变化;在第一个文件中有9个,然后是0,在第二个文件中保持这个顺序。

我写了下面的程序:

#include <stdio.h> 
#include <stdlib.h> 
#define N 32421 

int main() { 
    int A[N], B[N]; 
    int i,j,k=0,count=0; 
    FILE *fp; 

    if ((fp = fopen ("file1.dat", "r")) == NULL) { 
    printf ("Error opening file 1\n"); 
    exit (EXIT_FAILURE); 
    } 
    for (i = 0; i < N; i++) 
    fscanf (fp, "%d", &A[i]); 
    fclose (fp); 

    if ((fp = fopen ("file2.dat", "r")) == NULL) { 
    printf ("Error opening file 2\n"); 
    exit (EXIT_FAILURE); 
    } 
    for (i = 0; i < N; i++) 
    fscanf (fp, "%d", &B[i]); 
    fclose (fp); 

    for(i=0; i<N-1; i++) 
    for(j=0; j<N; j++) 
     for(k=0 ; k<N; k++) 
     if(B[j]==A[i] && B[k]==A[i+1] && k < j) 
    count++; 


    printf("The number of inversion is: %d\n",count); 

    return 0; 
} 

与我处理的文件是非常大的,你可以从程序(32421号每个文件)的3号线看到,所以时间采取的太大了。任何人有任何建议来提高计算速度?


我也试图与破环中的下列方式增加:

int a; 

    for(i=0;i<N-1;i++){ 
    a=0; 
    for(j=0;j<N;j++){ 
     for(k=0;k<N;k++){ 
    if(A[i]==B[j] && A[i+1]==B[k] && k<j) { 
     count++; 
     break; 
     a=1; 
    } if(A[i]==B[j] && A[i+1]==B[k] && j<k){ 
     break; 
     a=1; 
    } 
     } 
     if(a==1){ 
     break; 
     } 
    } 
    } 

但它仍然需要5个多小时。我如何加快速度?

+0

是否所有的号码不同的第一阵列的第一个元素的位置? – pmg

+2

你可以在你的循环中做一些'break'ing – pmg

+0

@pmg,这个中断可能是一个解决方案,但我不知道如何在程序中编写它们。这些数字都是截然不同的 –

回答

4
for(i=0; i<N-1; i++) { 
    //looking for the position of B[i] in A 
    j=-1; 
    while (A[++j] != B[i]) {} 

    //now A[j] is B[i] 

    for (k= 0 ; k < j; k++) { 
     //is the next in B in a previous position in A ? 
     if (B[i+1] == A[k]) { 
      count++; 
      break; 
     } 
    } 
} 

并且还,这里是另一种解决方案

int pos1, pos2; 
for(i=0; i<N-1; i++) { 
    pos2=-1; 
    for(j=-1; j<N && pos1 != -1 && pos2 != -1; j++) { //will stop if both are found 
     if (pos1 == -1 && B[i]==A[j]) pos1 = j; //found the position of a num 
     if (B[i+1]==A[j]) pos2 = j; //found the position of the next num 
     if (pos2 < pos1) { 
      count++; 
     } 
    } 
    pos1 = pos2; //useful for next loop.. 
} 
+0

不客气:) –

+1

不错。你也可以查找(B [i + 1] == A [k]),其中k从N开始,当j接近N时停止在k> j。 – pfnuesel

+0

@pfnuesel是的,这是一种改进方法:) –

1

这里的关键是 “第一文件中的两个连续号”。

没有必要做一个O(N^2)循环。事实上,你可以使用动态规划方法采用以下标准:

  • 的数字是不同的

  • 对于任何一组N数字,该数值是0..N-1(这是我的假设)

  • 对于第一个文件中的任何两个连续号码AB,如果您在遇到B时已遇到A,则顺序将保留在第二个文件中。

请注意我对数值的假设。如果这个假设是错误的,那么你可以使用当前被接受的O(N^2)-ish答案(尽管你可以建立一个树来索引值,最坏的情况变成O(N.log(N) )。

如果可以索引的值直接,那么这个问题变为线性。

+0

但是我应该如何修改我的cicle? –

+0

'cicle'是什么意思? – paddy

+0

对不起,我做了一个不好的翻译。我的意思是循环 –

0

长度的两个阵列,N是间倒位数...

如果N是1,反转的数目是0
否则,它是所述第一阵列的最后N-1的元素和所述第二阵列不包括第一阵列加上的第一元件之间的反转次数第二阵列

万岁递归:)

#include <stdlib.h> 
#include <string.h> 

static int find(int a, int *b, size_t n) { 
    size_t k = 0; 
    while (k < n) { 
    if (b[k] == a) return k; 
    k++; 
    } 
    return -1; 
} 

int ninversions(int *a, int *b, size_t n) { 
    if (n == 1) return 0; 
    size_t pos = find(*a, b, n); 
    if (pos == (size_t)-1) exit(EXIT_FAILURE); 
    int *newb = malloc((n - 1) * sizeof *newb); 
    memcpy(newb, b, pos * sizeof *b); 
    memcpy(newb + pos, b + pos + 1, (n - pos - 1) * sizeof *b); 
    int retval = pos + ninversions(a + 1, newb, n - 1); 
    free(newb); 
    return retval; 
}