【数据结构|C语言版】双向链表

news2024/11/24 18:56:47

  • 前言
  • 1. 初步认识双向链表
    • 1.1 定义
    • 1.2 结构
    • 1.3 储存
  • 2. 双向链表的方法(接口函数)
    • 2.1 动态申请空间
    • 2.2 创建哨兵位
    • 2.3 查找指定数据
    • 2.4 指定位置插入
    • 2.5 指定位置删除
    • 2.6 头部插入
    • 2.7 头部删除
    • 2.8 尾部插入
    • 2.9 尾部删除
    • 2.10 计算链表大小
    • 2.11 销毁链表
  • 3. 双向链表的代码实现
  • 结语


在这里插入图片描述


上期回顾: 【数据结构|C语言版】顺序表应用
个人主页:C_GUIQU
专栏:【数据结构(C语言版)学习】

在这里插入图片描述

前言

各位小伙伴大家好!上期小编给大家讲解了数据结构中的顺序表应用,接下来讲讲数据结构中的双向链表!
在这里插入图片描述

1. 初步认识双向链表

1.1 定义

双向链表也叫双链表,是链表的一种,它的每个数据结点中都有两个指针,分别指向直接后继和直接前驱。

1.2 结构

在这里插入图片描述

在这里插入图片描述

1.3 储存

//双链表节点结构体
typedef struct DoubleLinkNode
{
    char data;
    struct DoubleLinkNode* prior;
    struct DoubleLinkNode* next;
} Node,*NodePtr;

2. 双向链表的方法(接口函数)

2.1 动态申请空间

【本质】动态开辟一块sizeof(ListNode)大小的空间进行存储
在这里插入图片描述

// 动态申请一个结点
ListNode *BuyListNode(LTDateType x) {
    ListNode *node = (ListNode *) malloc(sizeof(ListNode));
    node->data = x;
    node->prev = NULL;
    node->next = NULL;
    return node;
}

2.2 创建哨兵位

在这里插入图片描述

// 创建返回链表的哨兵位
ListNode *ListInit() {
    ListNode *pHead = BuyListNode(-1);
    pHead->prev = pHead;
    pHead->next = pHead;
    return pHead;
}

2.3 查找指定数据

// 双向链表查找
ListNode *ListFind(ListNode *pHead, LTDateType x) {
    assert(pHead);

    ListNode *curr = pHead->next;
    while (curr != pHead) {
        if (curr->data == x) {
            return curr;
        }
        curr = curr->next;
    }
    return NULL;
}

2.4 指定位置插入

// 双向链表在pos位置插入x
void ListInsert(ListNode *pos, LTDateType x) {
    assert(pos);

    ListNode *newNode = BuyListNode(x);
    ListNode *prev = pos->prev;

    newNode->prev = prev;
    newNode->next = pos;
    prev->next = newNode;
    pos->prev = newNode;
}

2.5 指定位置删除

// 双向链表在pos位置删除
void ListErase(ListNode *pos) {
    assert(pos);
    assert(pos != pos->next);

    pos->next->prev = pos->prev;
    pos->prev->next = pos->next;
    free(pos);
}

2.6 头部插入

// 双向链表头插
void ListPushFront(ListNode *pHead, LTDateType x) {
    ListInsert(pHead->next, x);
}

2.7 头部删除

// 双向链表头删
void ListPopFront(ListNode *pHead) {
    ListErase(pHead->next);
}

2.8 尾部插入

// 双向链表尾插
void ListPushBack(ListNode *pHead, LTDateType x) {
    ListInsert(pHead, x);
}

2.9 尾部删除

// 双向链表尾删
void ListPopBack(ListNode *pHead) {
    ListErase(pHead->prev);
}

2.10 计算链表大小

// 计算大小
int ListSize(ListNode *pHead) {
    ListNode *curr = pHead->next;
    int size = 0;
    while (curr != pHead) {
        size++;
        curr = curr->next;
    }
    return size;
}

2.11 销毁链表

// 销毁(手动置空)
void ListDestory(ListNode *pHead) {
    ListNode *curr = pHead->next;
    while (curr != pHead) {
        ListNode *next = curr->next;
        free(curr);
        curr = next;
    }
    free(pHead);
}

3. 双向链表的代码实现

#include <stdio.h>
#include <stdlib.h>
int Linklength;

//双链表节点结构体
typedef struct DoubleLinkNode
{
    char data;
    struct DoubleLinkNode* prior;
    struct DoubleLinkNode* next;
} Node,*NodePtr;

