数据结构漫游记:静态链表的实现(CPP)

server/2024/12/26 2:08:54/

嘿,各位技术潮人!好久不见甚是想念。生活就像一场奇妙冒险,而编程就是那把超酷的万能钥匙。此刻,阳光洒在键盘上,灵感在指尖跳跃,让我们抛开一切束缚,给平淡日子加点料,注入满满的passion。准备好和我一起冲进代码的奇幻宇宙了吗?Let's go!

我的博客:yuanManGan

我的专栏:C++入门小馆 C言雅韵集 数据结构漫游记  闲言碎语小记坊

之前我们了解到动态链表的实现感兴趣的可以点点链接看一看

数据结构漫游记:动态链表的实现-CSDN博客

静态链表的认识

我们知道链表有两部分组成

一部分是数据域

一部分是指针域

我们动态实现链表时每次都会为新的链表申请空间,会搞得很麻烦代码量也很高,运行的时间也会很高,但静态实现完美的解决了这个问题。

我们是不是可以用空间很大的数组来分开存储指针和指针呢?

用数组的下标来找到每个结点。

静态链表的实现

定义两个数组分别为e和ne存储数据和指针。再用h指向哨兵位(指第一个不存储任何有效数据的结点),id指向最后一个结点。

这是有人就会问了你这个ne数组是不是多余了,我靠一个一个下标就能找到下一个元素啊,根本用不到ne数组啊

小伙子你想的太天真了,那你来实现下面这个呢?

 如果你画出来这个结构会发现是A-》D-》E,C去哪里啦?每次C是无效数据,可能被删除了


创建空链表

const int N = 1e5 + 10;int ne[N], e[N]; // 创建两个很大的数组int id, h;int main()
{return 0;
} 

注意这里将数组放在全局变量有两个好处,一个是全局变量的内存更大,溢出问题更少出现;另一个是数组等变量不初始化放在main函数外会自动初始化为0。

这就实现了第一步创建空链表

头插

无论是头插还是什么基本的思路都和动态的链表无二。我们需要先将新结点指向下一个结点,再将哨兵位的指针指向新节点。顺序不能搞错,不然就不能找到下一个结点了。

代码实现:

void push_front(int x)
{id++;//指向下一个空的位置//处理新结点e[id] = x;//存储数据ne[id] = ne[h];//处理哨兵位ne[h] = id;
}

遍历链表打印

遍历链表的思路就是,定义一个指针cur令cur =ne[cur]直到cur等于0就结束了。也和动态链表的思路大差不差。

实现:

void print()
{for (int i = ne[id]; i; i = ne[i]){cout << e[i] << " ->";}cout << endl << endl;
}

按值查找

实现按值查找一种方法就是遍历链表然后一个一个找,但这种做法时间复杂度是O(N)。这里我们可以先创建一个mp数组,以存储的数据为下标存储每个元素的地址。


const int N = 1e5 + 10;int ne[N], e[N]; // 创建两个很大的数组int id, h;int mp[N];int main()
{return 0;
} 

然后在插入元素时储存元素的下标

void push_front(int x)
{id++;//指向下一个空的位置//处理新结点e[id] = x;//存储数据ne[id] = ne[h];//处理哨兵位ne[h] = id;//标记新结点的位置mp[x] = id;
}

就可以实现find函数了

int find(int x)
{/*int i = ne[h];while (i){if (e[i] == x) return i;i = ne[i];}return 0;*/return mp[x];
}

注释部分是第一种方法。

这里有一个弊端,当存储两个相同的数时,mp数组就不知道存储谁的下标,当没有重复的数据时使用这个方法的时间复杂度是O(1),大大的优化。

在任意位置之后处插入数据

这个功能要传入的数据是某个位置的下标,如果传入的是数据,也得转化为下标来计算,这个位置之后的插入就和头插的执行过程差不多,这里就简单带过咯

void push_front(int p,int x)
{id++;//指向下一个空的位置//处理新结点e[id] = x;//存储数据ne[id] = ne[p];//处理p位置ne[p] = id;//标记新结点mp[x] = id;
}

