数据结构:静态链表(编程技巧)

文章目录

    • 一、理解
    • 二、静态链表
      • 2.1、结构定义
      • 2.2、静态链表的初始化
      • 2.3、操作
      • 2.4、示例
      • 2.5、优点
      • 2.6、缺点
    • 三、例题


链表的元素用数组存储, 用数组的下标模拟指针。

一、理解

在这里插入图片描述
如果有些程序设计语言没有指针类型,如何实现链表?
在这里插入图片描述
  在使用指针类型实现链表时,我们很容易就可以直接在内存中新建一块地址用于创建下一个结点,在逻辑上,我们好像链表是顺序的一样,我们根本不用管他们在内存中是如何存储的,直接“顺序”地遍历即可。
  我们用静态链表,使用数组存储元素和下标,也可以实现逻辑上是顺序的。实际上,我们只需要用数组模拟指针,我们在创建一个新结点时,只需要找到一块“空地”即可创建成功,我们在保证data不动的情况下,直接修改next数组就能实现指针的变换,即一旦创建成功数据的值就存在一个固定的位置,而是通过改变“存指针的数组”来改变指向。我们也不需要去考虑到底存在哪,逻辑上一样可以想象成和普通链表一样的。可以模拟为:

int new_place=find_empty();//找到空地(伪代码) 
data[new_place]=new_data;//利用空地“创建新节点”并赋值
next[last_place]=new_place;//链表中最后一个结点指向该结点
next[new_place]=-1;//新建结点指向为-1

  同理,实现双向循环静态链表,使用left和right数组的下标就可以实现两个左右指针。当然我们可以将其合并为一个结构体,由于空间的局部性,它们可能会被同时使用因此用结构体可能更快:

struct node{int data;int next;
};
node[new_place].data=new_data;
node[last_place].next=new_place;
node[new_place].next=-1;//新建结点指向为-1

  在图论的邻接表中使用非常明显(链式前向星)可跳过这一段:

while(cin>>Vertex>>edge>>cos){//假定输入都是正确的,没有重边//为了复杂化,我们先找到边链表的最后一个结点int adj=head[Vertex];if(adj!=-1)while(next[adj]!=-1){adj=next[adj];}/*创建一个新结点 其之后无指向即next=-1*/VerName.push_back(edge);next.push_back(-1);cost.push_back(cos);/*-adj为Vertex边链表的最后一个元素-*/if(adj!=-1)next[adj]=next.size()-1;//VerName.size()-1、cost.size()-1均可 就是指向最后一个嘛。if(adj==-1){//只可能是顶点还没有边head[Vertex]=next.size()-1;}
}

不过最终需要通过具体语义来实现。

二、静态链表

  静态链表是一种在数组上模拟链表操作的数据结构,它利用数组的索引来代替指针,以此来实现链表的节点间的连接。静态链表特别适合在不支持指针的环境中使用,或者当内存空间非常有限且不允许动态分配内存时的场景。

2.1、结构定义

静态链表通常通过结构体数组来实现。每个结构体元素至少包含两个部分:

  • 数据域:存储链表节点的数据。
  • 游标(或称为next索引):存储下一个节点的索引位置。

在C++中,静态链表的节点可以这样定义:

struct Node {int data; // 数据域int next; // 游标,存储下一个元素的索引
};

2.2、静态链表的初始化

静态链表的初始化涉及到设置一个固定大小的数组,并初始化next索引。一般会有一个特殊的头节点(head),其next索引指向链表的第一个元素,如果链表为空,则指向-1或链表的末尾标识。

2.3、操作

静态链表的基本操作与普通链表类似,包括插入、删除和查找等,但操作方式通过数组索引来实现。

  • 插入操作:在指定位置插入一个新的节点,需要修改该位置前一个节点的next值指向新节点,新节点的next值指向原先该位置的节点。
  • 删除操作:删除指定位置的节点,需要修改该位置前一个节点的next值,让它直接指向被删除节点的下一个节点。
  • 查找操作:从头节点开始,逐个跟随next索引遍历直到找到目标节点。

2.4、示例

假设我们有一个静态链表来存储整数,可以这样表示:

Node nodes[MAX_SIZE]; // 静态链表的数组表示
int head = -1; // 初始化头节点的next索引为-1,表示链表为空

2.5、优点

  • 空间利用率高:在连续的内存空间中模拟链表,避免了指针的额外空间消耗。
  • 适用于静态存储管理:当内存分配不允许使用动态分配时,静态链表是一种有效的选择。

2.6、缺点

  • 固定大小:静态链表的最大大小在编译时就确定了,这限制了其动态扩展的能力。
  • 操作复杂度:与动态链表相比,静态链表在插入和删除操作时可能需要更多的步骤来更新索引。

静态链表是一种特殊场景下的解决方案,它展示了数据结构在不同约束下的灵活应用。在现代编程实践中,由于动态内存管理的广泛支持,静态链表的使用场景相对较少,但理解其原理对学习数据结构的基本概念非常有帮助。

