用链表的详解和综合应用——实现链表的创建、输出、删除及添加结点(C语言)

发布于:2024-12-21 ⋅ 阅读:(15) ⋅ 点赞:(0)

在这里插入图片描述

👋 欢迎来到C语言编程小天地!

链表 是一种非常重要的数据结构,广泛应用于内存管理、队列、栈以及图的表示等领域。掌握链表的基本操作——创建、输出、删除和添加结点,将为你打下坚实的编程基础。今天,我们将用 C 语言来实现链表的基本操作,并通过实际代码示例帮助你更好地理解链表的工作原理。🎯


🌟 本文重点

  1. 链表的创建
  2. 链表的输出
  3. 删除链表中的指定结点
  4. 向链表中添加新结点
  5. 通过文件输入数据来创建链表

🔍 1. 链表的结构体定义与基本操作

C 语言 中,链表是通过指针来实现的,每个结点包含数据和指向下一个结点的指针。

1.1 结构体定义

struct student {
    long num;           // 学生编号
    char name[20];      // 学生姓名
    int grade;          // 学生成绩
    struct student *next; // 指向下一个学生结点的指针
};

结构体 student 中包含了学生的信息和一个指向下一个结点的指针 next,这个指针使得学生的数据形成了链表的结构。


🔍 2. 链表创建与输入数据

我们可以通过两种方式来输入数据:

  • 直接手动输入数据
  • 通过文件读取数据

2.1 直接手动输入数据

在这一部分,我们通过手动输入学生的编号、姓名和成绩来创建链表。

struct student *creat(void) {
    struct student *p1, *p2, *head;
    int n = 0;
    head = NULL;
    p1 = p2 = (struct student*)malloc(size);
    
    // 输入第一个学生信息
    scanf("%ld %s %d", &p1->num, p1->name, &p1->grade);
    
    while (p1->num != 0) {
        n = n + 1;
        if (n == 1) head = p1;
        else p2->next = p1;
        
        p2 = p1;
        p1 = (struct student*)malloc(size);
        
        // 输入下一个学生信息
        scanf("%ld %s %d", &p1->num, p1->name, &p1->grade);
    }
    
    p2->next = NULL;
    return head;
}

在这里,creat 函数通过循环输入每个学生的数据,并将每个学生的 next 指针连接到下一个学生,直到输入的学生编号为 0,标志着输入结束。注意,链表的头指针 head 用于返回整个链表的起始位置。


2.2 利用文件读取数据

在实际应用中,数据通常存储在文件中,我们可以从文件中读取数据并创建链表。

struct student* creat(void) {
    struct student* p1, * p2, * head;
    int n = 0;
    head = NULL;
    p1 = p2 = (struct student*)malloc(size);
    
    FILE *fp;
    fp = fopen("D:\\桌面\\成绩.txt", "r");  // 打开文件
    
    if (fp == NULL) {
        printf("Can't open this file\n");
        exit(0);
    }
    
    // 从文件读取学生信息
    fscanf(fp, "%ld %s %d", &p1->num, p1->name, &p1->grade);
    
    while (p1->num != 0) {
        n = n + 1;
        if (n == 1) head = p1;
        else p2->next = p1;
        
        p2 = p1;
        p1 = (struct student*)malloc(size);
        
        // 从文件中读取下一个学生信息
        fscanf(fp, "%ld %s %d", &p1->num, p1->name, &p1->grade);
    }
    
    fclose(fp);  // 关闭文件
    p2->next = NULL;
    return head;
}

这里我们打开一个名为 "成绩.txt" 的文件,通过 fscanf 从文件中逐行读取学生的编号、姓名和成绩,并将数据添加到链表中。


🔍 3. 链表的基本操作

3.1 输出链表内容

我们可以使用 print 函数来遍历链表并输出每个学生的信息。

void print(struct student *head) {
    struct student *p = head;
    while (p != NULL) {
        printf("%ld %s %d\n", p->num, p->name, p->grade);
        p = p->next;
    }
}

print 函数遍历链表,依次输出每个学生的信息,直到链表结束(即 p == NULL)。


3.2 删除链表中的指定结点

删除链表中的结点是一项常见操作,通常通过遍历链表找到指定结点,并将其从链表中移除。

struct student* del(struct student *head, long num) {
    struct student *p1, *p2;
    p1 = head;
    
    if (head == NULL) {
        printf("List is empty\n");
        return head;
    }
    
    while (p1 != NULL && p1->num != num) {
        p2 = p1;
        p1 = p1->next;
    }
    
    if (p1 == NULL) {
        printf("Can't find %ld in the list.\n", num);
    } else {
        if (p1 == head) head = p1->next;
        else p2->next = p1->next;
        
        free(p1);  // 释放内存
        printf("%ld is deleted.\n", num);
    }
    
    return head;
}

这里,我们通过遍历链表找到指定的学生编号 num,如果找到则删除该结点,若未找到则输出错误信息。


3.3 添加新结点到链表中

向链表中添加结点通常有两种情况:添加到链表头部或链表尾部,或者按照某种顺序(如按编号排序)插入。

struct student* add(struct student *head, struct student *stu) {
    struct student *p1, *p2;
    p1 = head;
    
    // 查找插入位置
    while (p1 != NULL && p1->num < stu->num) {
        p2 = p1;
        p1 = p1->next;
    }
    
    // 插入新结点
    if (p1 == head) {
        stu->next = head;
        head = stu;
    } else {
        stu->next = p1;
        p2->next = stu;
    }
    
    return head;
}

这里我们将新结点 stu 插入到合适的位置,保持链表的顺序。


🌟 总结

  1. 链表是一种非常重要的动态数据结构,适合在需要频繁插入和删除的场景中使用。
  2. 基本操作:链表的基本操作包括创建、输出、删除和添加结点。这些操作是链表的核心,也是学习链表时的基础。
  3. 实践应用:链表不仅用于存储数据,也常用于实现各种数据结构(如栈、队列)和算法。

✨ 进一步探索

  • 链表的变种:如双向链表、循环链表等,它们在不同的场景下具有更高的性能。
  • 链表的应用场景:操作系统的内存管理、数据结构中的栈和队列等。

✍️ 互动交流

  • 👉 你曾经在什么项目中使用过链表?
  • 👉 你如何优化链表的性能?

欢迎在评论区分享你的想法!让我们一起探索链表的更多可能性!🤝


网站公告

今日签到

点亮在社区的每一天
去签到