c语言 数据结构-双链表 学习笔记

 我是在哔哩哔哩的 up主TyrantLucifer 的手撕数据结构课程上学习的,个人感觉非常不错,大家也可以去学习,适合有c语言基础的。

注意:未考虑到malloc开辟空间错误或者取参数错误所发生的情况

 1.定义一个结点结构体类型 并创建空表

#include<stdio.h>
#include<stdlib.h>
#define TRUE 1
#define FALSE 0
typedef struct Node
{
    int data;         //结点数据
  struct Node * next; //next指针指向下一个结点
  struct Node* pre;   //pre指针指向前一个结点
}Node;
//创建空链表
Node * intList()
{
    Node* L = (Node*)malloc(sizeof(Node));// 开辟新空间给头结点
    L->data = 0;
    L->next = NULL;  // 空链表地址为空
    L->pre = NULL;
    return L;        返回头结点 地址
}

2.头插法                                                                                                                 


//头插法
void headInsert(Node * L,int data)
{
    Node* node = (Node*)malloc(sizeof(Node)); // 定义一个新结点指针 并为其开辟新空间
    node->data = data;                        //将传入的值赋给新节点 
    if (L->next == NULL)                      //判断原先链表是否为空
    {
        //链表为空
        node->next = L->next;   // 新节点next 指向NULL
        node->pre = L;          // 新节点pre  指向头节点
        L->next = node;         //头节点next  指向新节点 
    }
    else
    {
        //链表不为空
        node->pre = L;           //新节点pre  指向头节点
        node->next = L->next;    //新节点next 指向头节点指向的下一个结点(首结点)
        L->next->pre = node;     //首结点pre  指向新节点
        L->next = node;          //头节点next 指向新节点
    }
    L->data++;                   //更新链表的长度 L->data 代表着记录链表的长度 加入结点 长度+1
}

3.尾插法

/尾插法
void tailInsert(Node * L,int data)
{
    Node* temp = L;                            //借用 temp结点 来代表 头节点
    Node* node = (Node*)malloc(sizeof(Node));  //开辟新空间给新节点
    node->data = data;                         //传入的值赋给新节点
    while (L->next != NULL)                    //找到尾结点
    {
        L = L->next;//将头节点指向下一结点的地址
    }                                          //结束循环 此时 L 为尾结点
    node->next = L->next;                      //新节点next 指向 NULL
    node->pre = L;                             //新节点pre  指向 尾结点
    L->next = node;                            //尾结点next 指向 新节点
    temp->data++;                              //更新链表的长度  加入链表 长度+1 
}

4.删除结点

//删除结点
int deleteList(Node* L, int data)
{
    Node* current = L->next;            //用 current指针 代表 头节点指向的下一个结点(首结点)
    while (current)            
    {
        if (current->data == data)     //找到删除的相应结点  
        {
            current->pre->next = current->next;                                           
                                      //将current结点前一个结点指向current结点的下一个结点 
            current->next->pre = current->pre;
                                      //将current结点后一个结点指向current结点的前一个结点 
            free(current);            //释放current的地址
            L->data--;                //更新链表的长度  删除结点 长度-1
            return TRUE;
        }
        current = current->next;     //未找到 current继续指向下一个结点
    }
      //如果循环结束依然未找到 返回 false
    return FALSE;
}

5.遍历复制链表

//遍历
void printList(Node * L)
{
    Node* node = L->next;  //将node 指向 首结点
    while (node)
    {
        printf("%d->", node->data);
        node = node->next;  //node继续指向下一个结点
    }
    printf("NULL\n");
}

6.进行初始化链表

int main()
{
    Node* L = intList();
    headInsert(L, 1);
    headInsert(L, 2);
    headInsert(L, 3);
    headInsert(L, 4);
    tailInsert(L, 5);
    tailInsert(L, 6);
    tailInsert(L, 7);
    tailInsert(L, 8);
    printList(L);
    deleteList(L, 2);
    deleteList(L, 4);
    deleteList(L, 6);
    printList(L);
    return 0;

}

7.运行结果

8.完整代码

#include<stdio.h>
#include<stdlib.h>
#define TRUE 1
#define FALSE 0
typedef struct Node
{
    int data;
  struct Node * next;
  struct Node* pre;
}Node;
//创建空链表
Node * intList()
{
    Node* L = (Node*)malloc(sizeof(Node));
    L->data = 0;
    L->next = NULL;
    L->pre = NULL;
    return L;
}
//头插法
void headInsert(Node * L,int data)
{
    Node* node = (Node*)malloc(sizeof(Node));
    node->data = data;
    if (L->next == NULL)
    {
        node->next = L->next;
        node->pre = L;
        L->next = node;
    }
    else
    {
        node->pre = L;
        node->next = L->next;
        L->next->pre = node;
        L->next = node;
    }
    L->data++;
}
//尾插法
void tailInsert(Node * L,int data)
{
    Node* temp = L;
    Node* node = (Node*)malloc(sizeof(Node));
    node->data = data;
    while (L->next != NULL)
    {
        L = L->next;
    }
    node->next = L->next;
    node->pre = L;
    L->next = node;
    temp->data++;
}
//删除结点
int deleteList(Node* L, int data)
{
    Node* current = L->next;
    while (current)
    {
        if (current->data == data)
        {
            current->pre->next = current->next;
            current->next->pre = current->pre;
            free(current);
            L->data--;
            return TRUE;
        }
        current = current->next;
    }
    return FALSE;
}
//遍历
void printList(Node * L)
{
    Node* node = L->next;
    while (node)
    {
        printf("%d->", node->data);
        node = node->next;
    }
    printf("NULL\n");
}
int main()
{
    Node* L = intList();
    headInsert(L, 1);
    headInsert(L, 2);
    headInsert(L, 3);
    headInsert(L, 4);
    tailInsert(L, 5);
    tailInsert(L, 6);
    tailInsert(L, 7);
    tailInsert(L, 8);
    printList(L);
    deleteList(L, 2);
    deleteList(L, 4);
    deleteList(L, 6);
    printList(L);
    return 0;

}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

小苏先生.

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

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

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

打赏作者

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

抵扣说明:

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

余额充值