数据结构与算法——静态链表及其创建(C语言实现)

news2024/10/4 14:29:41

《顺序表和链表优缺点》里面,我们了解了两种存储结构各自的特点,那么,是否存在一种存储结构,可以融合顺序表链表各自的优点,从而既能快速访问元素,又能快速增加或删除数据元素。

静态链表,也是线性存储结构的一种,它兼顾了顺序表和链表的优点于一身,可以看做是顺序表和链表的升级版。

使用静态链表存储数据,数据全部存储在数组中(和顺序表一样),但存储位置是随机的,数据之间"一对一"的逻辑关系通过一个整形变量(称为"游标",和指针功能类似)维持(和链表类似)。

例如,使用静态链表存储 {1,2,3} 的过程如下:

创建一个足够大的数组,假设大小为 6,如下图所示:

空数组

接着,在将数据存放到数组中时,给各个数据元素配备一个整形变量,此变量用于指明各个元素的直接后继元素所在数组中的位置下标,如下图所示:

静态链表存储数据

通常,静态链表会将第一个数据元素放到数组下标为 1 的位置(a[1])中。

上图中,从 a[1] 存储的数据元素 1 开始,通过存储的游标变量 3,就可以在 a[3] 中找到元素 1 的直接后继元素 2;同样,通过元素 a[3] 存储的游标变量 5,可以在 a[5] 中找到元素 2 的直接后继元素 3,这样的循环过程直到某元素的游标变量为 0 截止(因为 a[0] 默认不存储数据元素)。

类似上图这样,通过 "数组+游标" 的方式存储具有线性关系数据的存储结构就是静态链表。

静态链表中的节点

通过上面的学习我们知道,静态链表存储数据元素也需要自定义数据类型,至少需要包含以下 2 部分信息:

  • 数据域:用于存储数据元素的值;
  • 游标:其实就是数组下标,表示直接后继元素所在数组中的位置;

因此,静态链表中节点的构成用 C 语言实现为:

typedef struct {
    int data;//数据域
    int cur;//游标
}component;

备用链表

上图显示的静态链表还不够完整,静态链表中,除了数据本身通过游标组成的链表外,还需要有一条连接各个空闲位置的链表,称为备用链表。

备用链表的作用是回收数组中未使用或之前使用过(目前未使用)的存储空间,留待后期使用。也就是说,静态链表使用数组申请的物理空间中,存有两个链表,一条连接数据,另一条连接数组中未使用的空间。

通常,备用链表的表头位于数组下标为 0(a[0]) 的位置,而数据链表的表头位于数组下标为 1(a[1])的位置。

静态链表中设置备用链表的好处是,可以清楚地知道数组中是否有空闲位置,以便数据链表添加新数据时使用。比如,若静态链表中数组下标为 0 的位置上存有数据,则证明数组已满。

例如,使用静态链表存储 {1,2,3},假设使用长度为 6 的数组 a,则存储状态可能如下图所示:

备用链表和数据链表

上图中,备用链表上连接的依次是 a[0]、a[2] 和 a[4],而数据链表上连接的依次是 a[1]、a[3] 和 a[5]。

静态链表的创建

假设使用静态链表(数组长度为 6)存储 {1,2,3},则需经历以下几个阶段:

1、在数据链表未初始化之前,数组中所有位置都处于空闲状态,因此都应被链接在备用链表上,如下图所示:

未存储数据之前静态链表的状态

当向静态链表中添加数据时,需提前从备用链表中摘除节点,以供新数据使用。

备用链表摘除节点最简单的方法是摘除 a[0] 的直接后继节点;同样,向备用链表中添加空闲节点也是添加作为 a[0] 新的直接后继节点。因为 a[0] 是备用链表的第一个节点,我们知道它的位置,操作它的直接后继节点相对容易,无需遍历备用链表,耗费的时间复杂度为 O(1)

2、在上图的基础上,向静态链表中添加元素 1 的过程如下图所示:

静态链表中添加元素 1

3、在上图的基础上,添加元素 2 的过程如下图所示:

静态链表中继续添加元素 2

4、在上图的基础上,继续添加元素 3 ,过程如下图所示:

静态链表中继续添加元素 3

由此,静态链表就创建完成了。

下面给出了创建静态链表的 C 语言实现代码:

