C语言超详细i讲解双向链表

C语言超详细讲解双向链表

什么是双向链表

双向链表是一个动态数据结构,它由一系列的节点构成,每个节点分为三部分:数据域、指向前驱节点的指针和指向后继节点的指针。双向链表支持在任意位置插入或删除节点,与数组相比,它具有更好的灵活性和效率。

如何实现双向链表

定义节点

typedef struct DNode {
    int data;
    struct DNode* prev;
    struct DNode* next;
}DNode, *DLinkList;

创建节点

//创建节点
DNode* create_node(int data) {
    DNode* node = (DNode*)malloc(sizeof(DNode));
    node->data = data;
    node->prev = NULL;
    node->next = NULL;
    return node;
}

插入节点

头部插入节点

//头部插入节点
void insert_head(DLinkList* head, DNode* node) {
    if (node == NULL) {
        return;
    }
    node->next = *head;
    node->prev = NULL;
    if (*head != NULL) {
        (*head)->prev = node;
    }
    *head = node;
}

尾部插入节点

//尾部插入节点
void insert_tail(DLinkList* head, DNode* node) {
    if (node == NULL) {
        return;
    }
    if (*head == NULL) {
        *head = node;
        node->prev = NULL;
        node->next = NULL;
    }
    else {
        DNode* p = *head;
        while (p->next != NULL) {
            p = p->next;
        }
        node->prev = p;
        node->next = NULL;
        p->next = node;
    }
}

按位置插入节点

//按位置插入节点
void insert_pos(DLinkList* head, DNode* node, int pos) {
    if (node == NULL) {
        return;
    }
    if (*head == NULL || pos <= 1) {
        node->prev = NULL;
        node->next = *head;
        if (*head != NULL) {
            (*head)->prev = node;
        }
        *head = node;
    }
    else {
        DNode* p = *head;
        int i = 1;
        while (p->next != NULL && i < pos-1) {
            p = p->next;
            i++;
        }
        node->prev = p;
        node->next = p->next;
        if (p->next != NULL) {
            p->next->prev = node;
        }
        p->next = node;
    }
}

删除节点

删除头部节点

//删除头部节点
void delete_head(DLinkList* head) {
    if (*head != NULL) {
        DNode* p = *head;
        *head = (*head)->next;
        if (*head != NULL) {
            (*head)->prev = NULL;
        }
        free(p);
    }
}

删除尾部节点

//删除尾部节点
void delete_tail(DLinkList* head) {
    if (*head != NULL) {
        DNode* p = *head;
        while (p->next != NULL) {
            p = p->next;
        }
        if (p->prev != NULL) {
            p->prev->next = NULL;
        }
        else {
            //删除头部节点
            *head = NULL;
        }
        free(p);
    }
}

按位置删除节点

//按位置删除节点
void delete_pos(DLinkList* head, int pos) {
    if (*head != NULL && pos >= 1) {
        if (pos == 1) {
            //删除头部节点
            delete_head(head);
        }
        else {
            DNode* p = *head;
            int i = 1;
            while (p->next != NULL && i < pos) {
                p = p->next;
                i++;
            }
            if (i == pos && p != NULL) {
                if (p->prev != NULL) {
                    p->prev->next = p->next;
                }
                if (p->next != NULL) {
                    p->next->prev = p->prev;
                }
                free(p);
            }
        }
    }
}

示例说明

插入节点示例

//创建双向链表
DLinkList head = NULL;
int n, i, data;
printf("请输入节点个数:");
scanf("%d", &n);
for (i = 1; i <= n; i++) {
    printf("请输入第%d个节点的数据:", i);
    scanf("%d", &data);

    //创建节点
    DNode* node = create_node(data);

    //头部插入节点
    //insert_head(&head, node);

    //尾部插入节点
    insert_tail(&head, node);

    //按位置插入节点
    //insert_pos(&head, node, i);
}

//遍历双向链表
DNode* p = head;
printf("双向链表元素:");
while (p != NULL) {
    printf("%d ", p->data);
    p = p->next;
}

删除节点示例

//创建双向链表
DLinkList head = NULL;
int n, i, data;
printf("请输入节点个数:");
scanf("%d", &n);
for (i = 1; i <= n; i++) {
    printf("请输入第%d个节点的数据:", i);
    scanf("%d", &data);

    //创建节点
    DNode* node = create_node(data);

    //头部插入节点
    insert_head(&head, node);

    //尾部插入节点
    //insert_tail(&head, node);

    //按位置插入节点
    //insert_pos(&head, node, i);
}

