鱼C论坛

 找回密码
 立即注册
查看: 35|回复: 3

动态链表

[复制链接]
发表于 昨天 21:43 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
链表我可以看懂,但是到了动态链表我感觉一点都看不懂,这可咋整。。。。前面的函数、指针虽然不是很熟练,但至少能看懂程序,但是动态链表是真的看不懂,云里雾里。。。。
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 昨天 21:44 | 显示全部楼层
动态链表我可以看懂,但是到了动态链表我感觉一点都看不懂,这可咋整。。。。前面的函数、指针虽然不是很熟练,但至少能看懂程序,但是动态链表是真的看不懂,云里雾里。。。。


别担心,动态链表只是链表的一种实现方式,它在程序运行时动态分配内存来创建节点。如果你已经理解了链表的基本概念,那么动态链表只是多加了一步:动态内存分配。下面我用简单的方式解释一下。

核心概念:
- 动态链表的每个节点包含两部分:数据(存储值)和指针(指向下一个节点)。
- 它使用动态内存分配函数(如C中的 malloc)在运行时创建新节点,而不是在编译时固定大小。
- 通过指针操作将节点连接起来,形成链式结构。

一个简单的动态链表示例(C语言):
以下代码创建了一个包含三个节点的动态链表,并遍历输出。


  1. #include <stdio.h>
  2. #include <stdlib.h>

  3. // 定义链表节点结构
  4. struct Node {
  5.     int data;           // 数据域
  6.     struct Node* next;  // 指针域,指向下一个节点
  7. };

  8. int main() {
  9.     // 创建三个节点指针,初始化为NULL
  10.     struct Node* head = NULL;
  11.     struct Node* second = NULL;
  12.     struct Node* third = NULL;

  13.     // 动态分配内存给三个节点
  14.     head = (struct Node*)malloc(sizeof(struct Node));
  15.     second = (struct Node*)malloc(sizeof(struct Node));
  16.     third = (struct Node*)malloc(sizeof(struct Node));

  17.     // 检查内存分配是否成功
  18.     if (head == NULL || second == NULL || third == NULL) {
  19.         printf("内存分配失败!\n");
  20.         return 1;
  21.     }

  22.     // 为节点赋值并连接它们
  23.     head->data = 1;          // 第一个节点的数据
  24.     head->next = second;     // 指向第二个节点

  25.     second->data = 2;        // 第二个节点的数据
  26.     second->next = third;    // 指向第三个节点

  27.     third->data = 3;         // 第三个节点的数据
  28.     third->next = NULL;      // 第三个节点是尾节点,next为NULL

  29.     // 遍历链表并打印数据
  30.     struct Node* current = head;
  31.     while (current != NULL) {
  32.         printf("%d -> ", current->data);
  33.         current = current->next;
  34.     }
  35.     printf("NULL\n");

  36.     // 释放动态分配的内存
  37.     free(head);
  38.     free(second);
  39.     free(third);

  40.     return 0;
  41. }
复制代码


逐步解释:
1. 定义节点结构 struct Node,它包含一个整数 data 和一个指向下一个节点的指针 next
2. 在 main 函数中,声明三个节点指针并初始化为NULL,表示它们还没有指向任何内存。
3. 使用 malloc 动态分配内存: sizeof(struct Node) 计算一个节点需要的内存大小, malloc 返回分配的内存地址,然后转换为 struct Node* 类型。
4. 检查内存分配是否成功,如果失败则输出错误信息。
5. 为每个节点的数据域赋值,并通过 next 指针连接节点,形成链表(head -> second -> third -> NULL)。
6. 遍历链表:从 head 开始,使用一个临时指针 current 依次访问每个节点,打印数据,直到 current 为NULL。
7. 最后,使用 free 释放内存,避免内存泄漏。

关键点总结:
- 动态链表的节点是在堆(heap)上动态创建的,而不是在栈上静态分配。
- 指针是连接节点的桥梁:每个节点的 next 指针存储下一个节点的地址。
- 务必记得释放内存,否则会导致内存泄漏。

如果你对指针和函数不熟练,建议先复习指针基础(如指针声明、赋值、访问指针指向的数据)。动态链表只是这些知识的应用。多动手写代码,从简单示例开始,尝试添加节点、删除节点等操作,慢慢就会理解了。加油!

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 昨天 22:27 | 显示全部楼层
FishC 发表于 2025-12-2 21:44
别担心,动态链表只是链表的一种实现方式,它在程序运行时动态分配内存来创建节点。如果你已经理解了链 ...

