三角阵列

时间:2013-07-01 14:13:31

标签: c arrays

我想在C中构造一个2d数组,其中每行将具有不同数量的元素。具体来说,我想构建一个三角形7x6阵列。为了节省内存,我想避免存储零,如下例所示。

                               1 0 0 0 0 0 0
                               1 1 0 0 0 0 0
                                     ...
                               1 1 1 1 1 1 1   

我该怎么做?

6 个答案:

答案 0 :(得分:17)

制剂

这个索引系统不会起作用吗?

0
1 2
3 4 5
6 7 8 9
...

只需将数据存储在一维数组中,使用此映射到三角矩阵/数组。

双向注入

ki时,一维从零开始的索引j和二维从零开始的行k = i(i+1)/2 + j和列j <= i相同})。

注意

以上是针对下三角形方阵/阵列。你可以为

做一些非常相似的事情
  • 上三角形方阵/阵列
    • 只需交换ij
    • 即可
  • 矩形的下三角形或上三角形矩阵/阵列
    • 这有点棘手(需要通过案例推理),但是可以实现将一维数组(实现)映射到概念二维数组(视图)的相同想法

答案 1 :(得分:1)

注意 - 这是未经测试的伪代码,不是有效的C代码。

int **c;
c = malloc (7 * sizeof(int *));
for (i=0;i<7;i++)
  c[i] = malloc ( (i+1) * sizeof (int));

但是,我不确定你为什么要这样做。如果您对访问此阵列不是非常小心,则很可能最终会出现分段错误。

答案 2 :(得分:0)

此函数将在一维数组中为行和列编号指定索引,并且是无序的:

static inline int64_t index(const int32_t x, const int32_t y) {
    int_fast32_t min, max;
    if (x < y) {
        min = x;
        max = y;
    } else {
        min = y;
        max = x;
    }
    return ((max * (max + 1)) >> 1) + min;
}

会导致像(xy这样的索引以0开头:

0   1   3   6   10  15  21  28
1   2   4   7   11  16  22  29
3   4   5   8   12  17  23  30
6   7   8   9   13  18  24  31
10  11  12  13  14  19  25  32
15  16  17  18  19  20  26  33
21  22  23  24  25  26  27  34
28  29  30  31  32  33  34  35
36  37  38  39  40  41  42  43
45  46  47  48  49  50  51  52
55  56  57  58  59  60  61  62
66  67  68  69  70  71  72  73

答案 3 :(得分:0)

使用一维数组并计算 声明一个size = rows×(rows + 1)/ 2的数组 index = row x(row + 1)/ 2 +列 使用这种解决方案,你可以浪费时间乘以2除以加法(尽管右移会将除以2除以)。 或者,您可以为每一行使用一个指针数组,并在循环中分配所需数量的元素。

答案 4 :(得分:0)

您可以创建一个指针的一维数组,而不是创建单个一维数组并将其视为一个二维数组,其中每个指针指向另一个一维数组。这使您可以使用不同的大小分配数组中的每一行。

例如:

// Allocate and initialize a triangular 2-D array
int** make_triangle_array(int nrows)
{
    int **  arr;

    // Allocate the 1-D array of pointers
    arr = malloc(nrows * sizeof(int *));

    // Allocate each row of the triangular array
    for (int i = 0;  i < nrows;  i++)
    {
        int     rowlen = i+1;

        // Allocate a row of ints for the array
        arr[i] = malloc(rowlen * sizeof(int));

        // Fill the row with '1' values
        for (int j = 0;  j < rowlen;  j++)
            arr[i][j] = 1;
    }

    // Return the allocated array
    return arr;
}

// Test driver
void test(int n)
{
    int **  arr;

    arr = make_triangle_array(n);
    ...
    free_triangle_array(arr, n);
}

这种方法的优点是能够为每一行分配任何大小。它还具有能够使用语法arr[x][y]访问数组中给定元素的优点。

(这与Java和C#等语言使用 references 分配多维数组的方式非常类似。)

请注意,当您使用完阵列后,您必须分两步取消分配;首先你必须释放数组的每一行,然后你必须释放数组(指针)本身。

// Deallocate a 2-D array
void free_triangle_array(int **arr, int nrows)
{
    // Free each allocated row
    for (int i = 0;  i < nrows;  i++)
    {
        if (arr[i] != NULL)
            free(arr[i]);
        arr[i] = NULL;
    }

    // Free the pointer array
    free(arr);
}

答案 5 :(得分:0)

正如您在问题中提到的一个位数组。因此,我假设您希望在使用非常简单的代码时优化内存使用量。一个解决方案,如果2-d数组是固定的(可能在你的情况下)是创建一个分配了位文件的结构,如下所示:

struct triangular_array {
int line1:1      __attribute__((packed));  //line1 will have only one bit storage capacity
int line2:2      __attribute__((packed));
int line3:3      __attribute__((packed));
int line4:4      __attribute__((packed));
int lint5:5      __attribute__((packed));
int lint6:5      __attribute__((packed));
int lint7:7      __attribute__((packed));
.
.
.
.
and so on
};

//create an object
struct triangular_array object1;

//initialise the object
object1.line1= 0b1;
.
.
.
.

有关此实施的事情:

  1. 简单方法,但可能比不使用'packed'属性时慢。权衡将是额外的比特包装。对于某些实际情况,这可能是不安全的(请查看下面的stackoverflow链接)
  2. 您有时可能需要注意字节序
  3. 此方法有时用于需要交换数据包的网络代码。
  4. 您可以阅读有关属性的更多信息:

    1. 海湾合作委员会文件:http://gcc.gnu.org/onlinedocs/gcc-3.2/gcc/Type-Attributes.html
    2. 考虑:Is gcc's __attribute__((packed)) / #pragma pack unsafe?