链表详解(双向)

双链表的介绍

看到这里,我相信你们都已经对单向链表有一定的了解,与数组相比较,链表在处理插入和删除的时候非常好用,缺点是消耗的空间较大,而且还不能通过下标进行访问。

链表有单向和双向,单向查询困难,要找到某个元素需要将这个元素之前的位置都遍历一遍。除此之外,单向的链表想要访问上一级特别困难。在此基础上,出现了双链表。
这就是双链表,双链表的头节点prev可以为NULL,也可以与链表末端链接形成双向循环链表。
在这里插入图片描述
在这里插入图片描述

双链表的创建

在这里插入图片描述

首先要创建一个头节点,并且让这个头节点的prev为NULL(初始化)。假使我们要创建n个节点,那么我们需要创建(尾节点)end,和中间节点node。循环n-1遍,每次使用node接收malloc分配空间后的地址,再将end->next指向node,node->prev指向end。最后循环出来不要忘记将end->next=NULL,要不它的指向是未知的,也就是我们说的野指针,这会引起程序的崩溃。

List* ListCreat(int n)
{
    if (n <= 0)
    {
        printf("错误!\n");
        return;
    }
    List* head = (List*)malloc(sizeof(List)), * end = head;
    head->prev = NULL;
    List* node = NULL;
    int i = 0;
    printf("请输入值\n");
    scanf("%d", &head->data);
    for (i = 1; i < n; i++)
    {
        node = (List*)malloc(sizeof(List));
        scanf("%d", &node->data);
        end->next = node;
        node->prev = end;
        end = node;
    }
    end->next = NULL;
    return head;

}

双链表的长度

在创建完双链表之后,我们想知道它的长度,可以创建整形变量count,这需要将链表的位置传进来,可以想到,每次链表走一步,count自加1,直至链表走到NULL。

int ListLen(List* list)
{
    int count = 0;
    while (list)
    {
        count++;
        list = list->next;
    }
    return count;
}

双链表的插入

对于双链表的插入,其实与单链表相差无几,只不过多了俩个需要处理的指针,在插入的时候,需要考虑头插和尾插的情况,
在这里插入图片描述

List* ListInsert(List* list, int n)
{
    if (n < 0)
        return;
    List* node = list;
    for (int i = 0; i < n&&node->next; i++)//当超出链表长度时,当成尾插处理
    {
        node = node->next;
    }
    List* new = (List*)malloc(sizeof(List));
    printf("请输入要插入的值\n");
    scanf("%d", &new->data);
    if (!node->prev)//头插
    {
        new->next = list;
        list->prev = node;
        node->prev = NULL;
        return new;
    }
    if (!node->next)//尾插
    {
        node->next = new;
        new->prev = node;
        new->next = NULL;
        
    }
    else
    {
        node->prev->next = new;
        new->prev = node->prev;
        node->prev = new;
        new->next = node;
        
    }
    return list;
}

双链表的删除

删除双链表的某个元素时,需要处理俩个指针,即要删除节点的上一节点的next,和要删除的下一节点的prev,这里也要考虑到头删和尾删。
(这里博主对于链表的访问类似数组,从零开始)。

List* ListDel(List* list, int n)
{   

    List* node = list;

    if (n < 0)
    {
        printf("错误!\n");
    }
    for (int i = 0; i < n&&node->next; i++)//当超出链表长度当成尾删处理
    {
       node = node->next;
    }
    if (!node->next)//尾删
    {
        node->prev->next = NULL;
        free(node);
    }
    else if (!node->prev)//头删
    {
        list = list->next;
       
        list->prev = NULL;
        free(node);
    }
    else
    {
        node->prev->next = node->next;
        node->next->prev = node->prev;
        free(node);
    }
    return list;
}

到了这里,双链表的基本操作已经完成,剩下的销毁和打印可以自己去实现下。

  • 5
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
单循环链表是一种将单链表尾节点的指针域置为起始节点的地址,从而形成循环连接的链表结构。这样,从链表中的任意一个节点出发,都可以遍历到链表中的所有节点。单循环链表的结构图如下所示: 双向链表是一种可以从两个方向进行遍历的链表结构,每个节点除了保存下一个节点的地址外,还保存了上一个节点的地址。双向链表的一个特点是可以利用中间的一个节点推出下一个节点和上一个节点。双向链表的结构图如下所示: 对于一个循环链表来说,不论是单向循环链表还是双向循环链表,首节点和末节点都被连接在一起。这种方式在单向和双向链表中都可以实现。要转换一个循环链表,可以选择开始于任意一个节点然后沿着列表的任一方向直到返回开始的节点。另一种方法是将循环链表的指针指向NULL来打破循环。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* [数据结构——单向循环链表&双向循环链表](https://blog.csdn.net/qq_56668869/article/details/126498355)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *3* [C语言单循环链表的表示与实现实例详解](https://download.csdn.net/download/weixin_38684892/14870959)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值