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

server/2025/1/30 21:21:58/

一、概念与结构

带头双向循环链表

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.ppmy.cn/server/163624.html

相关文章

吴恩达深度学习——深层神经网络

来自https://www.bilibili.com/video/BV1FT4y1E74V&#xff0c;仅为本人学习所用。 符号约定 对于该深层网络&#xff0c;有四层&#xff0c;包含三个隐藏层和一个输出层。 隐藏层中&#xff0c;第一层有五个单元、第二层有五个单元&#xff0c;第三层有三个单元。标记 l l l…

Python 类型注解

文章目录 Python 类型注解详解1. 引言2. Python 类型注解基础2.1 变量类型注解2.2 函数参数和返回值注解2.3 typing 模块的支持 3. 进阶&#xff1a;复杂数据类型3.1 可选类型&#xff08;Optional&#xff09;3.2 联合类型&#xff08;Union&#xff09;3.3 泛型&#xff08;G…

记一次常规的网络安全渗透测试

视频教程在我主页简介和专栏里 目录&#xff1a; 前言 互联网突破 第一层内网 第二层内网 总结 前言 上个月根据领导安排&#xff0c;需要到本市一家电视台进行网络安全评估测试。通过对内外网进行渗透测试&#xff0c;网络和安全设备的使用和部署情况&#xff0c;以及网络…

自定义数据集,使用 PyTorch 框架实现逻辑回归并保存模型,然后保存模型后再加载模型进行预测

在本文中&#xff0c;我们将展示如何使用 NumPy 创建自定义数据集&#xff0c;利用 PyTorch 实现一个简单的逻辑回归模型&#xff0c;并在训练完成后保存该模型&#xff0c;最后加载模型并用它进行预测。 1. 创建自定义数据集 首先&#xff0c;我们使用 NumPy 创建一个简单的…

springboot使用rabbitmq

使用springboot创建rabbitMQ的链接。 整个项目结构如下&#xff1a; 1.maven依赖 <dependency><groupId>com.rabbitmq</groupId><artifactId>amqp-client</artifactId><version>3.4.1</version> </dependency>application.y…

计数排序算法

基本思想 先确定待排序数组的最大值&#xff08;Max&#xff09;和最小值&#xff08;Min&#xff09;&#xff0c;随后创建Max - Min 1个长度的数组称为计数数组&#xff0c;计数数组的索引对应着待排序数组中元素的值&#xff0c;数组的值表示该元素的出现次数。通过从前往…

[笔记] 极狐GitLab实例 : 手动备份步骤总结

官方备份文档 : 备份和恢复极狐GitLab 一. 要求 为了能够进行备份和恢复&#xff0c;请确保您系统已安装 Rsync。 如果您安装了极狐GitLab&#xff1a; 如果您使用 Omnibus 软件包&#xff0c;则无需额外操作。如果您使用源代码安装&#xff0c;您需要确定是否安装了 rsync。…

系统架构设计基础:概念与原则

系统架构设计基础:概念与原则 引言 系统架构设计是软件开发过程中至关重要的一环,它决定了系统的整体结构、组件之间的关系以及系统的可扩展性、可维护性和性能。系统架构设计师不仅需要具备扎实的技术功底,还需要对业务需求有深刻的理解,能够在复杂的需求中找到平衡点,…