C语言之双向链表详解及实例代码

C语言之双向链表详解及实例代码

本文将详细讲解C语言中双向链表的实现原理及实例代码,让读者能够深入理解双向链表的基本概念和用法。

什么是双向链表?

双向链表是一种常见的数据结构,它由多个节点构成,每个节点包含两个指针,一个指向前一个节点,一个指向后一个节点,在实际应用中可以用来存储一系列元素,以股票数据为例,将每支股票的编码和名称存储在一个双向链表中,方便快捷地查找和修改。

双向链表的实现原理

在C语言中,我们可以用结构体来定义双向链表中每个节点的数据结构,如下所示:

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

其中,data表示节点中存储的数据,prev指针表示上一个节点的地址,next指针表示下一个节点的地址。当链表为空时,prev和next指针都指向NULL。

插入节点的操作分为两种情况:

  • 在链表头部插入节点
  • 在链表尾部插入节点

可以定义两个函数来分别实现这两种操作:

// 在链表头部插入节点
void insert_at_head(struct Node **head_ref, int new_data) {
    struct Node *new_node = (struct Node*)malloc(sizeof(struct Node));
    new_node->data = new_data;
    new_node->next = (*head_ref);
    new_node->prev = NULL;
    if ((*head_ref) != NULL) {
        (*head_ref)->prev = new_node;
    }
    (*head_ref) = new_node;
}

// 在链表尾部插入节点
void insert_at_end(struct Node **head_ref, int new_data) {
    struct Node *new_node = (struct Node*)malloc(sizeof(struct Node));
    struct Node *last = *head_ref;
    new_node->data = new_data;
    new_node->next = NULL;
    if (*head_ref == NULL) {
        new_node->prev = NULL;
        *head_ref = new_node;
        return;
    }
    while (last->next != NULL) {
        last = last->next;
    }
    last->next = new_node;
    new_node->prev = last;
    return;
}

这两个函数的实现原理都类似,主要是通过malloc函数动态分配内存用来存储新节点的数据,然后判断链表是为空,如果不为空就在头部插入新节点或在尾部插入新节点。

示例说明

下面给出两个示例说明如何使用双向链表来实现对数据的快速查找和修改。

示例1: 股票查询系统

假设我们要实现一个股票查询系统,其中需要存储大量的股票数据,每支股票包括股票代码和股票名称两个信息。我们可以利用双向链表来存储这些数据,然后按照股票代码进行快速查找和修改。实现代码如下:

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

struct Stock {
    char code[10];
    char name[100];
    struct Stock *prev;
    struct Stock *next;
};

void insert_stock(struct Stock **head_ref, char code[], char name[]) {
    struct Stock *new_node = (struct Stock*)malloc(sizeof(struct Stock));
    strcpy(new_node->code, code);
    strcpy(new_node->name, name);
    new_node->next = (*head_ref);
    new_node->prev = NULL;
    if ((*head_ref) != NULL) {
        (*head_ref)->prev = new_node;
    }
    (*head_ref) = new_node;
}

void search_stock(struct Stock **head_ref, char code[]) {
    struct Stock *temp = *head_ref;
    while (temp != NULL) {
        if (strcmp(temp->code, code) == 0) {
            printf("股票代码:%s\n股票名称:%s\n", temp->code, temp->name);
            return;
        }
        temp = temp->next;
    }
    printf("未查找到该股票,请重新输入股票代码!\n");
}

void modify_stock(struct Stock **head_ref, char code[], char name[]) {
    struct Stock *temp = *head_ref;
    while (temp != NULL) {
        if (strcmp(temp->code, code) == 0) {
            strcpy(temp->name, name);
            printf("股票信息修改成功!\n");
            return;
        }
        temp = temp->next;
    }
    printf("未查找到该股票,请重新输入股票代码!\n");
}

