首页 > 解决方案 > 在 C 中连接两个结构

问题描述

我正在尝试链接 2 个结构,一个是矩阵,一个是单个节点。连接应该是一个包含大小的矩阵和一个包含彼此连接的节点的行数组:因此 3X3 矩阵应该如下所示:

|节点|->|节点|->|节点|-> NULL

|节点|->|节点|->|节点|-> NULL

|节点|->|节点|->|节点|-> NULL

问题是如何正确连接它?我只需要为行分配内存还是应该为所有元素分配内存然后连接它们?

typedef struct cellNode {
        int cell;
        struct cellNode* next;
}   Node;

typedef struct  {
        int numRows;
        int numColumns;
        Node** rows;
}   Matrix;



Matrix* MatrixAdder(int row, int col, char mat)
{
    Matrix temp=NULL;
    int i,j;
    if(!(temp=(Matrix*)malloc(sizeof(Matrix)));
        exit(1);
    temp->numRows=row;
    temp->numColumns=col;
    if (!(temp.rows[i]=(Node*)malloc((row)*sizeof(Node))));
        exit (1);
    printf("Please insert values for matrix %c:\n",mat);
    for (i=0;i<row;i++)
    {
        if(!(temp->rows[i]=(Node*)malloc(sizeof(Node))))
            exit (1);
        printf("Enter row %d data\n",i);
        for(j=0;j<col;j++)
        {
            scanf("%d",&temp->rows->cell);
            temp->rows=temp->rows->next;
            if(!(temp->rows=(Node*)malloc(sizeof(Node))))
              exit (1);
        }
        temp->rows=NULL;
    }


}

标签: cstruct

解决方案


如果您知道需要分配多少个节点,那么您当然可以在一次调用中将它们全部分配malloc(作为一个普通的普通节点“动态数组”),然后将它们全部链接在一起。您需要做的就是跟踪由malloc.

但是您仍然需要分配用于rows. 因此,无论您需要至少两次分配。

它可能是这样的圆顶(使用普通变量而不是你的结构):

int numRows = 3;
int numColumns = 3;

// Allocate all the nodes
Node *allNodes = malloc(sizeof *allNodes * numRows * numColumns);

// Allocate the array of pointers needed
Node **rows = malloc(sizeof *rows * numRows);

// Initialize the rows
for (int row = 0; row < numRows; ++row)
{
    // if numColums == 3 then for
    //   row == 0 get a pointer to allNodes[0]
    //   row == 1 get a pointer to allNodes[3]
    //   row == 2 get a pointer to allNodes[6]
    rows[row] = &allNodes[row * numColumns];
}

// Now create the linked lists
for (int row = 0; i < numRows; ++row)
{
    // For numRows == 3, this will make node point to, in turn:
    //   allNodes[0]
    //   allNodes[3]
    //   allNodes[6]
    Node **node = &rows[row];

    // node will be pointing to a pointer to the *previous* node
    // So start with 1 because that's then the *next* node in the list
    for (int col = 1; col < numColumns; ++col)
    {
        // When row == 0 then:
        //   When col == 1 then link allNodes[0]->next to allNodes[1]
        //   When col == 2 then link allNodes[1]->next to allNodes[2]
        // When row == 1 then:
        //   When col == 1 then link allNodes[3]->next to allNodes[4]
        //   When col == 2 then link allNodes[4]->next to allNodes[5]
        // Etc...
        (*node)->next = &allNodes[row * numColumns + col];
        (*node) = &(*node)->next;
    }

    // Now head will be pointing to the lasts nodes next member
    (*node) = NULL;
}

[注意:代码未经测试!]

完成后,您只有两个指向 free 的指针:

free(rows);
free(allNodes);

要准确了解发生了什么,如果您在跟进时遇到问题,我建议您使用调试器以及笔和一些纸。

首先绘制一个长矩形allNodes并将其划分为numRows * numColumns多个子矩形。用它们的索引标记它们(所以第一个变成0,第二个1等等)。然后绘制第二个矩形rows并将其划分为numRows子矩形。也用索引标记这些。

现在,当您进入调试器时,在子矩形之间为表单“指针”绘制箭头。例如,在第一个循环的第一次迭代中,您从rows[0]to绘制一个箭头allNodes[0]

对于创建链表的第二个循环,绘制另一个小矩形并标记它head。对于外部链接循环的每次迭代,您(擦除)并从head到 first绘制一个箭头rows[0],依此类推。

在带有语句的内部链接循环内(在列上)

(*head)->next = &allNodes[row * numColumns + col];

从 开始head并按照它的箭头到rows。然后再次按照箭头到allNodes,并继续按照任何箭头,直到不再有。然后从该元素绘制一个箭头,allNodes指向下一个元素,allNodes如 所示row * numColumns + col。因此,对于第一次迭代,您沿着箭头 fromheadrows[0],然后沿着allNodes[0]该箭头到您绘制箭头到 的位置allNodes[1]

要理解为什么我们使用指向指针的指针node以及(*node) = NULL在做什么,那么我们需要绘制内部循环完成后它的样子。我们再次使用row == 0作为示例。

+------+ +------------------+
| 节点 | --> | allNodes[2].next | --> ???
+------+ +------------------+

通过取消引用node(如 中(*node)allNodes[2].next,我们可以将其分配为NULL指针。


推荐阅读