//初始化
NodePtr initLinkList()
{
    NodePtr LinkHeader = (NodePtr)malloc(sizeof(Node));
    LinkHeader->data = '\0';
    LinkHeader->next = NULL;
    LinkHeader->prior = NULL;
    Linklength = 0;
    return LinkHeader;
}

//寻找尾节点
NodePtr tailNodeSearch(NodePtr LinkHeader)
{
    NodePtr p = LinkHeader;
    while(p->next)
    {
        p = p->next;
    }
    return p;
}

//正向打印
void printListByHead(NodePtr LinkHeader)
{
    NodePtr p = LinkHeader->next;
    while (p)
    {
        printf("%c",p->data);
        p = p->next;
    }
    printf("\n");
}

//反向打印
void printListByTail(NodePtr LinkHeader)
{
    NodePtr tail = tailNodeSearch(LinkHeader);
    NodePtr p = tail;
    while (p)
    {
        printf("%c",p->data);
        p = p->prior;
    }
    printf("\n");
}

//在某位置插入
void ListInsert(NodePtr LinkHeader, int InsertPosition, char InsertChar)
{
    if(InsertPosition < 0 || InsertPosition > Linklength)
    {
        printf("The position %d out of range of linked list!\n",InsertPosition);
        return ;
    }
    NodePtr p,q,r,tail;
    p = LinkHeader;
    for(int i = 0; i < InsertPosition; ++i)
    {
        p = p->next;
        if(!p)
        {
            printf("The position %d out of range of linked list!\n",InsertPosition);
            return ;
        }
    }
    q = (NodePtr)malloc(sizeof(Node));
    q->data = InsertChar;
    r = p->next;
    q->prior = p;
    q->next = r;
    p->next = q;
    if(r)
    {
        r->prior = q;
    }
    Linklength++;
}

//删除第一个数据域为x的节点
void ListDeleteByData(NodePtr LinkHeader, char DeleteChar)
{
    NodePtr p,q,r;
    p = LinkHeader;
    while(p->next && p->next->data != DeleteChar)
    {
        p = p->next;
    }
    if(!(p->next))
    {
        printf("The char '%c' does't exist.\n",DeleteChar);
        return ;
    }
    q = p->next;
    r = q->next;
    p->next = r;
    if(r)
    {
        r->prior = p;
    }
    free(q);
    Linklength--;
}

//删除第Position个节点
void ListDeleteByPosition(NodePtr LinkHeader, int Position)
{
    NodePtr p,q,r,tail;
    int j = 0;
    tail = tailNodeSearch(LinkHeader);
    p = LinkHeader;
    while(p->next && j < Position)
    {
        p = p->next;
        ++j;
    }
    if(!(p->next) || j > Position)
    {
        printf("Can't delete it!\n");
        return ;
    }
    q = p->next;
    r = q->next;
    p->next = r;
    if(r)
    {
        r->prior = p;
    }
    free(q);
    Linklength--;
}

//链表节点的读取(打印链表中第position个数据元素的值)
void GetElement(NodePtr LinkHeader, int position)
{
    NodePtr p,q,r;
    if(position <= Linklength/2)
    {
        p = LinkHeader->next;
        int j = 0;
        while(p && j < position)
        {
            p = p->next;
            ++j;
        }
        if(!p || j > position)
        {
            printf("Can't get it !\n");
            return ;
        }
        printf("The element at its %d-th position is %c\n",position,p->data);
    }else
    {
        p = tailNodeSearch(LinkHeader);
        int j = 0;
        while(p->prior && j < Linklength-position-1)
        {
            p = p->prior;
            ++j;
        }
        if(!p || j > Linklength-position-1)
        {
            printf("Can't get it !\n");
            return ;
        }
        printf("The element at its %d-th position is %c\n",position,p->data);
    }
}

//测试
void insertDeleteTest()
{
    printf("---------------Initialize bidirectional linked list--------------\n");
    NodePtr tempList = initLinkList();
    printListByHead(tempList);
    printListByTail(tempList);

    printf("---------------Inserts a node at the specified location--------------\n");
    ListInsert(tempList,0,'H');
    ListInsert(tempList,1,'e');
    ListInsert(tempList,2,'l');
    ListInsert(tempList,3,'l');
    ListInsert(tempList,4,'o');
    
    printListByHead(tempList);
    printListByTail(tempList);

    printf("---------------Gets the node data field at the specified location--------------\n");
    GetElement(tempList,0);
    GetElement(tempList,4);
    GetElement(tempList,5);

    printf("---------------Delete the first node whose data field is X--------------\n");
    ListDeleteByData(tempList,'e');
    printListByHead(tempList);
    printListByTail(tempList);

    printf("---------------Delete the position node--------------\n");
    ListDeleteByPosition(tempList,3);
    printListByHead(tempList);
    printListByTail(tempList);
}