三、例题

例题:有若干个盒子,从左至右依次编号为
1,2,3,…,n。可执行以下指令(保证X不等于Y):
➢L X Y表示把盒子X移动到盒子Y左边(如果X
已在Y左边,则忽略该指令)。
➢R X Y表示把盒子X移动到盒子Y右边(如果X
已在Y右边,则忽略该指令)。

这里使用双向循环链表来实现。

vector<int> data(n+1);//留出一个头结点
vector<int> left(n+1);
vector<int> right(n+1);
for(int i=1;i<=n;++i){data[i]=i;//创建结点并赋值    if(i!=1)left[i]=i-1;//初始化左指针指向前一个结点(用下标模拟指针)else left[i]=n;if(i!=n)right[i]=i+1;//初始化左指针指向后一个结点(用下标模拟指针)else right[i]=1;
}
while(cin>>Direct>>x>y){//x和y虽然是盒子编号,但是data[x]就是盒子x,所以left[x]就是盒子x左边指向的盒子if(Direct=='L'||Direct=='R')if(Direct=='L'){while(right[x]!=y){//右边指向的盒子不等于y  1--2--1--2right[left[x]]=right[x];left[right[x]]=left[x];left[x]=right[x];right[x]=right[left[x]];left[right[x]]=x;right[left[x]]=x;}}else{while(left[x]!=y){right[left[x]]=right[x];left[right[x]]=left[x];right[x]=left[x];left[x]=left[left[x]];right[left[x]]=x;left[right[x]]=x;}}
}
int i=1;
while(i!=-1){cout<<"盒子编号:"<<data[i]<<endl;i=right[i];
}

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

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

相关文章

电气识图基础

1 电气系统组成 电气系统分为强电系统和弱电系统。 强电系统有变配电系统,照明系统,动力系统,接地系统。弱电系统有消防报警系统,安全防范系统,楼宇自控系统等等。强电和弱电的区别? 在非电力工程领域。强电和弱电是以电压分界的,工作在交流220伏以上为强电,以下为弱电…

【目标跟踪】红绿灯跟踪

文章目录 一、前言二、结果三、跟踪3.1、检测输入3.2、预测与运动补偿3.3、第一次匹配3.4、第二次匹配3.5、第三次匹配3.6、航迹的起始与信息的发布 四、后记 一、前言 红绿灯场景对当前无人驾驶来说是个灾难性的挑战。暂且不说复杂的十字路口&#xff0c;譬如简单的人行道红绿…

马上蓝桥杯了,干货总结动态规划专题,祝你考场爆杀(拔高篇)最佳课题选择 书本整理 打鼹鼠 吃吃吃 非零字段划分

目录 最佳课题选择 思路&#xff1a; 书本整理 思路&#xff1a; 打鼹鼠 思路&#xff1a; 吃吃吃 思路&#xff1a; 非零字段划分 最佳课题选择 思路&#xff1a; 根本还是论文的分配&#xff0c;每个课题分配多少个论文是不确定的&#xff0c;这个也是很影响转…

天梯算法Day3整理

浮点数解析 炸鱼题掠过 冲突值 题面 解析 方法一 —— 并查集 按照边值排序&#xff0c;然后按边值从大到小遍历&#xff0c;通过并查集判断能否将所有点无冲突地归于两个集合。在判断时&#xff0c;若有两个点不得不产生冲突&#xff0c;则输出这两个点之间的边值并结束。…

PLC通讯时如何判断选用MODBUS方式还是现场总线方式?

在工业自动化领域&#xff0c;PLC扮演着至关重要的角色。然而&#xff0c;许多人在初次接触PLC通讯时&#xff0c;常因其复杂性而感到困扰。事实上&#xff0c;PLC的通讯并不如人们想象中的那么神秘&#xff0c;它主要只有两种类型&#xff1a;一种是需要编写代码的通讯方式&am…

Verilog语法之assign语句学习

assign语法主要是对组合逻辑的变量进行赋值的&#xff0c;就是把一个变量赋值给另一个变量&#xff0c;被复制的变量必须是wire类型的参数。 从仿真结果可以看出&#xff0c;data_in变量的值赋值给了data_out,assign语法就是赋值没有任何延迟&#xff0c;data_in是什么值&#…

服务器被挖矿了怎么办,实战清退

当我们发现服务器资源大量被占用的时候&#xff0c;疑似中招了怎么办 第一时间重启服务是不行的&#xff0c;这些挖矿木马一定是会伴随着你的重启而自动重启&#xff0c;一定时间内重新霸占你的服务器资源 第一步检查高占用进程 top -c ps -ef 要注意这里%CPU&#xff0c;如果…

[Python人工智能] 四十五.命名实体识别 (6)利用keras构建CNN-BiLSTM-ATT-CRF实体识别模型(注意力问题探讨)