前面的章节我是逐步看下来的,虽说可能独立编写程序还弱一些,但程序基本能看懂,但是到了链表这边就觉得非常的吃力,基本都看不懂了,我需要将前面的指针函数等再巩固巩固吗?
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 昨天 22:27 | 显示全部楼层
但求过程001 发表于 2025-12-02 22:27
FishC 发表于 2025-12-2 21:44
别担心,动态链表只是 ...


别灰心,这是非常正常的现象!链表确实是C语言学习中的一个重要门槛,因为它综合运用了结构体、指针、动态内存分配等多个核心概念。你感觉吃力,恰好说明这些基础部分还需要进一步巩固。

是的,我强烈建议你先回头巩固一下指针和函数。不过,这不是简单的“再读一遍”,而是有针对性的复习和练习。

具体建议如下:

一、必须巩固的核心知识点
  • 指针:重点理解指针存储的是地址这一本质。特别是结构体指针指针作为函数参数(传地址)。
  • 结构体:熟练掌握结构体的定义和访问成员,特别是用指针访问成员时,-> 运算符的含义。
  • 动态内存管理:彻底弄懂 mallocfree。理解为什么需要动态分配,以及分配后得到的是一块怎样的内存。


二、巩固方法(动手实践)
不要只看书,一定要动手写小程序验证。例如:
  • 写一个函数,交换两个整型变量的值,分别用普通变量和指针作为参数,体会区别。
  • 定义一个简单的结构体(比如学生,包含学号和姓名),写函数分别用结构体变量和结构体指针作为参数来修改其成员。
  • 单独练习 malloc:为一个整数、一个结构体分配内存,赋值,打印,然后 free。务必理解分配后返回的指针是什么。


三、攻克链表的步骤
当你对以上内容感觉比较自信后,再回过头来看链表,并按照以下顺序理解:
  • 先理解“静态”链表:也就是用全局变量或局部变量先创建几个节点,然后把它们手动用指针连起来。这样你可以避开 malloc 的干扰,先搞懂指针是怎么“链”的。
  • 然后加入动态创建:理解“需要的时候才创建一个新节点”这一思想。重点画图!对每个操作(创建、插入、删除),都在纸上画出节点(一个框,里面分两格:数据和next指针)和指针箭头,跟着代码一步步更新箭头指向。这是理解链表最有效的方法,没有之一。
  • 从最简单的操作开始:先只实现“创建头节点”和“遍历打印”,成功后再逐步增加“在末尾添加节点”、“在开头插入节点”等功能。


下面是一个极简的“动态创建链表”示例,它只做两件事:创建一个节点,然后打印它。请你先确保能完全看懂这个:


#include <stdio.h>
#include <stdlib.h>

struct Node {
    int data;
    struct Node* next;
};

int main() {
    // 1. 声明一个头指针,表示链表开始。初始为空链表。
    struct Node* head = NULL;

    // 2. 动态创建一个新节点
    struct Node* newNode = (struct Node*)malloc(sizeof(struct Node));
    newNode->data = 10;       // 给新节点的数据赋值
    newNode->next = NULL;     // 新节点目前不指向任何地方

    // 3. 将这个新节点设置为链表的第一个节点(头节点)
    head = newNode;

    // 4. 现在链表有一个节点了,我们来遍历它(虽然只有一个节点)
    struct Node* current = head; // 用一个临时指针current从头开始
    while (current != NULL) {
        printf("%d -> ", current->data);
        current = current->next; // 移动到下一个节点(这里next是NULL,所以循环结束)
    }
    printf("NULL\n");

    // 5. 释放内存
    free(newNode);
    head = NULL; // 好习惯:释放后指针置NULL,防止成为野指针

    return 0;
}
[/code]

试着理解每一行,然后自己画图:一开始 head 是 NULL。malloc 之后,得到一块内存(新节点),它的地址赋给了 newNode。然后 head = newNode 就是将头指针指向这块内存。遍历时,current 从 head 开始,打印后,current = current->next(即 NULL),循环结束。

当你把这个最简单的例子吃透后,再尝试加入第二个节点(比如在末尾添加),你就会慢慢开窍了。

总结
链表是检验你对指针和内存理解程度的“试金石”。感觉吃力是好事,它逼着你回头把基础打得更牢。按照上面的步骤,放慢速度,多画图,多写小程序验证,你一定能跨过这个坎。加油!

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-12-3 14:21

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表