链表节点的创建,优先使用malloc

1、链表节点的动态分配

下面代码在执行地62行的打印语句时,发现链表L中的一个节点信息突然发生了变化,下图是打印语句执行前后链表L的变化对比图:

这个过程中明明没有对链表L进行操作,为什么会改变其节点信息呢?后来了解到该链表的节点是在另一个函数中通过LNode node;的方式创建的,这样做的结果是变量node为局部变量,保存在栈中,当退出创建该节点的函数后,这个节点所在的栈空间将被释放。 之前没有出问题是由于这片空间暂未被再次使用,所以在打印语句之前看上去一切正常,直到执行打印语句时这片空间被打印语句当作缓冲区利用,导致内存地址中的值发生改变,也就发生了图二的情况。

2、链表节点的释放

在下面的程序中,释放链表中的节点时出现错误:Trace/breakpoint trap

经了解后发现s所指向的节点也是采用DNode node;的方式创建的,该变量同样保存在函数栈区,而free函数是用于释放堆区的空间的,导致在这里用于释放栈区的变量时出错。

其实很好理解,局部变量都保存在了栈区,当函数结束时,它所在的函数栈会被回收,该函数中的局部变量也都会回收,所以无需采用free函数去回收局部变量。而malloc申请的空间位于堆区,这个区域的数据由程序员通过malloc申请,之后即使函数退出也依然保留着不会被自动回收,所以创建链表后,在其他函数中访问可以正常的访问链表。但也正是因为malloc申请的空间不会被自动回收,才需要程序员通过free函数手动去回收,否则,可以想象这样的一个后台程序,它每秒会创建一个1MB的节点并在1秒后回收,但写这个代码的程序员忘记用free回收了,假如这个程序持续运行1小时,那将有60x60=3600MB(3个多G)的内存空间被持续占用而得不到释放,这种内存泄漏是很严重的问题。

在创建链表时,采用malloc在堆区给节点分配内存,使链表在全局都可以被访问,但同样要记得在用完后使用free函数回收,避免内存泄漏。

  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一个基本的图的创建和深度优先遍历的C语言代码: ```c #include <stdio.h> #include <stdlib.h> #define MAX_VERTICES 100 typedef struct node { int vertex; struct node* next; } Node; Node* graph[MAX_VERTICES]; int visited[MAX_VERTICES]; void addEdge(int u, int v) { Node* newNode = (Node*)malloc(sizeof(Node)); newNode->vertex = v; newNode->next = graph[u]; graph[u] = newNode; } void createGraph(int vertices, int edges) { int i, u, v; for (i = 0; i < vertices; i++) { graph[i] = NULL; visited[i] = 0; } for (i = 0; i < edges; i++) { scanf("%d %d", &u, &v); addEdge(u, v); addEdge(v, u); } } void DFS(int vertex) { visited[vertex] = 1; printf("%d ", vertex); Node* temp = graph[vertex]; while (temp != NULL) { int adjVertex = temp->vertex; if (!visited[adjVertex]) { DFS(adjVertex); } temp = temp->next; } } int main() { int vertices, edges; printf("Enter the number of vertices: "); scanf("%d", &vertices); printf("Enter the number of edges: "); scanf("%d", &edges); createGraph(vertices, edges); int startVertex; printf("Enter the starting vertex for DFS: "); scanf("%d", &startVertex); printf("DFS Traversal: "); DFS(startVertex); return 0; } ``` 代码中定义了一个 `Node` 结构体来表示图中的每个节点,其中包含了节点的值和一个指向下一个节点的指针。 `graph` 数组用于存储整个图,其中每个元素都是一个指向链表头部节点的指针。链表中的节点表示与该节点相邻的其他节点。 `visited` 数组用于记录每个节点是否已经被访问过。 `addEdge` 函数用于向图中添加边,这里采用无向图,因此需要同时添加两个方向的边。 `createGraph` 函数用于创建图,它首先将每个节点的邻接链表初始化为空,并将 `visited` 数组中每个元素都初始化为 0。然后通过循环读取每个边的起始节点和结束节点,并调用 `addEdge` 函数将这些边添加到图中。 `DFS` 函数用于进行深度优先遍历,它首先将当前节点标记为已访问,并输出该节点的值。然后遍历该节点的邻接链表,对于每个未被访问的相邻节点,递归调用 `DFS` 函数。 在 `main` 函数中,首先读取图的顶点数和边数,并调用 `createGraph` 函数创建图。然后读取起始节点并调用 `DFS` 函数进行深度优先遍历。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值