#include <stdio.h>
#define maxSize 6
typedef struct {
    int data;
    int cur;
}component;
//将结构体数组中所有分量链接到备用链表中
void reserveArr(component *array);
//初始化静态链表
int initArr(component *array);
//输出函数
void displayArr(component * array,int body);
//从备用链表上摘下空闲节点的函数
int mallocArr(component * array);
int main() {
    component array[maxSize];
    int body=initArr(array);
    printf("静态链表为:\n");
    displayArr(array, body);
    return 0;
}
//创建备用链表
void reserveArr(component *array){
    for (int i=0; i<maxSize; i++) {
        array[i].cur=i+1;//将每个数组分量链接到一起
        array[i].data=-1;
    }
    array[maxSize-1].cur=0;//链表最后一个结点的游标值为0
}
//提取分配空间
int mallocArr(component * array){
    //若备用链表非空,则返回分配的结点下标,否则返回 0(当分配最后一个结点时,该结点的游标值为 0)
    int i=array[0].cur;
    if (array[0].cur) {
        array[0].cur=array[i].cur;
    }
    return i;
}
//初始化静态链表
int initArr(component *array){
    reserveArr(array);
    int body=mallocArr(array);
    //声明一个变量,把它当指针使,指向链表的最后的一个结点,因为链表为空,所以和头结点重合
    int tempBody=body;
    for (int i=1; i<4; i++) {
        int j=mallocArr(array);//从备用链表中拿出空闲的分量
        array[tempBody].cur=j;//将申请的空闲分量链接在链表的最后一个结点后面
        array[j].data=i;//给新申请的分量的数据域初始化
        tempBody=j;//将指向链表最后一个结点的指针后移
    }
    array[tempBody].cur=0;//新的链表最后一个结点的指针设置为0
    return body;
}
void displayArr(component * array,int body){
    int tempBody=body;//tempBody准备做遍历使用
    while (array[tempBody].cur) {
        printf("%d,%d ",array[tempBody].data,array[tempBody].cur);
        tempBody=array[tempBody].cur;
    }
    printf("%d,%d\n",array[tempBody].data,array[tempBody].cur);
}

代码输出结果为:

静态链表为:
-1,2 1,3 2,4 3,0

提示,此代码创建了一个带有头节点的静态链表,因此最先输出的 "-1,2" 表示的是头节点(-1表示此处未存储数据),其首元节点(存储元素 1 的节点)在数组 array[2] 中。

2023新版数据结构与算法Java视频教程(上篇),java高级程序员必学的数据结构与算法
2023新版数据结构与算法Java视频教程(下篇),java高级程序员必学的数据结构与算法

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

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

相关文章

【雕爷学编程】Arduino动手做(22)——8X8 LED点阵MAX7219屏7

37款传感器与模块的提法&#xff0c;在网络上广泛流传&#xff0c;其实Arduino能够兼容的传感器模块肯定是不止37种的。鉴于本人手头积累了一些传感器和模块&#xff0c;依照实践出真知&#xff08;一定要动手做&#xff09;的理念&#xff0c;以学习和交流为目的&#xff0c;这…

Java开发中使用sql简化开发

引语&#xff1a; 在Java开发中&#xff0c;我们更希望数据库能直接给我们必要的数据&#xff0c;然后在业务层面直接进行使用&#xff0c;所以写一个简单的sql语句有助于提高Java开发效率&#xff0c;本文由简单到复杂的小白吸收&#xff0c;还请多多指教。 使用MySQL数据库…

GO 语言GC

目录 写屏障 读屏障 GO语言GC准备 堆内存结构: GC内存分配: GC触发&#xff1a; P的作用: 写屏障 实现强弱三色不式,为了避免误删,则实现写屏障. 写屏障是在写操作中插入指令,目的是把数据对象的修改通知到GC GO语言支持两种写屏障 读屏障 非移动垃圾回收(例如 三色)天…

详解c++---智能指针

目录标题 为什么会有智能指针智能指针模拟实现库中的智能指针auto_ptrunique_ptrshared_ptr 智能指针的线程安全问题循环智能指针weak_ptr定制删除器定制删除器的实现 为什么会有智能指针 根据前面的知识我们知道使用异常可能会导致部分资源没有被正常释放&#xff0c;因为异常…

Jupyter入门使用教程

1 Jupyter Notebook与Jupyter Lab简介 Jupyter Notebook是一个开源的Web应用&#xff0c;在深度学习领域非常活跃。用户可以在这里创建和分享可执行代码、可视化结构和注释说明的文档。 Jupyter Notebook以网页的形式展现&#xff0c;用户可以在此网页中直接编辑代码、运行程…

语法怎么学 | 7-非谓语动词

为什么要学非谓语动词 太常见了&#xff0c;非谓语动词可以做句子中&#xff0c;除了谓语的任何成分 是一个非常重要课题&#xff0c;弄懂了这个&#xff0c;就相当于弄懂了语法的90%&#xff0c;特别是语法题 怎样学习 我在小破站上查了不少教程&#xff0c;大多数都很好&…

三种视频字幕提取工具让你更好地阅读和学习

视频字幕提取技术是指通过计算机算法自动从视频中提取出字幕文本的技术。这项技术能够大大提高视频的可用性&#xff0c;使得聋哑人士、语言学习者以及听力不佳的观众可以更好地理解视频内容。那么你知道视频字幕提取工具免费有哪些吗&#xff1f;接下来我将分享三款我亲测好用…

CSDN铁粉是什么?看完这篇你也可以获得忠实铁粉!(详细总结)

&#x1f3ac; 鸽芷咕&#xff1a;个人主页 &#x1f525; 个人专栏:《C语言初阶篇》 《C语言进阶篇》 ⛺️生活的理想&#xff0c;就是为了理想的生活! 文章目录 &#x1f4cb; 前言&#x1f4ac; 什么是铁粉&#x1f3ac; 为什么存在铁粉⁉️ 为什么我的铁粉那么少 &#x1…

