数据结构--双向链表专题

目录

    • 1. 双向链表的结构
    • 2. 实现双向链表
      • 预先的准备
      • 初始化
      • 尾插、头插
      • 尾删、头删
      • 查找
      • 在pos位置之后插⼊数据
      • 删除pos位置的数据
    • 3. 顺序表和双向链表的分析

1. 双向链表的结构

在这里插入图片描述
注意:这里的“带头”跟前面我们说的“头结点”是两个概念,为了更好的理解直接称为单链表的头结点

带头链表里的头结点,实际为“哨兵位”,哨兵位节点不存储任何有效数字,知识站在这里“放哨”

“哨兵位”存在的意义:
遍历循环链表避免死循环

2. 实现双向链表

预先的准备

在这里插入图片描述

typedef int LTDataType;
typedef struct ListNode
{
	LTDataType data;
	struct ListNode* prev;
	struct ListNode* next;
}LTNode;

初始化

注意,双向链表是带有哨兵位的,插入数据之前链表中必须要先初始化一个哨兵位

void LTInit(LTNode** pphead)
{
	*pphead = (LTNode*)malloc(sizeof(LTNode));
	if (*pphead == NULL)
	{
		perror("malloc");
		exit(1);
	}
	(*pphead)->data = -1;
	(*pphead)->next = (*pphead)->prev = *pphead;
}

当链表中只有哨兵位节点的时候,我们称该链为空链表
即哨兵位是不能删除也不能修改的,即不能对哨兵位进行任何操作

尾插、头插

在这里插入图片描述

在这里插入图片描述

//不需要改变哨兵位,则不需要传二级指针
//如果需要修稿哨兵位的话,则传二级指针
//尾插
LTNode* LTBuyNode(LTDataType  x)
{
	LTNode* newnode = (LTNode*)malloc(sizeof(LTNode));
	if (newnode == NULL)
	{
		perror("malloc");
		exit(1);
	}
	newnode->data = x;
	newnode->next = newnode->prev = newnode; 
}
void LTPushBack(LTNode* phead, LTDataType x)
{
	assert(phead);
	LTNode* newnode = LTBuyNode(x);
	newnode->next = phead;
	newnode->prev = phead->prev;

	phead->prev->next = newnode;
	phead->prev = newnode;
}

//头插
void LTPushFront(LTNode* phead, LTDataType x)
{
	assert(phead);
	LTNode* newnode = LTBuyNode(x);
	//phead newnode phead->next

	newnode->next = phead->next;
	newnode->prev = phead;

	phead->next->prev = newnode;
	phead->next = newnode;
}

单链表中涉及到二级指针:单链表中的phead(第一个节点)可能为空
双向链表中不需要二级指针:双向链表中的phead(哨兵位)不可能为空

尾删、头删

在这里插入图片描述

在这里插入图片描述

//头删、尾删
void LTPopBack(LTNode* phead)
{
	assert(phead);
	//链表为空:只有一个哨兵位
	assert(phead->next != phead);

	/*phead->prev->prev->next = phead;
	phead->prev = phead -> prev->prev*/
	LTNode* del = phead->prev;
	LTNode* prev = del->prev;

	prev->next = phead;
	phead->prev = prev;

	free(del);
	del = NULL;
}
//头删
void LTPopFront(LTNode* phead)
{
	assert(phead);
	assert(phead->next != phead);

	LTNode* del = phead->next;
	LTNode* next = del->next;

	next->prev = phead;
	phead->next = next;

	free(del);
	del = NULL;
}


查找

LTNode* LTFind(LTNode* phead, LTDataType x)
{
	assert(phead);
	LTNode* pcur = phead->next;
	while (pcur != phead)
	{
		if (pcur->data == x)
		{
			return pcur;
		}
		pcur = pcur->next;
	}
	return NULL;
}

在pos位置之后插⼊数据

在这里插入图片描述

