C中nxn矩阵的walsh表

时间:2014-05-13 14:58:40

标签: c matrix multidimensional-array

我一直试图理解n维的沃尔什表矩阵,因为我需要编写一个代码,为任何给定的顺序生成沃尔什矩阵。到目前为止,我没有编写一个有效的代码。任何人都可以帮我解决这个问题,或者建议我的程序如下:(适用于2x2和4x4,但8x8无效)

#include<stdio.h>
#include<conio.h>
main()
{
    /* Program variables
    Dimension variable, n
    Loop variables i,j
    Two dimensional array for walsh table a[100][100] */

      int n,j,i,a[100][100];
      clrscr();
      // User input to display walsh table
      printf("enter the size ");
      scanf("%d",&n);

      // Iterate rows from 0 to 'n'
      for(i=0;i<n;i++)
      {

      // Iterate columns from 0 to 'n' for each row 'i'
      for(j=0;j<n;j++)
      {
        if(i%2==1 && j%2==1) // for both i & j not divisible by 2, initialize array elements with -1
                a[i][j] = -1;
        else if(i/2==1 && j/2==1){  // for both i & j, if completely divisble by 2 and dividend is 1
            if(j == 3 && i == 3){
                a[i][j]=1;
        }
            else
                a[i][j] = -1;
        }
        else                
                a[i][j] = 1;        // default case initialized to 1
        }
        a[3][3] = 1;
      }

      // Output complete walsh table
      for(i=0;i<n;i++)
      {
          for(j=0;j<n;j++)
          {
          printf("\t%d",a[i][j]);
          }
          // go to next line after every row 
          printf("\n");
      }
      getch();
      }

2 个答案:

答案 0 :(得分:1)

您应该将沃尔什代码的生成视为递归问题。首先你生成2x2;从那里你生成4x4等。每次,通过在右上角和左下象限中添加较小阶块的两个副本,从右上角生成下一个块,并在右下角添加其反转象限。您可以通过创建一次矩阵并逐步增加块大小来完成此操作。这是如何工作的

更新,因此它会生成您在wiki上看到的1 -1版代码;

再次更新使其能够获取矩阵大小的输入并生成任意大小的Walsh矩阵;包括各种错误检查和其他很酷的技巧:

FINAL(?)UPDATE Ryyker指出我的代码中存在内存错误。我发现并修复了它 - 并使用valgrind进行了检查以确定。现在似乎工作正常。

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

int **twoDmatrix(int m, int n) {
// create a 2D matrix of arbitrary dimensions
  int ii, **M;
  M = malloc(m * sizeof(int**));
  M[0] = malloc(m*n*sizeof(int*));
  for(ii=1; ii<m; ii++) {
    M[ii] = M[0] + ii * n;
  }
  return M;
}

void free2D(int** M) {
// free memory allocated by twoDmatrix()
  free(M[0]);
  free(M);
}

int isPow2(int n) {
// return 1 if the argument is a valid (positive) power of 2
  if(n<=1) return 0;
  while(n>1) {
    if (n%2==1) return 0;
    n = n/2;
  }
  return 1;
}

void emptyBuf(void) {
  while(getchar()!='\n');
  return;
}

int main(void) {
  int **W;
  int N;
  int power = 1;
  int i,j,k,l,p=0;
  while(1==1) {
    printf("enter the size of the matrix - must be a positive power of 2\n");
    if(scanf("%d", &N)!=1) {
      printf("unable to scan input\n"); 
      emptyBuf(); 
      continue;
    }
    if (!isPow2(N)) {
      printf("%d is not a valid power of 2\n", N); 
      continue;
    }
    break; // valid input: go on
  }

  W = twoDmatrix(N,N); // allocate memory for 2D matrix
  W[0][0]=1;   // this is the 1x1 Walsh code...

  while (power < N) {
    for(i=0; i<2; i++) {
      for(j=0; j<2; j++) {
        if (!(i==0 && j==0)) {
          for(k=0; k<power; k++) {
            for(l=0; l<power; l++) {
              if (i==1 && j == 1) {
                W[i*power+k][j*power+l] = -W[k][l]; // invert signal
              }
              else {
                W[i*power+k][j*power+l] = W[k][l]; // copy signal
              }
            }
          }
        }
      }
    }
    power *=2; // double matrix and repeat
  }

  // print out result
  for(i=0; i<N; i++) {
    for(j=0; j<N; j++) {
      printf("%2d ", W[i][j]);  // <<<<< updated
    }
    printf("\n");
  }
  free2D(W); // always remember to free your memory...
}

输出:

enter the size of the matrix - must be a positive power of 2
5
5 is not a valid power of 2
enter the size of the matrix - must be a positive power of 2
3
3 is not a valid power of 2
enter the size of the matrix - must be a positive power of 2
0
0 is not a valid power of 2
enter the size of the matrix - must be a positive power of 2
-4
-4 is not a valid power of 2
enter the size of the matrix - must be a positive power of 2
asdf
unable to scan input
enter the size of the matrix - must be a positive power of 2
asdfasdfasdfasdf
unable to scan input
enter the size of the matrix - must be a positive power of 2
16
 1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1 
 1 -1  1 -1  1 -1  1 -1  1 -1  1 -1  1 -1  1 -1 
 1  1 -1 -1  1  1 -1 -1  1  1 -1 -1  1  1 -1 -1 
 1 -1 -1  1  1 -1 -1  1  1 -1 -1  1  1 -1 -1  1 
 1  1  1  1 -1 -1 -1 -1  1  1  1  1 -1 -1 -1 -1 
 1 -1  1 -1 -1  1 -1  1  1 -1  1 -1 -1  1 -1  1 
 1  1 -1 -1 -1 -1  1  1  1  1 -1 -1 -1 -1  1  1 
 1 -1 -1  1 -1  1  1 -1  1 -1 -1  1 -1  1  1 -1 
 1  1  1  1  1  1  1  1 -1 -1 -1 -1 -1 -1 -1 -1 
 1 -1  1 -1  1 -1  1 -1 -1  1 -1  1 -1  1 -1  1 
 1  1 -1 -1  1  1 -1 -1 -1 -1  1  1 -1 -1  1  1 
 1 -1 -1  1  1 -1 -1  1 -1  1  1 -1 -1  1  1 -1 
 1  1  1  1 -1 -1 -1 -1 -1 -1 -1 -1  1  1  1  1 
 1 -1  1 -1 -1  1 -1  1 -1  1 -1  1  1 -1  1 -1 
 1  1 -1 -1 -1 -1  1  1 -1 -1  1  1  1  1 -1 -1 
 1 -1 -1  1 -1  1  1 -1 -1  1  1 -1  1 -1 -1  1 

供参考,请参阅http://my.fit.edu/~kostanic/Personal%20Communication%20Systems/ECE%205221%20-%20Lecture14.pptx - 我从中获取了以下内容:

enter image description here

<强> POSTSCRIPT

关于twoDmatrix()功能的说明。我编写了这个函数,因为没有直接的方法在C中分配未知大小的2D矩阵。所以这个函数创建了一个指向int的指针数组 - 矩阵中每一行的一个指针;它还分配一块内存 - 一个用于数组中的每个元素。然后它将一个指针与矩阵中每行的开头相关联,以便您可以使用通常的W[i][j]索引访问元素。这使得它看起来像数组的第一行真的很长(它指向整个NxN块),第二行稍短,等等。但它只是一个技巧,所以你可以访问数组的元素通常的语法。想象一下,你有一个3x3数组填充数字0到8 - 然后事情看起来像这样:

pointer      values
W[0]         0 1 2
W[1]         3 4 5
W[2]         6 7 8

但另一种看待它的方式是:

0 1 2 3 4 5 6 7 8 
^ W[0]
      ^W[1]
            ^W[2]

这意味着您可以访问元素W[0][6] - 其值与W[1][3]相同,后者再次与W[2][0]相同。

当你不再需要这个功能时,你必须释放两块内存 - 首先是数据块,然后是指针块。这是free2D()函数的作用。

答案 1 :(得分:0)

修改 您的代码 :我做了三件事:

为了便于阅读,

1) 格式化了更多块{...} 使用a[100][100]

的所有元素的 2) 初始化数组memset()

3) 添加了额外的getchar()(我的系统使用的不是getch()),并评论了clrscr()

它运行4x4和8x8 (但输出看起来不正确,你还有更多工作要做):

main()
{

    /* Program variables
    Dimension variable, n
    Loop variables i,j
    Two dimensional array for walsh table a[100][100] */

      int n,j,i,a[100][100];
      //clrscr();
      // User input to display walsh table

      memset(a, 0, 100*100);
      printf("enter the size ");
      scanf("%d",&n);

      // Iterate rows from 0 to 'n'
      for(i=0;i<n;i++)
      {

      // Iterate columns from 0 to 'n' for each row 'i'
            for(j=0;j<n;j++)
            {
                if(i%2==1 && j%2==1) // for both i & j not divisible by 2, initialize array elements with -1
                {
                        a[i][j] = -1;
                }
                else if(i/2==1 && j/2==1)
                {  // for both i & j, if completely divisble by 2 and dividend is 1
                    if(j == 3 && i == 3)
                    {
                        a[i][j]=1;
                    }
                }
                else
                {
                        a[i][j] = -1;
                }
            }
            a[i][j] = 1;        // default case initialized to 1
      }
      a[3][3] = 1;

      // Output complete walsh table
      for(i=0;i<n;i++)
      {
          for(j=0;j<n;j++)
          {
          printf("\t%d",a[i][j]);
          }
          // go to next line after every row 
          printf("\n");
      }
      getchar();
      getchar();
}