Spring【AOP】

AOP-面向切面编程 AOP&#xff1a;面向切面编程&#xff0c;通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。 SpringAop中&#xff0c;通过Advice定义横切逻辑&#xff0c;并支持5种类型的Advice&#xff1a; 导入依赖 <dependency><groupId>…

Linux基础服务11——LNMP架构

文章目录 一、环境说明二、安装nginx三、安装mysql四、安装php五、配置nginx六、配置php七、验证 一、环境说明 主机服务192.168.161.129nginx192.168.161.131mysql192.168.161.132php 二、安装nginx 1.参考文章&#xff0c;nginx部署。 三、安装mysql 1.参考文章&#x…

隐私计算大会亮点前瞻:“隐私计算互联互通标准及第二批实践示范征集项目”解读预告

7月26日&#xff0c;2023隐私计算大会将于青岛正式扬帆&#xff0c;本次大会将齐聚业内专家大咖共论行业最新进展&#xff0c;洞察未来发展趋势&#xff0c;共同推进隐私计算行业蓬勃发展。本次大会将公开正式发布解读《隐私计算应用研究报告&#xff08;2023&#xff09;》、“…

QT6之QtWidgets和QWidget

1、概念 如上图&#xff1a; QtWidgets是模块&#xff0c;它不是类。它与Qt core模块等是同级别的模块&#xff0c;它提供了一系列类的来创建界面相关。QWidget是类&#xff0c;它不是模块。它是所有用户界面对象的基类&#xff0c;QWidget 及其子类是开发桌面应用的核心&…

隐私计算大会亮点前瞻:《隐私计算应用研究报告(2023年)》发布预告

7月26日&#xff0c;2023隐私计算大会将于青岛正式扬帆&#xff0c;本次大会将齐聚业内专家大咖共论行业最新进展&#xff0c;洞察未来发展趋势&#xff0c;共同推进隐私计算行业蓬勃发展。 本次大会将公开正式发布《隐私计算应用研究报告&#xff08;2023&#xff09;》、“隐…

IDEA 安装完成无法打开排查插件问题

以前我自己遇到IDEA&#xff08;19.3&#xff09;突然打不开了、所以写过一篇IDEA无法正常启动&#xff08;打不开&报错&#xff09;_idea启动报错_DJyzh的博客-CSDN博客版权声明&#xff1a;转载请附上文章地址https://blog.csdn.net/qq_42672839IDEA无法正常启动 今天在清…

演讲实录:以 AI 变革组织运营与管理

7月14日&#xff0c;以“释放数智生产力”为主题的 Kyligence 用户大会在上海前滩香格里拉大酒店成功举行。大会现场发布了 Kyligence 最新产品家族&#xff1a;AI 数智助理——Kyligence Copilot 的预览版、一站式指标平台 Kyligence Zen 的 Cloud 和 Enterprise 版本&#xf…

0基础学习VR全景平台篇 第66篇:VR直播-如何管理VR直播活动

一、电脑端管理 已创建好的VR直播活动可以在【管理后台】-【作品管理】-【VR直播】列表下查看到。 1、点击活动标题可以直接进入电脑端的播放页面&#xff0c;点击“编辑”按钮可以进入活动的设置界面。 2、电脑端播放页 该链接地址是可以自适应电脑端和手机端的&#xff0c…

C国演义 [第十二章]

第十二章 打家劫舍题目理解步骤dp数组递推公式初始化遍历顺序 代码 打家劫舍II题目理解步骤递推公式初始化遍历顺序 代码 打家劫舍 力扣链接 你是一个专业的小偷&#xff0c;计划偷窃沿街的房屋。每间房内都藏有一定的现金&#xff0c;影响你偷窃的唯一制约因素就是相邻的房屋…

微服务Day2——Nacos注册中心入门

Nacos注册中心 1、Nacos简介 国内公司一般都推崇阿里巴巴的技术&#xff0c;比如注册中心&#xff0c;SpringCloudAlibaba也推出了一个名为Nacos的注册中心。 2、Mac安装 进入Nacos官网下载安装包 http://nacos.io/zh-cn/ Github仓库地址 下载解压后进入nacos/bin目录下 …

【论文解读】2017 STGCN: Spatio-Temporal Graph Convolutional Networks

一、简介 使用历史速度数据预测未来时间的速度。同时用于序列学习的RNN(GRU、LSTM等)网络需要迭代训练&#xff0c;它引入了逐步累积的误差&#xff0c;并且RNN模型较难训练。为了解决以上问题&#xff0c;我们提出了新颖的深度学习框架STGCN&#xff0c;用于交通预测。 二、…

【云原生|Docker系列第4篇】Docker的容器的入门实践

欢迎来到云原生系列的第4篇博客&#xff01;在前面的两篇博客中&#xff0c;我们已经学习了Docker镜像的基本概念和入门实践。本篇博客将带您深入了解Docker容器&#xff0c;探索如何使用Docker容器来构建、运行和管理应用程序。无论您是新手还是有一定经验的开发者&#xff0c…