这里就是把h换成了p。

删除任意位后的数据

删除下一个位置就是将这个位置的下一个指针指向下下个元素。

实现也很简单

void erase(int p)
{if(ne[p]) // 当 p 不是最后一个元素的时候{mp[e[ne[p]]] = 0; // 把标记清空ne[p] = ne[ne[p]];}
}

注意这里的p不能是最后一个元素哦!

这里不实现尾插,在任意位置之前插入,删除任意位置的原因很简单,相对与这些代码要复杂一点,并且时间复杂度都基本上是O(n),我们可以使用其他的数据结构来实现。

比如下期我要写的循环链表,请大家敬请期待!谢谢! ~


http://www.ppmy.cn/server/153198.html

相关文章

postgreSql对分钟级的降雨数据进行插值为整小时

postgreSql对分钟级的降雨数据进行插值为整小时 SQL语句实现 SQL语句实现 --核查某个小流域的降雨量小时插值是否正确SELECT tm, sum(drp) as sum, round(sum(drp), 2) as drp2 from(SELECT a.stcd, (TO_TIMESTAMP(time_period, YYYY-MM-DD HH24:MI:SS) INTERVAL 1 HOUR) as t…

解决“SVN无法上传或下载*.so、*.a等二进制文件“问题

今天&#xff0c;在使用Subversion提交代码到服务器时&#xff0c;发现无法提交*.a、*.so等二进制文件&#xff0c;右击这些文件&#xff0c;发现其属性为ignores。     问题原因&#xff1a;SVN的配置文件里&#xff0c;屏蔽了*.a、*.so文件的上传与下载&#xff0c;并把这些…

04、Vue与Ajax

4.1 发送AJAX异步请求的方式 发送AJAX异步请求的常见方式包括&#xff1a; 4.1.1. 原生方式 使用浏览器内置的JS对象XMLHttpRequest const xhr new XMLHttpRequest() xhr.open() xhr.send() xhr.onreadystatechange function(){} 4.1.2. 原生方式 使用浏览器内置的JS函…

mac 上安装Selenium + 谷歌浏览器驱动 116.0.5845.x

1、本地安装Selenium pip install selenium pip show selenium 2、安装谷歌驱动 &#xff08;1&#xff09;驱动地址 https://chromedriver.storage.googleapis.com/index.html &#xff08;2&#xff09;查看谷歌版本 &#xff08;3&#xff09;选择驱动并下载 上述没有我…

ISO17025最新认证消息

ISO17025认证是国际上广泛认可的实验室管理标准&#xff0c;全称为《检测和校准实验室能力的通用要求》&#xff0c;由国际标准化组织&#xff08;ISO&#xff09;和国际电工委员会&#xff08;IEC&#xff09;联合发布。以下是对ISO17025最新认证消息及相关内容的归纳&#xf…

设计模式——组合模式

文章目录 1.定义2. 结构组成3. 组合模式结构4. 示例代码5. 模式优势6. 应用场景 1.定义 组合模式是一种设计模式&#xff0c;它允许将对象组合成树形结构来表示 “部分 - 整体” 的层次关系&#xff0c;使得客户端可以统一地处理单个对象和对象组合&#xff0c;而无需区分它们…

深度解析 Pytest 中的 conftest.py

关注开源优测不迷路 大数据测试过程、策略及挑战 测试框架原理&#xff0c;构建成功的基石 在自动化测试工作之前&#xff0c;你应该知道的10条建议 在自动化测试中&#xff0c;重要的不是工具 在使用 Pytest 进行测试的过程中&#xff0c;conftest.py 文件扮演着极为重要的角色…

【bWAPP】XSS跨站脚本攻击实战

别低头&#xff0c;皇冠会掉&#xff1b;别流泪&#xff0c;贱人会笑。 0x01、XSS - Reflected (GET) Low 输入的内容直接输出到页面中: 后台服务端没有对输入的参数进行过滤, 构造一个注入xss payload即可: <script>alert(1)</script> 成功弹窗 Medium 审查…