int main() {
    struct Stock *head = NULL;
    insert_stock(&head, "000001", "平安银行");
    insert_stock(&head, "000002", "万科A");
    insert_stock(&head, "600036", "招商银行");
    insert_stock(&head, "600519", "贵州茅台");
    insert_stock(&head, "601318", "中国平安");
    char code[10]; char name[100];
    printf("请输入要查询的股票代码:");
    scanf("%s", code);
    search_stock(&head, code);
    printf("请输入要修改的股票代码和股票名称:");
    scanf("%s%s", code, name);
    modify_stock(&head, code, name);
    return 0;
}

示例2: 学生信息管理系统

双向链表还可以用来实现学生信息管理系统,在学生信息管理系统中,我们需要将每个学生的信息存储在一个链表中,然后实现对学生信息的更新、删除和查询等操作。实现代码如下:

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

struct Student {
    char name[20];
    int age;
    int id;
    struct Student *prev;
    struct Student *next;
};

void insert_student(struct Student **head_ref, char name[], int age, int id) {
    struct Student *new_node = (struct Student*)malloc(sizeof(struct Student));
    strcpy(new_node->name, name);
    new_node->age = age;
    new_node->id = id;
    new_node->next = (*head_ref);
    new_node->prev = NULL;
    if ((*head_ref) != NULL) {
        (*head_ref)->prev = new_node;
    }
    (*head_ref) = new_node;
}

void search_student(struct Student **head_ref, int id) {
    struct Student *temp = *head_ref;
    while (temp != NULL) {
        if (temp->id == id) {
            printf("学生姓名:%s\n学生年龄:%d\n学生ID:%d\n", temp->name, temp->age, temp->id);
            return;
        }
        temp = temp->next;
    }
    printf("未查找到该学生,请重新输入学生ID!\n");
}

void delete_student(struct Student **head_ref, int id) {
    struct Student *temp = *head_ref;
    while (temp != NULL) {
        if (temp->id == id) {
            if (temp->prev == NULL) {
                *head_ref = temp->next;
                (*head_ref)->prev = NULL;
                free(temp);
                printf("学生信息删除成功!\n");
                return;
            }
            if (temp->next == NULL) {
                temp->prev->next = NULL;
                free(temp);
                printf("学生信息删除成功!\n");
                return;
            }
            temp->prev->next = temp->next;
            temp->next->prev = temp->prev;
            free(temp);
            printf("学生信息删除成功!\n");
            return;
        }
        temp = temp->next;
    }
    printf("未查找到该学生,请重新输入学生ID!\n");
}

int main() {
    struct Student *head = NULL;
    insert_student(&head, "Tom", 18, 1001);
    insert_student(&head, "Jerry", 20, 1002);
    insert_student(&head, "Lucy", 19, 1003);
    insert_student(&head, "Amy", 18, 1004);
    int option, id, age; char name[20];
    while (1) {
        printf("---------------------------\n");
        printf("1.查询学生信息\n2.删除学生信息\n3.退出\n");
        printf("---------------------------\n");
        printf("请选择要执行的操作:");
        scanf("%d", &option);
        switch(option) {
            case 1:
                printf("请输入要查询的学生ID:");
                scanf("%d", &id);
                search_student(&head, id);
                break;
            case 2:
                printf("请输入要删除的学生ID:");
                scanf("%d", &id);
                delete_student(&head, id);
                break;
            case 3:
                printf("退出系统成功!\n");
                return 0;
            default:
                printf("输入错误,请重新输入!\n");
        }
    }
    return 0;
}

总结

本文详细讲解了C语言中双向链表的实现原理及其应用,同时给出了两个实际示例,希望读者通过学习本文,掌握C语言中链表的基本使用方法,加深对链表的理解,有助于提高C语言程序的编写能力。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:C语言之双向链表详解及实例代码 - Python技术站

(0)
上一篇 2023年5月24日
下一篇 2023年5月24日

