当前位置: 首页 > article >正文

数据结构初阶之双向链表的介绍与双向链表的实现

一、概念与结构

带头双向循环链表

next :指向下一个结点(后继结点)

prev :指向前一个结点(前驱结点)

二、实现双向链表

项目创建的时候,要创建一个头文件(.h)List.h ,两个源文件(.c)List.ctest.c 。List.h 用于定义结构体和声明函数;List.c 用于实现函数;test.c 用于测试函数,每实现一个函数要进行相应的测试。编写代码过程中要勤测试,避免写出大量代码后再测试,如果出现问题,问题无从定位。

1、List.h

#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<stdbool.h>

//定义双向链表的结构
typedef int DataType;
typedef struct ListNode
{
    DataType data; 
    struct ListNode* next;
    struct ListNode* prev;
}ListNode;

//申请一个新节点
ListNode* buy_Node(DataType x);

//双向链表的初始化,申请一个头结点
ListNode* init_List(void);

//打印双向链表
void print_List(ListNode* head);

//尾插一个结点
void pushback_Node(ListNode* head, DataType x);

//头插一个结点
void pushfront_Node(ListNode* head, DataType x);

//判断链表是否为空链表
bool empty_List(ListNode* head);

//尾删一个结点
void popback_Node(ListNode* head);

//头删一个结点
void popfront_Node(ListNode* head);

//查找指定结点
ListNode* find_Node(ListNode* head, DataType x);

//在 pos 位置之后插入一个结点
void insert_Node(ListNode* pos, DataType x);

//删除指定 pos 位置的结点
void erase_Node(ListNode* pos);

//销毁双向链表
void destory_List(ListNode* head);

2、List.c


#include"List.h"

//申请一个新节点
ListNode* buy_Node(DataType x)
{
    ListNode* newnode = (ListNode*)malloc(sizeof(ListNode));
    if (!newnode)
    {
        perror("malloc fail!");
        exit(1);
    }
    newnode->data = x;
    newnode->next = newnode->prev = newnode;
    return newnode;
}

//双向链表的初始化,申请一个头结点
ListNode* init_List(void)
{
    ListNode* plist = buy_Node(-1);
    return plist;
}

//打印双向链表
void print_List(ListNode* head)
{
    ListNode* pcur = head->next;
    while (pcur != head)
    {
        printf("%d -> ", pcur->data);
        pcur = pcur->next;
    }
    printf("\n");
}

//判断链表是否为空链表
bool empty_List(ListNode* head)
{
    assert(head);
    return head->next != head;
}


//尾插一个结点
void pushback_Node(ListNode* head, DataType x)
{
    assert(head);
    ListNode* newnode = buy_Node(x);
    newnode->next = head;
    newnode->prev = head->prev;
    head->prev->next = newnode;
    head->prev = newnode;
}

//头插一个结点
void pushfront_Node(ListNode* head, DataType x)
{
    assert(head);
    ListNode* newnode = buy_Node(x);
    newnode->next = head->next;
    newnode->prev = head;
    head->next->prev = newnode;
    head->next = newnode;
}

//尾删一个结点
void popback_Node(ListNode* head)
{
    assert(empty_List(head));
    ListNode* del = head->prev;
    head->prev = del->prev;
    del->prev->next = head;
    free(del);
    del = NULL;
}
//头删一个结点
void popfront_Node(ListNode* head)
{
    assert(empty_List(head));
    ListNode* del = head->next;
    del->next->prev = head;
    head->next = del->next;
    free(del);
    del = NULL;
}

//查找指定结点
ListNode* find_Node(ListNode* head, DataType x)
{
    assert(head);
    ListNode* pcur = head->next;
    while (pcur != head)
    {
        if (pcur->data == x)
            return pcur;
        pcur = pcur->next;
    }
    return NULL;
}

//在 pos 位置之后插入一个结点
void insert_Node(ListNode* pos, DataType x)
{
    assert(pos);
    ListNode* newnode = buy_Node(x);
    newnode->next = pos->next;
    newnode->prev = pos;
    pos->next->prev = newnode;
    pos->next = newnode;
}

//删除指定 pos 位置的结点
void erase_Node(ListNode* pos)
{
    assert(pos);
    pos->next->prev = pos->prev;
    pos->prev->next = pos->next;
    free(pos);
    pos = NULL;
}

//销毁双向链表
void destory_List(ListNode** head)
{
    ListNode* pcur = (*head)->next;
    while (pcur != *head)
    {
        ListNode* next = pcur->next;
        free(pcur);
        pcur = next;
    }
    free(*head);
    *head = NULL;
}

test.c自行测试,这里不予提供。


http://www.kler.cn/a/515923.html

相关文章:

  • SpringAI 之AI 模型输出与 POJO 映射
  • 数据分析 six库
  • 步入响应式编程篇(二)之Reactor API
  • 每天五分钟深度学习pytorch:基于VGG神经网络完成CAFIR10的识别
  • Kafak 单例生产者实现-C#操作
  • 工厂模式 - 工厂方法模式、抽象工厂模式
  • 软件测试丨SDK 功能测试
  • 【软件测试入门】测试工作总结
  • 蓝桥杯例题一
  • 使用 Element-UI 中的 el-button 添加防抖指令防止重复提交
  • 备赛蓝桥杯之第十五届职业院校组省赛第三题:产品360度展示
  • Alibaba Spring Cloud 四 Seata 的核心组件:TC
  • 【浙江省乡镇界】面图层shp格式arcgis数据+乡镇名称和编码+wgs84坐标无偏移内容测评
  • 在 Windows 11 中为 SMB 3.x 文件共享协议提供 RDMA 支持
  • 【C++图论 并集查找】2492. 两个城市间路径的最小分数|1679
  • TOGAF之架构标准规范-信息系统架构 | 数据架构
  • 小利特惠源码/生活缴费/电话费/油卡燃气/等充值业务类源码附带承兑系统
  • c语言贪吃蛇(极简版,基本能玩)
  • 【豆包MarsCode蛇年编程大作战】花样贪吃蛇
  • 操作系统(Linux Kernel 0.11Linux Kernel 0.12)解读整理——内核初始化(main init)之缓冲区的管理