/在pos位置之后插⼊数据
void LTInsert(LTNode* pos, LTDataType x)
{
	assert(pos);
	LTNode* newnode = LTBuyNode(x);
	//pos newnode pos->next

	newnode->next = pos->next;
	newnode->prev = pos;

	pos->next->prev = newnode;
	pos->next = newnode;

}

删除pos位置的数据

在这里插入图片描述

void LTErase(LTNode* pos)
{
	assert(pos);

	pos->next->prev = pos->prev;
	pos->prev->next = pos->next;

	free(pos);
	pos = NULL;
}

3. 顺序表和双向链表的分析

不同点顺序表链表(单链表)
存储空间上物理上一定连续逻辑上连续,但物理上不一定连续
随机访问支持O(1)不支持 O(N)
任意插入或者删除元素可能需要搬移元素,效率低只需要修改指针指向
插入动态顺序表,空间不够时需要扩展没有容量的概念
应用场景元素高效存储+频繁访问任意位置插入和删除频繁

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Nginx的反向代理:实现灵活的请求转发和内容缓存

一、引言:代理服务器的简介 本节介绍代理服务器的基本配置。学习如何通过不同协议将 NGINX 请求传递给代理的服务器,修改发送到代理服务器的客户端请求标头,以及配置来自代理服务器的响应缓冲。 代理通常用于在多个服务器之间分配负载&…

tigramite教程(二)生物地球科学案例研究

文章目录 数据生成与绘图因果发现分析平稳性假设、确定性、潜在混杂因素结构假设参数假设使用PCMCIplus的滑动窗口分析聚合因果图非参数因果效应估计假设的图形和调整集干预的真实情况假设的参数模型和因果效应的估计使用关于图的不同假设进行估计非因果估计项目地址 这个文件…

力扣随笔之颜色分类(中等75)

思路:定义两个指针划分left,right划分三个区域left左边是红色区域,right右边是蓝色区域,left和right之间是白色区域;定义一个遍历指针遍历整个数组,遇到红色与left所指位置数字交换,并将left自加…

鸿蒙开发实战-手写一个Openharmony投屏工具

实战手写一个Openharmony投屏工具,实现代码分享如下: java import javax.imageio.ImageIO; import javax.swing.*; import java.awt.*; import java.awt.event.*; import java.awt.image.BufferedImage; import java.io.File; import java.io.IOExcepti…

一篇文章告诉你ELK Stack是什么

目录 ELK Stack简介 ELK Stack优点 ELK Stack组成 Elasticsearch Elasticsearch简介 Elasticsearch主要特点 Elasticsearch核心概念 Elasticsearch的配置 Logstash Logstash简介 Logstash过滤器之grok正则匹配 Logstash过滤器之mutate数据修改 Logstash过滤器之Ge…

如何快速将每个图片做二维码?批量生成图片码的步骤

现在很多商品的包装上扫码都会展现出物品的图片信息,每个物品都会有单独的一张物品信息图片。那么当导出一批图片后,如何快速将每张图片单独生成一个二维码来使用呢?本文小编将通过图文内容给大家讲解一下图片二维码生成器的批量建码功能该如…

automatic_mine_sweeper —— A project review to improve myself

1. How to understand the whole structure of the project? 1.Cbutton.h 和 Cbutton.cpp文件: Cbutton.h文件- // Cbutton.h : main header file for the CBUTTON application //#if !defined(AFX_CBUTTON_H__240DD99D_BEDE_49BD_A960_3268C3644816__INCLUDED_…

Python实用技巧:处理JSON文件写入换行问题

Python实用技巧:处理JSON文件写入换行问题 🌈 个人主页:高斯小哥 🔥 高质量专栏:Matplotlib之旅:零基础精通数据可视化、Python基础【高质量合集】、PyTorch零基础入门教程 👈 希望得到您的订阅…

05 Flink 的 WordCount