相关文章

  • C++小游戏tankwar之界面绘制的详细过程

    下面是“C++小游戏tankwar之界面绘制的详细过程”的完整攻略。 界面绘制的流程 初始化SDL 在使用SDL进行图形绘制前,需要进行SDL库的初始化。调用SDL_Init函数即可进行初始化。同时还需要对SDL图形界面进行设置,包括窗口大小、窗口名称等。 SDL_Init(SDL_INIT_VIDEO); SDL_Window* window = SDL_…

    C 2023年5月23日
    00
  • C++实现简单班级成绩管理系统

    C++实现简单班级成绩管理系统攻略 1. 需求分析 在实现班级成绩管理系统前,首先需要明确实现系统的主要功能,如本系统需要实现的功能有:- 添加学生的基本信息,包括学生姓名和学号;- 添加学生成绩信息,包括数学、语文、英语等科目的成绩;- 对学生成绩进行管理,包括查看某个学生的成绩、某个科目的平均成绩、班级总体平均成绩等。 2. 设计思路 本系统的设计思路为…

    C 2023年5月30日
    00
  • C++实现恶搞电脑关机小程序的示例代码

    为了向站点的访问者提供有价值的信息,网站作者在教程中提供了如何使用C++实现恶搞电脑关机小程序的示例代码。下面是实现的完整攻略: 程序简介 首先要了解的是,电脑关机小程序是一种作为开发者与计算机用户之间计算机恶搞竞技的一个漏洞程序,是一种不被计算机用户接受的。 通常,这种程序被认为是具有伤害性的程序,因此,如果不了解该程序的实现,其使用方法和操作规则,则不要…

    C 2023年5月23日
    00
  • springboot-dubbo cannot be cast to问题及解决

    “springboot-dubbo cannot be cast to”问题往往会在Spring Boot项目中使用Dubbo时出现。该问题出现的原因往往是因为Dubbo的版本与Spring Boot的版本不兼容导致Dubbo不能正确地使用Spring Boot的自动配置机制。下面将详细介绍该问题的解决方法。 步骤1:检查Dubbo版本与Spring Boo…

    C 2023年5月23日
    00
  • 融会贯通C++智能指针教程

    下面我来详细讲解融会贯通C++智能指针教程的完整攻略。 一、什么是C++智能指针 C++智能指针(Smart Pointer)是一个封装了RAII(Resource Acquisition Is Initialization,资源获取即初始化)和指针语义的类模板,它会在对象生命结束时自动释放所持有的资源。智能指针可以有效地解决代码中因忘记释放资源而导致的内存…

    C 2023年5月22日
    00
  • c#基础——了解程序结构

    C#基础——了解程序结构 C#是一种现代的、通用的、面向对象的编程语言。在学习C#编程语言时需要了解其基本的程序结构,其中包括C#程序中代码的组织方式以及控制其执行流程的结构和元素。 基本程序结构 C#程序由以下几个基本元素组成: 命名空间(Namespace) 类(Class) 方法(Method) 语句(Statement) 表达式(Expression…

    C 2023年5月23日
    00
  • C++实现读写文件的示例代码

    下面是关于C++实现读写文件的示例代码的攻略。 一、前置知识 在开始写C++读写文件的代码之前,你需要有一些基本的前置知识: 文件指针(FILE*):表示文件句柄,用于打开、关闭文件,以及进行读、写、定位等操作。 文件操作模式:用于指定打开文件的模式,例如读取、写入、追加等。 文件读写函数:主要有fscanf、fprintf、fgets、fputs、frea…

    C 2023年5月24日
    00
  • C 环境设置

    C 环境设置完整使用攻略 什么是 C 环境 C 环境包括编译器、链接器和调试器等,是用来开发 C 语言程序的软件集合。 C 环境设置步骤 1. 下载安装 C 语言编译器 常见的 C 语言编译器有 GCC 和 Clang 等,可根据自己的需求选择合适的编译器并下载安装。以 GCC 编译器为例,下载安装步骤如下: 在官网(https://gcc.gnu.org/…

    C 2023年5月10日
    00
合作推广
合作推广
分享本页
返回顶部