c - 在 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;
}
}
解决方案
如果您知道需要分配多少个节点,那么您当然可以在一次调用中将它们全部分配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
。因此,对于第一次迭代,您沿着箭头 fromhead
到rows[0]
,然后沿着allNodes[0]
该箭头到您绘制箭头到 的位置allNodes[1]
。
要理解为什么我们使用指向指针的指针node
以及(*node) = NULL
在做什么,那么我们需要绘制内部循环完成后它的样子。我们再次使用row == 0
作为示例。
+------+ +------------------+ | 节点 | --> | allNodes[2].next | --> ??? +------+ +------------------+
通过取消引用node
(如 中(*node)
)allNodes[2].next
,我们可以将其分配为NULL
指针。
推荐阅读
- c# - 如何按名称将现有表单动态添加到集合中
- function - 使用 AutoHotKey 打开任何应用程序的功能错误
- file - Ant 可以从两个目录中删除 _identical_ 文件吗?
- flask - 如何运行 websockets 服务器以及为 HTML 页面提供服务的烧瓶服务器?
- windows - 如何使用融合样式禁用焦点边框和背景 QTreeWidget?
- c - 二进制到十进制转换 C 代码 - 满足特定测试用例的问题
- android - Android MediaPlayer 发布问题(bug?)
- .htaccess - htaccess 重定向将回到家而不是新位置
- c# - 可空的 int 文化特定于 toString()
- asp.net - Identity Server 不调用 BackChannelLogout url