int main()
{
    insertDeleteTest();
}

结语

以上就是小编对双向链表的讲解。
如果觉得小编讲的还可以,还请一键三连。互三必回!
持续更新中~!
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1600667.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

怎么样在外网登录访问CRM管理系统?

一、什么是CRM管理系统&#xff1f; Customer Relationship Management&#xff0c;简称CRM&#xff0c;指客户关系管理&#xff0c;是企业利用信息互联网技术&#xff0c;协调企业、顾客和服务上的交互&#xff0c;提升管理服务。为了企业信息安全以及使用方便&#xff0c;企业…

【K8s】:在 Kubernetes 集群中部署 MySQL8.0 高可用集群(1主2从)

【K8s】&#xff1a;在 Kubernetes 集群中部署 MySQL8.0 高可用集群&#xff08;1主2从&#xff09; 一、准备工作二、搭建nfs服务器2.1 安装 NFS 服务器软件包&#xff08;所有节点执行&#xff09;2.2 设置共享目录2.3 启动 NFS 服务器2.4 设置防火墙规则&#xff08;可选&am…

OpenHarmony南向开发实例:【游戏手柄】

介绍 基于TS扩展的声明式开发范式编程语言&#xff0c;以及OpenHarmony的分布式能力实现的一个手柄游戏。 完成本篇Codelab需要两台开发板&#xff0c;一台开发板作为游戏端&#xff0c;一台开发板作为手柄端&#xff0c;实现如下功能&#xff1a; 游戏端呈现飞机移动、发射…

计算机视觉——OpenCV Python基于颜色识别的目标检测

1. 计算机视觉中的颜色空间 颜色空间在计算机视觉领域的应用非常广泛&#xff0c;它们在图像和视频处理、物体检测等任务中扮演着重要角色。颜色空间的主要作用是将颜色以数值形式表示出来&#xff0c;这样计算机算法就能够对其进行处理和分析。不同的颜色空间有着不同的特点和…

Web3D智慧医院平台(HTML5+Threejs)

智慧医院的建设将借助物联网、云计算、大数据、数字孪生等技术&#xff0c;以轻量化渲染、极简架构、三维可视化“一张屏”的形式&#xff0c;让医院各大子系统管理既独立又链接&#xff0c;数据相互融合及联动。 建设医院物联网应用的目标对象&#xff08;人、物&#xff09;都…

基于afx透明视频的视觉增强前端方案

作者 | 青玉 导读 本文介绍了增长前端团队自研的Webview框架下透明视频视觉增强方案&#xff0c;该方案在保证对视觉进行高度还原的同时可投入更少的开发成本&#xff0c;还能获得更优的前端性能表现。文章首先分析了市面上动画方案的优缺点&#xff0c;然后详细介绍了透明视频…

CentOS下GitLab的安装部署_centos 安装部署 gitlab,2024年最新软件测试开发岗还不会这些问题

先自我介绍一下&#xff0c;小编浙江大学毕业&#xff0c;去过华为、字节跳动等大厂&#xff0c;目前阿里P7 深知大多数程序员&#xff0c;想要提升技能&#xff0c;往往是自己摸索成长&#xff0c;但自己不成体系的自学效果低效又漫长&#xff0c;而且极易碰到天花板技术停滞…

HTML段落标签、换行标签、文本格式化标签与水平线标签

目录 HTML段落标签 HTML换行标签 HTML格式化标签 加粗标签 倾斜标签 删除线标签 下划线标签 HTML水平线标签 HTML段落标签 在网页中&#xff0c;要把文字有条理地显示出来&#xff0c;就需要将这些文字分段显示。在 HTML 标签中&#xff0c;<p>标签用于定义段落…

Python 基于 OpenCV 视觉图像处理实战 之 OpenCV 简单人脸检测/识别实战案例 之十二 简单人脸识别

Python 基于 OpenCV 视觉图像处理实战 之 OpenCV 简单人脸检测/识别实战案例 之十二 简单人脸识别 目录 Python 基于 OpenCV 视觉图像处理实战 之 OpenCV 简单人脸检测/识别实战案例 之十二 简单人脸识别 一、简单介绍 二、简单人脸识别实现原理 三、简单人脸识别案例实现简…

