首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

C delete函数中的循环双向链表

C语言中的delete函数通常用于删除循环双向链表中的节点。循环双向链表是一种数据结构,它由多个节点组成,每个节点包含一个数据元素和两个指针,分别指向前一个节点和后一个节点。循环双向链表的特点是首尾节点相连,形成一个环。

在delete函数中,我们需要完成以下步骤来删除链表中的节点:

  1. 首先,判断链表是否为空。如果链表为空,则无法删除节点,直接返回。
  2. 然后,判断待删除节点是否是链表的唯一节点。如果是唯一节点,则将链表置为空。
  3. 如果待删除节点不是唯一节点,我们需要找到待删除节点的前一个节点和后一个节点。
  4. 将待删除节点的前一个节点的next指针指向待删除节点的后一个节点。
  5. 将待删除节点的后一个节点的prev指针指向待删除节点的前一个节点。
  6. 最后,释放待删除节点的内存空间。

以下是一个示例代码,演示了如何在C语言中实现delete函数来删除循环双向链表中的节点:

代码语言:txt
复制
#include <stdio.h>
#include <stdlib.h>

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

void delete(Node** head, int value) {
    if (*head == NULL) {
        printf("链表为空,无法删除节点。\n");
        return;
    }

    Node* current = *head;
    Node* prev = NULL;

    // 寻找待删除节点
    while (current->data != value) {
        if (current->next == *head) {
            printf("未找到值为%d的节点。\n", value);
            return;
        }

        prev = current;
        current = current->next;
    }

    // 如果待删除节点是唯一节点
    if (current->next == *head && prev == NULL) {
        *head = NULL;
        free(current);
        return;
    }

    // 如果待删除节点是头节点
    if (current == *head) {
        prev = *head;
        while (prev->next != *head)
            prev = prev->next;
        *head = (*head)->next;
        prev->next = *head;
        (*head)->prev = prev;
        free(current);
    }

    // 如果待删除节点是尾节点
    else if (current->next == *head) {
        prev->next = *head;
        (*head)->prev = prev;
        free(current);
    }

    // 如果待删除节点是中间节点
    else {
        Node* temp = current->next;
        prev->next = temp;
        temp->prev = prev;
        free(current);
    }
}

int main() {
    Node* head = NULL;
    Node* node1 = (Node*)malloc(sizeof(Node));
    Node* node2 = (Node*)malloc(sizeof(Node));
    Node* node3 = (Node*)malloc(sizeof(Node));

    node1->data = 1;
    node2->data = 2;
    node3->data = 3;

    head = node1;
    node1->prev = node3;
    node1->next = node2;
    node2->prev = node1;
    node2->next = node3;
    node3->prev = node2;
    node3->next = node1;

    printf("删除前的链表:\n");
    Node* current = head;
    do {
        printf("%d ", current->data);
        current = current->next;
    } while (current != head);
    printf("\n");

    delete(&head, 2);

    printf("删除后的链表:\n");
    current = head;
    do {
        printf("%d ", current->data);
        current = current->next;
    } while (current != head);
    printf("\n");

    return 0;
}

这段代码演示了如何删除循环双向链表中的节点。首先创建了一个包含3个节点的循环双向链表,然后调用delete函数删除了值为2的节点,最后打印删除后的链表。

在腾讯云的产品中,与循环双向链表相关的产品可能是较为基础的云计算服务,如云服务器、云数据库等。具体的产品选择和使用需根据实际需求和场景来确定。

页面内容是否对你有帮助?
有帮助
没帮助

相关·内容

循环双向链表的

链表的使用 初级版:   结构体   struct data{     struct data* next;     int data;   };   head=p1->p2->p3->p4->NULL...  需要删除节点p3时就很麻烦,我们需要从头去遍历,找到next指针为p3时将next指针指向p3的next;   为此方便起见,我们可以使用双向链表进行实现。...内核中是这样处理的,   创建一个双向循环链表   =>headp1p2p3p4=   向链表中指定位置插入节点   原有链prenext   这也是最基本的插入节点的方法...}   根据插入节点的方式写删除节点就容易的多了   _del(struct data * pre,struct data * next){     pre->next = next;     next...}   没有做释放的代码,创建链的时候需要用malloc去创建,内核中的双向链表正是这么实现的,   特别容易书写,不太会产生副作用。二级指向是在太难理解了

