【问题标题】:Transpose a jagged array in C?在C中转置一个锯齿状数组?
【发布时间】:2015-01-03 11:36:18
【问题描述】:

几天来,我一直在用 C 转换一个锯齿状数组时遇到问题,我真的找不到解决方案。基本上,我们得到一个大部分为零的矩阵(稀疏矩阵),我们打算将其转换为锯齿状数组。我能够做到这一点没有问题。备用矩阵是

7 8
0 0 0 5 1 0 0 5
0 0 0 0 0 0 0 0
0 0 0 0 1 2 0 0
1 0 0 0 0 0 0 0
3 0 0 5 0 0 3 0
1 0 0 0 0 3 0 0
0 0 0 0 0 0 0 1

7 和 8 是行和列,我们应该首先阅读它们。行全为零的任何点(在本例中为第二行),锯齿状数组都意味着具有 NULL。我们应该使用我在这个循环中执行的 calloc() 为锯齿状数组分配内存:

for(i=0; i<rows; i++)
{
    for(j=0; j<columns; j++)
    {
        if(matrix[i][j] != 0)
        {
            flag++;
        }
    }
    if(flag > 0)
    {
        jagged[i] = (float *)calloc(flag, sizeof(float));
    }
    else
    {
        jagged[i] = NULL;
    }
    flag = 0;
}   

所以我的锯齿状数组打印为:

5 1 5
NULL
1 2
1
3 5 3
1 3
1

这是按原样打印的,并且工作正常。然后,我们打算将锯齿状数组添加到自身,我在这个循环中(在函数内部)执行此操作:

    for(i=0; i<rows; i++)
    {
        if(jagged[i]) //if the row exists, continue
        {
            for(j=0; j<columns; j++)
            {
                if(jagged[i][j]) //if the index exists, add it to itself
                {
                    jagged[i][j] += jagged[i][j];
                }
            }
        }
    }

这也可以正常工作,新的锯齿状数组打印为:

10 2 10
2 4
2
6 10 6
2 6
2

最后一部分是我卡住的地方。我现在打算转置上面的数组(行变成列)。我已经尝试了几种方法来解决这个问题。我尝试使用 calloc() 创建一个新数组,其循环类似于上面的循环,但循环通过锯齿状数组,并且行和列颠倒。但是,每当我尝试沿着锯齿状数组的列向下移动时(循环从锯齿状 [0][0] 开始,然后下一次迭代在锯齿状 [1][0] 处),我总是会遇到分段错误,即使我是检查正在检查的下一行/元素是否为 NULL。有没有更好的方法来做这个换位,或者我在做这件事的方式上犯了可以修复的错误?这让我沮丧了将近一个星期,因此非常感谢任何帮助。如有必要,可以提供更多详细信息。提前致谢!

【问题讨论】:

  • 当您为锯齿状数组的第一行写入5 1 5 时,它代表的是“完整”数组中的0 0 0 5 1 0 0 5 行还是5 1 5 0 0 0 0 0 行?我们怎么知道?
  • 我给出的矩阵是我们从中读取的.txt文件,抱歉我没有提到
  • 输入的格式没有问题。矩阵行5 1 5 0 0 0 0 00 0 0 5 1 0 0 5 不同。我们可以很容易地看到这些行中的哪一行在 input 中,问题是我们如何知道这两行中的哪一行 存储 在您的锯齿状数组中。
  • 我只将非零值读入数组。锯齿状数组本身不包含任何零。
  • 那么您丢失了输入中的基本信息。您无法从数据结构中构造原始输入数组的转置。还不清楚“转置”数据结构意味着什么,因为您的数据结构不支持矩阵转置。

标签: c jagged-arrays


【解决方案1】:

显然,原始输入矩阵与您的问题完全无关,是一个转移注意力的问题。我会忽略它,只看你的锯齿状数组。

为了使锯齿状数组完全有用,您必须有某种方法可以知道每行中有多少个数字。否则,您永远无法知道是否应该从该行中再读取一个数字,或者这是否会导致段错误。

现在假设您有办法知道每行中的数字数量,并且您存储了一个锯齿状数组m,如下所示:

10 2 10
2 4
2
6 10 6
2 6
2

从一个空的锯齿状数组m_transpose 开始。基本上你想做的是, 对于m 的每一行,对于i 从0 向上计数, 从m 的那一行的元素i 中读取x; 然后找到第一行 m_transpose 中没有 i+1 数字的行, 并将x 附加到m_transpose 的那一行。

如果你必须为每一行分配正确大小的数组float m_transpose,那么您将不得不分两次执行此操作。 在第一遍中,您从一个零数组开始,只要m 的最长行, 并且您遍历m 的每一行,正如我已经描述的那样,除了 而不是将元素im的行附加到m_transpose的行, 您只需将 1 添加到整数数组中小于i+1 的第一个元素。 然后你可以将m_transpose的所有行分配到正确的大小, 在第二遍中,您可以将m 的元素复制到m_transpose 如前所述。 (请注意,您需要一个整数数组来跟踪每行的位置 m_transpose 你应该“追加”下一个数字。)

个人认为,除非锯齿状数组最长行的长度与数组非空行数的乘积非常很大(并且远大于非空行的总数) -数组的零元素),我将分配矩形数据结构 每行中最后一个非零数字后有一个零。 然后,您可以安全地遍历数组,而无需一些辅助数据结构 告诉你每行有多长。

【讨论】:

    【解决方案2】:

    检查下一个元素是否为 NULL 不是解决方案。您必须在它用完之前停止向下迭代。只要您读取 jagged[i][j] ,其中 j 在该数组的边界之外,您就有可能出现段错误。

    如果在数组仍然是矩形时先进行转置,然后再使其呈锯齿状,您可能会轻松得多。

    如果不允许这样做,您将不得不跟踪锯齿状数组的每一行中有多少项目,并相应地设置 j 内循环的限制。

    【讨论】:

    • 即使我这样做:for(i=0; i
    • 像你说的那样先移调是不允许的。
    猜你喜欢
    • 2016-06-17
    • 1970-01-01
    • 2015-04-23
    • 1970-01-01
    • 2019-02-18
    • 1970-01-01
    • 2011-06-10
    • 1970-01-01
    • 2010-11-08
    相关资源
    最近更新 更多