数据结构系列3-双链表

实现功能:

  1. 双链表的创建
  2. 双链表的插入(头插法、尾插法)
  3. 双链表的删除
  4. 双链表的遍历

代码实现:

//双链表
#include <stdio.h>
#include <stdlib.h>

//定义链表节点的结构体
typedef struct node_st
{
    int data;  //数据域
    struct node_st *prev;  //前驱指针
    struct node_st *next; //后继指针
}list;

/*函数声明部分*/
list *list_create();  //创建链表
void list_insert_h(list *head,int data);
void list_insert_t(list *head,int data);
int list_delete(list *head,int data);
void list_print(list *head);

int main()
{
    int i;
    list *head = list_create();

    list_insert_h(head,1);//头部插入
    list_insert_h(head,2);
    list_insert_h(head,3);

    list_insert_t(head,4);//尾部插入
    list_insert_t(head,5);
    list_print(head);

    for(i=1;i<6;i++)  //循环删除所有有效节点
    {
        list_delete(head,i);
    }

    list_print(head);

    return 0;
}

list *list_create()
{
    list *head = malloc(sizeof(*head));

    head->data = 0; //存放有效节点个数
    head->prev = NULL;
    head->next = NULL;

    return head;  //返回头指针
}

//头插法
void list_insert_h(list *head,int data)
{
    list *new = malloc(sizeof(*new));//为新节点申请内存空间
    new->data = data;   //插入的数据

    //1).链表不为空时
    if(head->next!=NULL)
    {
        new->prev = head;      //1.新节点的前驱指针指向头节点
        new->next = head->next;//2.新节点的后继指针指向第1个有效节点
        head->next = new;      //3.头节点的后继指针指向新节点
        head->next->prev = new;//4.第1个有效节点的前驱指针指向新节点
    }
    //2).链表为空时
    else
    {
        new->prev = head;     //1.新节点的前驱指针指向头节点
        new->next = head->next;//2.新节点的后继指针指向NULL
        head->next = new;      //3.头节点的后继指针指向新节点
    }

    head->data++;//有效节点数+1
}

//尾插法
void list_insert_t(list *head,int data)
{
    list *tail = head;  //尾节点
    list *new = malloc(sizeof(*new));//新节点
    new->data = data;  //新节点的数据
    int i = 0;

    //while(tail->next!=NULL)
    for(i=0;i<head->data;i++)
    {
        tail = tail->next;
    }

    new->prev = tail;      //1.新节点的前驱指针指向尾节点
    new->next = tail->next;//2.新节点的后继指针指向NULL
    tail->next = new;      //3.尾节点的后继指针指向新节点

    head->data++;   //有效节点个数+1
}

int list_delete(list *head,int data)
{
    list *node = head->next;

    while(node)  //节点不为空
    {
        if(node->data==data)
        {
            //1).待删节点不是尾节点时
            if(node->next)
            {
                //1.待删节点的前1节点的后继指针指向待删节点的后1节点
                node->prev->next = node->next;
                //2.待删节点的后1节点的前驱指针指向待删节点的前1节点
                node->next->prev = node->prev;
            }
            //2).待删节点为尾节点时
            else
            {
                //1.待删节点的前1节点的后继指针指向NULL
                node->prev->next = node->next;
            }

            free(node);
            head->data--;  //有效节点数-1
            return 1;
        }
        //继续往下找
        node = node->next;
    }
    return 0;
}

void list_print(list *head)
{
    list *node = head->next;//第1个有效节点
    while(node)
    {
        printf("%d->",node->data);
        node = node->next;
    }
    printf("NULL\n");
}
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           

运行结果:
在这里插入图片描述

代码分析:
5. 头插法
1). 链表不为空时
在这里插入图片描述

new->prev = head;      //1.新节点的前驱指针指向头节点
new->next = head->next;//2.新节点的后继指针指向第1个有效节点
head->next = new;      //3.头节点的后继指针指向新节点
head->next->prev = new;//4.第1个有效节点的前驱指针指向新节点

2). 链表为空时
在这里插入图片描述

new->prev = head;      //1.新节点的前驱指针指向头节点
new->next = head->next;//2.新节点的后继指针指向NULL
head->next = new;      //3.头节点的后继指针指向新节点
  1. 尾插法
    在这里插入图片描述
new->prev = tail;      //1. 新节点的前驱指针指向尾节点
new->next = tail->next;//2.新节点的后继指针指向NULL
tail->next = new;      //3.尾节点的后继指针指向新节点
  1. 链表的删除
    1). 待删节点不是尾节点时
    在这里插入图片描述
//1.待删节点的前1个节点的后继指针指向待删除节点的后1个节点
node->prev->next = node->next;
//2.待删节点的后1个节点的前驱指针指向待删节点的前1个节点
node->next->prev = node->prev;

2). 待删节点为尾节点时:
在这里插入图片描述

//1. 待删节点的前1节点的后继指针指向NULL
node->prev->next = node->next;
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

⁽⁽ଘ晴空万里ଓ⁾⁾

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值