29010

循环链表的实现_建立双向循环链表

循环链表   循环链表是一个收尾相接的链表,将单链表的最后一个指针域改由NULL改为指向表头结点这就是单链式的循环链表,并称为循环单链表   带头结点的循环单链表的各种操作的算法实现与带头结点单链表的算法实现类似...单链表中的判别条件为p!=NULL或p->next!=NULL,而单循环链表判别条件是p!=L或p->next!=L   在循环单链表中附设尾指针有时候比附设头指针更简单。...如:在用头指针的循环单链表中找a1的时间复杂度是O(1),找an需要从头找到尾,时间复杂度是O(n),如果用为指针rear,找开始结点和终端结点的存储位置分别是rear->next->next和rear...    方法一:先找到两个链表LA,LB的表尾,分别用p,q指向它,然后将第一个链表的表尾与第二个链表的第一个结点连起来,修改第二个表的尾q,使它的链域指向第一个表头 //头指针合并循环链表 #include...;//返回新的链表的尾指针 }   循环链表求长度 #include #define len sizeof(Node) #include typedef struct

75220
  • 单循环链表-带头双向循环链表的实现

    带头双向循环链表   前言   对于链表来说,不只有单链表这一个品种;   链表有很多种形态   按方向分:单向、双向   按带不带头:带头、不带头   按循环:循环、不循环   1、单向或则双向:...今天我们就来学习一下结构最复杂的带头双向循环链表!!!...;   虽然名字听上去比较复杂单循环链表,但是实现起来比单链表(全名:不带头、不循环、单向链表)更加简单,也不需要过多考虑特殊情况;   两种链表的比较:(上面是单链表,下面是带头双向循环链表)   结构分析...  首先链表的头节点是不存储有效数据的(该节点被称为哨兵位),其次我们只需要知道改头节点的指针就能找到整个链表单循环链表,并且便于对整个链表进行维护;   当然既然是双向的嘛,那节点一定有个指针域指向前一个节点...  由于是循环的,哨兵位的前一个节点就是尾节点,同时尾节点的前一个节点我们也不用遍历,可以很轻松的拿到:    // 双向链表尾删 void ListPopBack(ListNode

    61130

    1.Go-copy函数、sort排序、双向链表、list操作和双向循环链表

    (1)双向链表的结构 ?...双向链表结构中元素在内存中不是紧邻空间,而是每个元素中存放上一个元素和后一个元素的地址 第一个元素称为(头)元素,前连接(前置指针域)为nil 最后一个元素称为 尾(foot)元素,后连接(后置指针域)...  双向链表的缺点  链表增加了元素的指针域,空间开销比较大 遍历时跳跃性查找内容,大量数据遍历性能低  (2)双向链表容器List 在Go语言标准库的container/list包提供了双向链表List...)) 1.5.双向循环列表 (1)循环链表特点是没有节点的指针域为nil,通过任何一个元素都可以找到其它元素 环形链表结构如下 ?...双向循环链表和双向链表区别 双向循环链表没有严格意义上的头元素和尾元素 没有元素的前连接和后连接为nil 一个长度为n的双向循环链表,通过某个元素向某个方向移动,在查找最多n-1次,一定会找到另一个元素

    81430

    【链表】双向循环带头链表-增-删-查(C语言)

    ---- ---- 单链表存在的缺陷: 不能从后往前走, 找不到他的前驱, 指定位置 删除 增加 尾删 都要找前一个,时间复杂度都是O(n) ---- 针对上面的这些缺陷的解决方案——双向链表。...---- 实际中要实现的链表的结构非常多样,以下情况组合起来就有8种链表结构: 单向、双向 带头、不带头——带哨兵位的头结点,这个结点不存储有效数据,好处是什么?...循环、非循环 ---- 无头单向非循环:结构简单,一般不会单独用来存数据,实际中更多是作为其他数据结构的子结构,如哈希桶,图的邻接表等,另外这种数据结构在笔试面试中出现很多。...带头双向循环链表:结构最复杂,一般用在单独存储数据。实际中使用的链表数据结构,都是带头循环双向链表,另外,这个结构虽然复杂,但是使用代码代码实现的以后会发现结构带来许多优势,实现反而简单了。...空 return true; } else { //不为空 return false; } } 优化 为了更快的实现一个双向循环的带头链表,我们可以直接利用Insert和Erase。

    29400

    DS:带头双向循环链表的实现

    虽然有这么多的链表的结构,但是我们实际中最常用还是两种结构: 单链表(不带头单向不循环链表)和 双向链表(带头双向循环链表) 1. 无头单向非循环链表:结构简单,⼀般不会单独⽤来存数据。...实际中更多是作为其他数据结 构的⼦结构,如哈希桶、图的邻接表等等。另外这种结构在笔试⾯试中出现很多。 2. 带头双向循环链表:结构最复杂,⼀般⽤在单独存储数据。...二、带头双向循环链表的结构 带头链表⾥的头节点,实际为“哨兵位”,哨兵位节点不存储任何有效元素,只是站在这⾥“放哨的” “哨兵位”存在的意义:遍历循环链表避免死循环。...三、双向链表结点结构体的创建 与单链表结点结构体不同的是,双向链表的结点结构体多了一个前驱结点!!...=NULL必须在主函数中去使用,所以我们在调用销毁链表的函数的时候,别忘记了phead=NULL!!

    12310

    【初阶数据结构】——带头双向循环链表(C描述)

    但其实,最常用的还是两种结构: 上一篇文章我们已经学了单链表(不带头),那这篇文章,我们就来学习一下带头双向循环链表。 带头双向循环链表实现 1....结构介绍 首先,从结构上来说,带头双向循环链表是结构最复杂的: 它带哨兵位的头结点,还是双向的,还循环。 带头双向循环链表一般用来单独存储数据。...实际中使用的链表数据结构,都是带头双向循环链表。 对于带头双向循环链表来说: 首先它是带哨兵位的头结点的,也就是说,它是空表状态的时候,也是有一个头结点存在的(当然它不存储有效数据)。...接下来我们就来实现一下对应的接口函数。 2. 结点创建 带头双向循环链表的每个结点:一个数据域,两个指针域。...那为什么我们今天实现的带头双向循环链表还要搞一个初始化的函数呢?

    10910

    带头双向循环链表增删查改实现(C语言)

    带头双向循环链表 结点结构与头结点的创建 头插尾插 打印链表 头删与尾删 链表的查找 在pos的前面进行插入与删除pos位置的结点 销毁链表 完整代码 结点结构与头结点的创建 创建两个源文件和一个头文件...test.c linked_list.c linked_list.h 带头双向循环链表,那么,结点的结构就要有两个指针域,分别指向前一个结点和后一个结点。...这里尾插就很方便了,不像之前需要遍历找尾,因为是循环链表,尾的next就是头结点。 当然这里要先写一个创建新结点的函数。...打印链表 这里就要遍历链表了,因为是循环结构,所以结尾就不用空指针进行判断了。...printf("\n"); } 头删与尾删 删除的话,我们需要写一个函数判断链表中是否还有数据,如果只剩一个头结点就不能继续删除了。

    57300

    TencentOS-tiny中双向循环链表的实现及使用

    什么是双向循环链表 双向链表也是链表的一种,区别在于每个节点除了后继指针外,还有一个前驱指针,双向链表的节点长下面这样: [c7p68g2ngv.png] 由这种节点构成的双向链表有两种分类:按照是否有头结点可以分为两种...本文讨论的是不带头节点的双向循环链表,如下图: [qowp0vrk7c.png] 2. 双向循环链表的实现 TencentOS-tiny中的双向链表实现在tos_list.h中。 2.1....插入前的双向循环链表如下: [12x9hk0jf4.png] 插入后的双向循环链表如下: [g8b3e5w8ks.png] 图中的四个插入过程分别对应代码中的四行代码。...双向链表使用示例 3.1. 实验内容 本实验会创建一个带有10个静态结点的双向链表,每个新的自定义节点中有一个数据域,存放一个uint8_t类型的值,有一个双向链表节点,用于构成双向链表。 3.2....] 新建一个任务用来测试,编写如下的任务入口函数: #define LIST_LEN 10 void double_list_test(void *args) { int i; /* 用于挂载自定义节点中的双向节点

    1.1K1313

    【数据结构】双向带头循环链表(c语言)(附源码)

    双向带头循环链表:通常称为双向链表,它的结构较为复杂,实际使用中用于单独存放数据。虽然它的结构比较复杂,但是它的方法执行效率要高于单链表。 接下来,就让我们学习并尝试实现双向带头循环链表。...1.双向带头循环链表的概念和结构定义 双向带头循环链表(双向链表)有三个关键点: 1.双向:不同于单链表,双向链表的节点的指针域附带有两个指针,分别指向其前驱节点和后继节点,这便于我们更灵活地访问链表元素...3.循环:也就是说链表尾部不指向空指针,而是指向头部的节点,形成一个“环”状结构。 而对于单链表,由于不具备这三个特性,所以在运行效率上要低于双向链表。...struct ListNode* next;//指向前驱节点的指针 struct ListNode* prev;//指向后继节点的指针 }LTNode; 2.双向带头循环链表的实现...cur = NULL; free(*pphead);//删除头节点 *pphead = NULL; } 总结 今天我们学习了双向带头循环链表的概念以及功能实现。

    15010

    【数据结构】C语言实现带头双向循环链表

    带头双向循环链表:结构最复杂,一般用在单独存储数据。实际中使用的链表数据结构,都是带头双向循环链表。...在初始状态时,双向链表为空,这里的空指的是只有一个哨兵位,而哨兵位节点是不能被操作的,即哨兵位不能被改变。 要用C语言先定义一个包含哨兵位的双向循环链表。...用代码实现双向循环链表 同之前的单链表一样我们用三个文件来实现, List.h用来实现函数声明,List.c用来实现相关函数,test.c用来测试代码。...3.2.1 尾插分析 尾插就是在节点之后插入新节点,值得注意的是,在双向循环链表中要实现尾插就是在哨兵位的前面插入节点。...5,6,7 3.4 双向循环链表的尾删 3.4.1 尾删分析 我们用del来表示要删除的节点,要实现尾巴删除,就要先确定删除节点的位置,而我们知道这是在双向循环链表中,哨兵位的前一个节点就是del

    17010

    【数据结构】—带头双向循环链表的实现(完美链表)

    目录 前言 链表的实现 新节点的创建 链表初始化 尾插与尾删 头插与头删 查找数据 在任意位置的插入与删除 链表的销毁 总结 前言 链表结构一共有八种形式,在前面的文章里已经讲完了不带头单向非循环链表的实现...,但是我们发现该链表实现尾插与尾删时比较麻烦,要先从头节点进行遍历,找到尾节点,时间复杂度为O(N),而本次所讲的带头双向循环单链表,则可以直接找到尾节点。...* _next;//指向下一个节点的指针 struct ListNode* _prev;//指向前一个节点的指针 }ListNode; 新节点的创建 这里由于后面的插入都需要进行创建新节点,所以我们把它写成一个函数...空表状态下应该是如下图这样的,因为它是带头的循环链表,所以第一个节点不用来存储有效数据。...真的是链表中的完美存在,不过在进行删除操作时,一定要考虑空表情况下不可进行删除。因此要加个assert进行断言。

    61820

    双向带头循环链表的(增删查改)的实现

    一、双向带头循环链表 构成 二、双向带头循环链表的实现 1.函数的定义和结构体的创建——list.h #include #include #include双向带头循环链表与单链表的传递参数区别 1.单链表: 单链表因为没有头节点的存在,导致在尾插时会改变链表的头节点 所以需要传递二级指针的地址即二级指针。...2.双向带头循环链表: 初始化头指针时,是需要传递二级指针,只不过用函数传回结构体指针的方式代替了, 而在后续接口则不需要传递二级指针,因为后来都是在头指针的基础上进行的,而头节点本身不会存储有效数据,...4.双向带头循环链表的接口 1.初始化 struct listNode* stackinit()//初始化头节点 { struct listNode* phead = (struct listNode...(2)在动态开辟空间时,会造成一定的浪费。 2.链表: 逻辑上是来连续的,物理上的不连续。

    40540

    数据结构 | TencentOS-tiny中的双向循环链表的实现及使用

    什么是双向循环链表 双向链表也是链表的一种,区别在于每个节点除了后继指针外,还有一个前驱指针,双向链表的节点长下面这样: ?...由这种节点构成的双向链表有两种分类:按照是否有头结点可以分为两种,按照是否循环可以分为两种。 本文讨论的是不带头节点的双向循环链表,如下图: ?...相较于其他形式的链表,双向循环链表的添加节点,删除节点,遍历节点都非常的简单。 2. 双向循环链表的实现 TencentOS-tiny中的双向链表实现在tos_list.h中。 2.1....插入前的双向循环链表如下: ? 插入后的双向循环链表如下: ? 图中的四个插入过程分别对应代码中的四行代码。...新建一个任务用来测试,编写如下的任务入口函数: #define LIST_LEN 10 void double_list_test(void *args) { int i; /* 用于挂载自定义节点中的双向节点

    91020

    Android中的双向链表「建议收藏」

    1.看源代码必须搞懂Android的数据结构。在init源代码中双向链表listnode使用非常多,它仅仅有prev和next两个指针,没有不论什么数据成员。...假设我们手上有个宿主结构,那当然知道了它的某个listnode在哪里,从而以此为參数调用list_add和list_del函数。但是,反过来。...当我们顺着链表取得当中一项的listnode结构时,又如何找到其宿主结构呢?在listnode结构中并没有指向其宿主结构的指针啊。毕竟。我们我真正关心的是宿主结构。而不是连接件。...以下是取自mm/page_alloc.c中的一行代码: page = memlist_entry(curr, struct page, list); 这里的memlist_entry将一个list_head...node节点,list始终指向双向链表的头部(这个头部仅仅含有prev/next) void list_add_tail(listnode *list,listnode *node) {

    72010

    详解双向链表的基本操作(C语言)

    所以,从双向链表中的任意一个结点开始,都可以很方便地访问它的前驱结点和后继结点。下图为双向链表的结构图。 ?   ...从上中可以看到,双向链表中各节点包含以下 3 部分信息: 指针域:用于指向当前节点的直接前驱节点; 数据域:用于存储数据元素。 指针域:用于指向当前节点的直接后继节点; ?...双向循环链表的定义:   双向链表也可以进行首尾连接,构成双向循环链表,如下图所示 在创建链表时,只需要在最后将收尾相连即可(创建链表代码中已经标出)。其他代码稍加改动即可。 ?...;   这里给出创建双向链表的 C 语言实现代码: #define MAX 100 Node *CreatNode(Node *head) { head=(Node*)malloc(sizeof.../*更新函数,其中,add 表示更改结点在双链表中的位置,newElem 为新数据的值*/ Node *ModifyList(Node * p,int add,int newElem) { Node

    2K31

    单循环链表-这么好的单链表结构怎么能不会呢?带哨兵位头节点双向循环链表

    带头循环双向链表   优势是什么   先看看长啥样子   每一个节点都记录该节点的前后的节点,这会有什么好处呢?   ...带哨兵位头节点双向循环链表的基本操作   这一次,会写的规范一点。   准备3个文件,一个头件,一个链表操作文件,一个主函数所在的文件,和通讯录那一篇设计是一样的。   ...H:带头,D:双向,Loop:循环,List:链表       #include #include #include typedef int LTDataType;...有下面两种形式,但当链表为空的时候,是成环的,建议用下面一种。   这样设计以后函数形参中的指针是不可为NULL的,可以加一个assert判断一下。   ...不能删除头节点单循环链表,不然主函数中的头指针会非法访问。

    32610

    Linux内核中双向链表的经典实现

    概要 本文对双向链表进行探讨,介绍的内容是Linux内核中双向链表的经典实现和用法。其中,也会涉及到Linux内核中非常常用的两个经典宏定义offsetof和container_of。...Linux中双向链表的经典实现 1.Linux中双向链表介绍 Linux双向链表的定义主要涉及到两个文件: include/linux/types.h include/linux/list.h Linux...中双向链表的使用思想 它是将双向链表节点嵌套在其它的结构体中;在遍历链表的时候,根据双链表节点的指针获取"它所在结构体的指针",从而再获取数据。...在linux中,以""开头的函数意味着是内核的内部接口,外部不应该调用该接口。...3.Linux中双向链表的使用示例 双向链表代码(list.h): 1 #ifndef _LIST_HEAD_H 2 #define _LIST_HEAD_H 3 // 双向链表节点 4 struct

    2.7K30
    领券