前言 本文对应于 spark 系列的 Spark 的 WordCount 这里主要是 从宏观上面来看一下 flink 这边的几个角色, 以及其调度的整个流程 一个宏观 大局上的任务的处理, 执行 基于 一个本地的 flink 集群 测试用例 /*** com.hx.test.Test01WordCount** author Jerry.X.He* ver…

架构设计:流式处理与实时计算

引言 随着大数据技术的不断发展,流式处理和实时计算在各行各业中变得越来越重要。那么什么是流式处理呢?我们又该怎么使用它?流式处理允许我们对数据流进行实时分析和处理,而实时计算则使我们能够以低延迟和高吞吐量处理数据。本…

Bert基础(四)--解码器(上)

1 理解解码器 假设我们想把英语句子I am good(原句)翻译成法语句子Je vais bien(目标句)。首先,将原句I am good送入编码器,使编码器学习原句,并计算特征值。在前文中,我们学习了编…

4.测试教程 - 用例篇

文章目录 1.测试用例的基本要素2.测试用例的给我们带来的好处3.测试用例的设计方法3.1基于需求进行测试用例的设计3.1.1功能需求测试分析3.1.2非功能需求测试分析 3.2具体的设计方法3.2.1等价类3.2.2边界值3.2.3错误猜测法3.2.4判定表3.2.5场景设计法3.2.6因果图3.2.7因果图的需…

c++:vector的相关oj题(136. 只出现一次的数字、118. 杨辉三角、26. 删除有序数组中的重复项、JZ39 数组中出现次数超过一半的数字)

文章目录 1. 136. 只出现一次的数字题目详情代码(直接来异或)思路 2. 118. 杨辉三角题目详情代码1思路代码2思路2 3. 26. 删除有序数组中的重复项题目详情代码思路 4. JZ39 数组中出现次数超过一半的数字题目详情代码1(暴力)思路1代码2&#…

A Visual Guide to Mamba and State Space Models

用于语言建模的 Transformers 的替代方案 Transformer 架构一直是大型语言模型 (LLMs) 成功的主要组成部分。它已被用于当今几乎所有LLMs正在使用的产品,从 Mistral 等开源模型到 ChatGPT 等闭源模型。 为了进一步改进LLMs,开发…

【HarmonyOS】鸿蒙开发之Stage模型-基本概念——第4.1章

Stage模型-基本概念 名词解释 AbilityStage:应用组件的“舞台“ UIAbility:包含UI界面的应用组件,是系统调度的基本单元 WindowStage:组件内窗口的“舞台“ Window:用来绘制UI页面的窗口 HAP:Harmony Ability Package(鸿蒙能力类型的包) HSP:Harmony Sh…

【算法 - 动态规划】找零钱问题Ⅰ

在前面的动态规划系列文章中,关于如何对递归进行分析的四种基本模型都介绍完了,再来回顾一下: 从左到右模型 :arr[index ...] 从 index 之前的不用考虑,只考虑后面的该如何选择 。范围尝试模型 :思考 [L ,…

C++——二叉搜索树

二叉搜索树 二叉搜索树: 又为搜索二叉树,一般具有以下的性质 若它的左子树不为空,则左子树上所有的节点的值都小于父亲节点若它的右子树不为空,则右子树上所有的节点的值都大于父亲节点它的左右子树也都为二叉搜索树 二叉搜索树…

Vue前端实现一个本地消息队列(MQ), 让消息延迟消费或者做缓存

MQ功能实现的具体代码(TsMQ.ts): import { v4 as uuidx } from uuid;import emitter from /utils/mittclass Message {// 过期时间,0表示马上就消费exp: number;// 消费标识,避免重复消费tag : string;// 消息体body : any;constructor( exp…

Docker基础篇(六) dockerfile体系结构语法

FROM:基础镜像,当前新镜像是基于哪个镜像的 MAINTAINER :镜像维护者的姓名和邮箱地址 RUN:容器构建时需要运行的命令 EXPOSE :当前容器对外暴露出的端口号 WORKDIR:指定在创建容器后,终端默认登…

python中的类与对象(1)

目录 一. 引子:模板 二. 面向过程与面向对象 (1)面向过程编程 (2)面向对象编程 三. 对象与类 (1)对象 (2)类 四. 面向对象程序设计的特点:封装&#…