如何理解这些代码重新排列(a1 a2 ... am b1 b2..bn)数组到(b1 b2 .bn a1 a2..am)

时间:2016-07-18 14:47:11

标签: c algorithm

此代码是由某人设计的,用于将数组[a1 a2...am b1 b2..bn ]更改为数组[b1 b2 ..bn a1 a2..am],但它涉及最大的公约数,我无法理解这一点。

void Exchange(int a[],int m,int n,int s){
    int p=m,temp=m+n;int k=s%p;
    while(k!=0){temp=p;p=k;k=temp%p;}
    for(k=0 ; k<p ;k++){                //below is where i cant't understand
        temp=a[k];i=k;j=(i+m)%(m+n);
        while(j!=k)
            {a[i]=a[j];i=j;j=(j+m)%(m+n);}
        a[i]=temp;
    }
};

编辑:“正确”缩进:

void Exchange(int a[], int m, int n, int s) {
    int p = m, temp = m + n, k = s % p;

    while (k != 0) {
        temp = p;
        p = k;
        k = temp % p;
    }

    for (k = 0 ; k < p; k ++) {   // below is where i cant't understand
        temp = a[k];
        i = k;
        j = (i + m) % (m + n);

        while (j != k) {
            a[i] = a[j];
            i = j;
            j = (j + m) % (m + n);
        }

        a[i] = temp;
    }
};

2 个答案:

答案 0 :(得分:0)

代码使用单个开销值来实现数组旋转。如果长度是相互素数,则单次通过就足够了。如果没有,则必须通过长度为

的GCD重复移位循环

我之前说过,还有其他问题可以解决这个问题。找到SO 3333-3814的外观处理单个旋转。我做了一些乱码代码以支持前一段时间,证明需要GCD,但我以前没有发布过它。

这是代码 - 它使用C99 VLAs - 可变长度数组。

#include <stdio.h>

static int gcd(int x, int y)
{
    int r;

    if (x <= 0 || y <= 0)
        return(0);

    while ((r = x % y) != 0)
    {
        x = y;
        y = r;
    }
    return(y);
}

static void dump_matrix(int m, int n, int source[m][n])
{
    for (int i = 0; i < m; i++)
    {
        for (int j = 0; j < n; j++)
            printf("%4d", source[i][j]);
        putchar('\n');
    }
}

static void init_matrix(int m, int n, int source[m][n])
{
    for (int i = 0; i < m; i++)
    {
        for (int j = 0; j < n; j++)
            source[i][j] = (i + 1) * (j + 2);
    }
}

static void rotate_1col(int n, int vector[n], int z)
{
    z %= n;
    if (z != 0)
    {
        int c = gcd(n, z);
        int s = n / c;
        for (int r = 0; r < c; r++)
        {
            int x = r;
            int t = vector[x];
            for (int i = 0; i < s; i++)
            {
                int j = (x + z) % n;
                int v = vector[j];
                vector[j] = t;
                x = j;
                t = v;
            }
        }
    }
}

static void rotate_cols(int m, int n, int source[m][n], int z)
{
    for (int i = 0; i < m; i++)
        rotate_1col(n, source[i], z);
}

int main(void)
{
    int m = 3;

    for (int n = 2; n < 9; n++)
    {
        int source[m][n];
        for (int z = 0; z <= n; z++)
        {
            init_matrix(m, n, source);
            printf("Initial:\n");
            dump_matrix(m, n, source);
            rotate_cols(m, n, source, z);
            printf("Post-rotate %d:\n", z);
            dump_matrix(m, n, source);
            putchar('\n');
        }
    }

    return 0;
}

代码演示了不同大小的数组的不同旋转大小。输出的示例部分:

…
Initial:
   2   3   4
   4   6   8
   6   9  12
Post-rotate 1:
   4   2   3
   8   4   6
  12   6   9
…
Initial:
   2   3   4   5
   4   6   8  10
   6   9  12  15
Post-rotate 3:
   3   4   5   2
   6   8  10   4
   9  12  15   6
…
Initial:
   2   3   4   5   6   7
   4   6   8  10  12  14
   6   9  12  15  18  21
Post-rotate 1:
   7   2   3   4   5   6
  14   4   6   8  10  12
  21   6   9  12  15  18

Initial:
   2   3   4   5   6   7
   4   6   8  10  12  14
   6   9  12  15  18  21
Post-rotate 2:
   6   7   2   3   4   5
  12  14   4   6   8  10
  18  21   6   9  12  15

Initial:
   2   3   4   5   6   7
   4   6   8  10  12  14
   6   9  12  15  18  21
Post-rotate 3:
   5   6   7   2   3   4
  10  12  14   4   6   8
  15  18  21   6   9  12
…
Initial:
   2   3   4   5   6   7   8   9
   4   6   8  10  12  14  16  18
   6   9  12  15  18  21  24  27
Post-rotate 4:
   6   7   8   9   2   3   4   5
  12  14  16  18   4   6   8  10
  18  21  24  27   6   9  12  15

Initial:
   2   3   4   5   6   7   8   9
   4   6   8  10  12  14  16  18
   6   9  12  15  18  21  24  27
Post-rotate 5:
   5   6   7   8   9   2   3   4
  10  12  14  16  18   4   6   8
  15  18  21  24  27   6   9  12

Initial:
   2   3   4   5   6   7   8   9
   4   6   8  10  12  14  16  18
   6   9  12  15  18  21  24  27
Post-rotate 6:
   4   5   6   7   8   9   2   3
   8  10  12  14  16  18   4   6
  12  15  18  21  24  27   6   9
…

答案 1 :(得分:0)

首先,为了得到你所说的预期结果,我将m和n设置为数组大小的一半。我还假设s将初始化为零,在这种情况下,第一个while循环不会迭代。此外,您的代码中缺少多个声明,因此我的解释会做出一些假设。

The variable p holds the number of array elements to swap;


// This is to keep the value to be overwritten by the swap  
temp=a[k];

// This is the array index of the bottom half element to write the top half element to
i=k;

// this is to get the current index of the top half; 
j=(i+m)%(m+n);

// This assignes the bottom index value with the top half value
while(j!=k)
    {
            // Write top half element to corresponding bottom half element
            a[i]=a[j];
            // We can now overwrite top half element; this assignes the index at wich to copy the bottom half element
            i=j;
            // This is to get out of the loop
            j=(j+m)%(m+n);
    }

 // The bottom half element held at the beginning is now written to the top half at the corresponding index
 a[i]=temp;

希望这是您正在寻找的答案。我通过使用调试器并逐行踩入代码来达到这个结果。我不知道你是否知道如何使用调试器,但如果没有,那么我强烈推荐你的精益如何使用它;它花了很多时间,并返回了一个很棒的红利: - )