基于小程序实现的餐饮外卖系统

作者主页&#xff1a;Java码库 主营内容&#xff1a;SpringBoot、Vue、SSM、HLMT、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、小程序、安卓app等设计与开发。 收藏点赞不迷路 关注作者有好处 文末获取源码 技术选型 【后端】&#xff1a;Java 【框架】&#xff1a;spring…

如何在PPT中获得网页般的互动效果

如何在PPT中获得网页般的互动效果 效果可以看视频 PPT中插入网页有互动效果 当然了&#xff0c;获得网页般的互动效果&#xff0c;最简单的方法就是在 PPT 中插入网页呀。 那么如何插入呢&#xff1f; 接下来为你讲解如何获得&#xff08;此方法在 PowerPoint中行得通&#…

华为配置静态ARP示例

华为配置静态ARP示例 组网图形 图1 配置静态ARP组网图 静态ARP简介配置注意事项组网需求配置思路操作步骤配置文件相关信息 静态ARP简介 静态ARP表项是指网络管理员手工建立IP地址和MAC地址之间固定的映射关系。 正常情况下网络中设备可以通过ARP协议进行ARP表项的动态学习&…

差速机器人模型LQR 控制仿真——路径模拟

LQR路径跟踪要求路径中带角度&#xff0c;即坐标&#xff08;x,y,yaw&#xff09;&#xff0c;而一般我们的规划出来的路径不带角度。这里通过总结相关方法&#xff0c;并提供一个案例。 将点路径拟合成一条完整的线路径算法 将点路径拟合成一条完整的线路径是一个常见的问题…

C#语法知识之变量

2.变量 一、知识点 1、折叠代码 //#region按Tab键#region MyRegion(描述)#endregion //本质是编译器提供给我们的预处理指令&#xff0c;发布代码是会被自动删除2、声明变量和变量类型 ​ 变量就是可以变化的容器&#xff0c;用来存储各种不同类型数值的一个容器&#xff1b…

jenkins从节点配置说明

目的 打包构建时使用从节点&#xff0c;从节点所在服务器配置4C8G5000G&#xff08;服务器2&#xff09; 前提 首先在服务器1上部署jenkins服务&#xff0c;即主节点&#xff0c;默认节点名称为master 步骤 1&#xff09;登录进入jenkins平台&#xff0c;在系统设置中&…

KT-105小动物人工呼吸机

咳咳&#xff0c;请各位小伙伴们注意啦&#xff01;我们要聊的主题可是相当高大上——小动物呼吸机&#xff01; 我们得先了解一下什么是小动物呼吸机。这可不是一般的机器哦&#xff0c;它是一种实验设备&#xff0c;主要用于各种各样的科学研究实验中。比如&#xff0c;在基…

ICV:《中美量子产业融资比较分析》

近日&#xff0c;全球前沿科技咨询公司ICV发布了A Comparative Analysis of Quantum Industry Financing in the U.S and China&#xff08;美国和中国量子产业融资比较分析&#xff09;报告。该报告旨在对中美两国在量子技术领域的投融资情况进行比较分析&#xff0c;探讨其差…

python解释器安装路径查询以及版本查询

查询安装路径 1、利用脚本&#xff1a; 路径: import sys import osprint(当前 Python 解释器路径&#xff1a;) print(sys.executable)运行结果&#xff1a; 目录: print(当前 Python 解释器目录&#xff1a;) print(os.path.dirname(sys.executable))运行结果&#xff1a…

十大排序——11.十大排序的比较汇总及Java中自带的排序算法

这篇文章对排序算法进行一个汇总比较&#xff01; 目录 0.十大排序汇总 0.1概述 0.2比较和非比较的区别 0.3基本术语 0.4排序算法的复杂度及稳定性 1.冒泡排序 算法简介 动图演示 代码演示 应用场景 算法分析 2.快速排序 算法简介 动图演示 代码演示 应用场景…

AGI的智力有可能在两年内超过人类水平

特斯拉CEO埃隆马斯克近日与挪威银行投资管理基金CEO坦根的访谈中表示&#xff0c;AGI的智力将在两年内可能超过人类智力&#xff0c;在未来五年内&#xff0c;AI的能力很可能超过所有人类。 马斯克透漏&#xff0c;去年人工智能发展过程中的主要制约因素是缺少高性能芯片&#…