从本专栏开始,作者正式研究Python深度学习、神经网络及人工智能相关知识。前文讲解融合Bert的实体识别研究,使用bert4keras和kears包来构建Bert+BiLSTM-CRF模型。这篇文章将详细结合如何利用keras和tensorflow构建基于注意力机制的CNN-BiLSTM-ATT-CRF模型,并实现中文实体识别…

【MySQL】16.事务管理(重点) -- 2

1. 事务隔离级别 如何理解隔离性1 MySQL服务可能会同时被多个客户端进程(线程)访问&#xff0c;访问的方式以事务方式进行一个事务可能由多条SQL构成&#xff0c;也就意味着&#xff0c;任何一个事务&#xff0c;都有执行前&#xff0c;执行中&#xff0c;执行后的阶段。而所…

Linux 动静态库的制作,使用和加载

Linux 动静态库的制作,使用和加载 一.前置说明1.mylib.h2.mylib.c3.mymath.h mymath.c4.如何制作库 二.动静态库的制作1.静态库的制作1.制作2.使用一下静态库,验证是否成功打包 2.动态库的制作1.编译.c源文件文件生成.o目标文件2.打包生成动态库3.编写makefile文件,自动化制作动…

【SpringCloud】Ribbon负载均衡

&#x1f3e1;浩泽学编程&#xff1a;个人主页 &#x1f525; 推荐专栏&#xff1a;《深入浅出SpringBoot》《java对AI的调用开发》 《RabbitMQ》《Spring》《SpringMVC》《项目实战》 &#x1f6f8;学无止境&#xff0c;不骄不躁&#xff0c;知行合一 文章目录 …

警惕.360勒索病毒:如何预防.360勒索病毒攻击

导言&#xff1a; 在网络安全领域&#xff0c;勒索病毒是一种非常危险的恶意软件&#xff0c;它以其独特的加密方式和高昂的赎金要求&#xff0c;给个人和企业带来了严重的损失。.360勒索病毒便是其中之一&#xff0c;它属于BeijingCrypt勒索病毒家族&#xff0c;具有高度的隐…

NO12 蓝桥杯单片机之DS1302的使用

1 DS1302是什么 DS1302由两块存储器组成&#xff0c;一个是日历时钟寄存器还有一个是31位的静态RAM存储器。 而在蓝桥杯中常考的就是日历时钟寄存器&#xff0c;故这里只介绍日历时钟寄存器。简单来说&#xff0c;其就是一个“电子表”&#xff0c;他会自动的实时记录时间&am…

Suno - AI自动作曲

文章目录 关于 Suno创作歌词结构曲风 关于 Suno Suno 是一款自动编曲工具。 官网 &#xff1a;https://www.suno.ai Suno is building a future where anyone can make great music. Whether you’re a shower singer or a charting artist, we break barriers between you …

关于Devc++调试的问题以及解决STL变量无法查看

目前Devc的调试主要有以下几点&#xff1a; 1.调试不能直接查看stl变量&#xff0c;会卡死不动 2.目前单步进入只能用鼠标键按 3.若想按下一步进入函数体内&#xff0c;要在函数体内打上断点才行 4.调试到return 0 ;上一句就停了&#xff0c;不会结束程序 5.目前F2跳至断点…

matplotlib 绘图

matplotlib 绘图 方便设置legend图例的位置 ax1.legend(loc‘upper center’, bbox_to_anchor(0.3, -0.1)) ax2.legend(loc‘upper center’, bbox_to_anchor(0.6, -0.1)) import numpy as np import matplotlib.pyplot as plt from scipy.stats import norm from scipy.inter…

SpringBoot Redis的使用

官方文档&#xff1a; 官方文档&#xff1a;Spring Data Redis :: Spring Data Redis 和jedis一样&#xff0c;SpringBoot Redis 也可以让我在Java代码中使用redis&#xff0c;同样也是通过引入maven依赖的形式。 加速访问github: 使用steam可以免费加速访问github Spring…

HarmonyOS实战开发-目标管理、如何实现一个自定义弹窗。

介绍 本篇Codelab将介绍如何使用State、Prop、Link、Watch、Provide、Consume管理页面级变量的状态&#xff0c;实现对页面数据的增加、删除、修改。要求完成以下功能&#xff1a; 实现一个自定义弹窗&#xff0c;完成添加子目标的功能。实现一个可编辑列表&#xff0c;可点击…

Android14之深入理解sp模板类(二百零二)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 优质专栏&#xff1a;Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 优质专栏&#xff1a;多媒…

Android R 广播注册与发送流程分析

静态广播注册时序图 动态广播注册时序图 发送广播时序图 前言 广播接收器可以分为动态和静态&#xff0c;静态广播接收器就是在 AndroidManifest.xml 中注册的&#xff0c;而动态的广播接收器是在代码中通过 Context#registerReceiver() 注册的。 这里先从静态广播的流程开始…