//删除双向链表中第3个节点
delete_pos(&head, 3);

//遍历双向链表
DNode* p = head;
printf("双向链表元素:");
while (p != NULL) {
    printf("%d ", p->data);
    p = p->next;
}

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:C语言超详细i讲解双向链表 - Python技术站

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

相关文章

  • 易语言中Com对象的简单调用方法

    易语言中Com对象的简单调用方法 在易语言中,我们可以通过Com组件来访问外部的COM对象。COM对象,是一种组件对象模型(Component Object Model)。COM对象可以通过易语言Com组件来进行简单的调用和使用。 Com组件的基本使用 首先,我们需要在易语言中添加Com组件。在IDE中,打开工具箱视图,右键单击“常用控件”节点,选择“添加\…

    C 2023年5月22日
    00
  • 如何在c++中实现字符串分割函数split详解

    如何在C++中实现字符串分割函数split详解 简介 字符串分割是比较常见的字符串处理方式之一,常用于将一个字符串按照特定的分隔符分割成若干个子串。在C++中,实现字符串分割可以通过一些STL容器和标准库函数来完成。 实现 方法一:使用stringstream stringstream是C++ STL库中用来进行字符串流处理的一个类。使用这个类可以将一个字符…

    C 2023年5月23日
    00
  • 逍遥自在学C语言 | 关系运算符

    前言 一、人物简介 第一位闪亮登场,有请今后会一直教我们C语言的老师 —— 自在。 第二位上场的是和我们一起学习的小白程序猿 —— 逍遥。 二、构成和表示方式 关系运算符的作用是判断符号两边大小的关系 C语言中的关系运算符主要有六个,如下表所示 运算符 名称 示例 描述 == 等于 a == b 判断a是否等于b != 不等于 a != b 判断a是否不等于…

    C语言 2023年4月17日
    00
  • FFmpeg开发笔记(二)搭建Windows系统的开发环境

    由于Linux系统比较专业,个人电脑很少安装Linux,反而大都安装Windows系统,因此提高了FFmpeg的学习门槛,毕竟在Windows系统搭建FFmpeg的开发环境还是比较麻烦的。不过若有已经编译好的Windows版本FFmpeg开发包,那就免去了繁琐的Windows编译过程,所以直接安装已编译的FFmpeg开发包,还是相对容易的。在Windows系…

    C 2023年4月30日
    00
  • 三星C480FW打印机出现脱机问题怎么复位?

    三星C480FW打印机出现脱机问题如何复位? 如果你的三星C480FW打印机出现了脱机(Offline)问题,这可能是由于打印机连接的USB或无线网络中的问题导致。以下是复位打印机的步骤: 1. 确认网络连接 首先,你需要确保打印机已经正确连接到网络,并且网络连接是可靠的。 网络打印机 如果你的三星C480FW打印机是连接到网络的,你可以按照以下步骤来确保打…

    C 2023年5月23日
    00
  • Linux C 后台服务程序单进程控制的实现

    实现 Linux C 后台服务程序单进程控制的攻略,主要包括以下几个步骤: 创建守护进程 首先,我们需要编写一个程序,将其作为守护进程来运行。守护进程的作用是在后台运行,独立于用户的终端,并拥有自己的会话和进程组。我们需要遵循以下步骤来创建守护进程: 1)fork 一个子进程。 2)在子进程中调用 setsid 函数创建新会话。 3)再次 fork 一个子进…

    C 2023年5月23日
    00
  • 使用系统默认的备份还原注册表的图文教程

    使用系统默认的备份还原注册表的图文教程 首先,备份注册表非常重要。在我们进行一些重要的系统修改时,需要备份注册表以防万一。系统默认的备份功能十分实用,可以快速地恢复到之前的状态。以下是使用系统默认的备份还原注册表的步骤: 打开“运行”窗口 我们可以使用快捷键 Win + R 打开运行窗口。 输入 regedit 命令 在弹出的运行窗口中,输入 regedit…

    C 2023年5月23日
    00
  • C++超详细讲解函数对象

    C++超详细讲解函数对象 函数对象,也称为仿函数,是一种重载了()运算符并可以像函数一样被调用的对象。在C++中,函数对象可以看作是一个类,它可以像一个函数一样去调用。 为什么需要函数对象? 在许多场景中,我们需要对容器(如vector、map等)中的元素进行排序、查找或者进行相关的算术计算。这个时候我们常常使用STL中提供的STL算法函数,其中就用到了函数…

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