首页
学习
活动
专区
工具
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指针指向p3next;   为此方便起见,我们可以使用双向链表进行实现。...内核是这样处理,   创建一个双向循环链表   =>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

74920
  • 循环链表-带头双向循环链表实现

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

    60730

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

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

    79830

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

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

    28100

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

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

    11710

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

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

    10510

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

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

    56800

    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; } 总结 今天我们学习了双向带头循环链表概念以及功能实现。

    12410

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

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

    16310

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

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

    60220

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

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

    40240

    【数据结构】带头双向循环链表增删查改(C语言实现)

    文章目录 前言 一、什么是带头双向循环链表 二、带头双向循环链表实现 1、结构定义 2、链表初始化 3、开辟新节点 4、在头部插入数据 5、在尾部插入数据 6、查找数据 7、在pos位置之前插入数据...、List.h 2、List.c 3、test.c 四、顺序表和链表区别 前言 在上一节我们学习了单链表,但是我们发现单链表有如下缺陷: 1、在尾部插入、删除数据时间复杂度为O(N),效率低;...可以看出,带头双向循环链表是结构最复杂一种链表,但是它复杂结构所带来优势就是它管理数据非常简单,效率非常高;下面我们用C语言实现一个带头双向循环链表,以此来感受它魅力。...---- 二、带头双向循环链表实现 1、结构定义 相比于单链表双向链表需要增加一个结构体指针prev,用来存放前一个节点地址。...,由于单链表最开始是没有节点,所以我们定义一个指向NULL节点指针即可;但是带头链表不同,我们需要在初始化函数开辟一个哨兵位头结点,此节点不用于存储有效数据; 另外,由于我们链表循环,所以最开始我们需要让头结点

    67700

    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) {

    71310

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

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

    90420

    详解双向链表基本操作(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

    1.9K31

    链接未来:深入理解链表数据结构(二.c语言实现带头双向循环链表

    上篇文章简述讲解了链表基本概念并且实现了无头单向不循环链表:链接未来:深入理解链表数据结构(一.c语言实现无头单向非循环链表)-CSDN博 那今天接着给大家带来带头双向循环链表实现: 一.项目文件规划...头文件DoubleList.h:用来基础准备(常量定义,typedef),链表基本框架,函数声明 源文件DoubleList.h:用来各种功能函数具体实现 源文件test.c:用来测试功能是否有问题...);//删除pos void LTDestroy(LTNode* phead);//销毁 三.各功能接口具体实现 1.创建节点 因为后面尾插,头插,插入,初始化都要用到创建新节点,所以抽出来作为一个函数...next 指针指向新节点 newnode 将新节点 newnode prev 指针指向前一个节点 pre 将新节点 newnode next 指针指向指定节点 pos 将指定节点 pos prev...next = cur->next; free(cur); cur = next; } free(phead); phead = NULL; } 四.利用插入和删除改变“两插两删”(快速写出链表

    12910
    领券