数组实现单链表和双链表

news/2024/11/26 6:32:34/

全文目录

  • 😀 数组实现的优势
  • 🤔 单链表
    • 😕 初始化
    • 😕 头插
    • 😕 在下标 `k` 后面插入元素
    • 😕 删除下标 `k` 后面的元素
    • 😕 遍历
  • 😵‍💫 双链表
    • 🤨 初始化
    • 🤨 插入
    • 🤨 删除元素
    • 🤨 遍历

😀 数组实现的优势

链表在很多语言的标准库里面都有,基本上是通过 Node 节点来链接下一个节点实现的:

struct Node
{int _data;Node* _next;Node* _prev;    // 双链表
}

这样的链表使用起来虽然方便,但是有两个缺点:

  1. 空间更大,因为有内存对齐的存在
  2. 如果有大量的节点,那么会在耗费大量的时间来开辟节点,效率低

所以一般,如果数据是整数的话可以使用数组来代替链表,可以大幅度地提升效率。

🤔 单链表

通过数组实现,需要用到两个数组,一个用来存放数据 e[],一个用来存放下一个节点的下标 ne[],一个用来标记头结点的位置 head,一个用来标记下一个需要用到的位置 index

实现的样子大概是这样:

在这里插入图片描述

😕 初始化

void init()
{head = 0;index = 1;
}

同样也可以 head = -1, index = 0 来进行初始化,但是这样的话,后面的操作下标都需要 -1 ,所以个人感觉 上一种方式处理起来更加方便。

😕 头插

void add_head(int x)
{e[index] = x;ne[index] = head;head = index;index ++;
}

这里需要清楚的是,如果是没有数据的话,那么节点一定是头插的。这样才能保证 head 的更新和顺利找到尾结点。

😕 在下标 k 后面插入元素

void add(int k, int x)
{e[index] = x;ne[index] = ne[k];ne[k] = index;index ++;
}

😕 删除下标 k 后面的元素

void remove(int k)
{ne[k] = ne[ne[k]];
}

😕 遍历

for (int i = head; i; i = ne[i])
{cout << e[i] << ' ';
}

遍历可能会有一些误导,需要找到初始化的 head 才算是到了尾,

首先这个head指的是链表中头节点的下标,当链表中没有节点时head = 0,但当链表中有值插到头节点的时候,head储存的就是这个值的idx1,通过e[idx1]可以求出这个节点的值。而ne[idx1]就等于head之前的值,即0。如果再在头节点插入一个元素,则head指向这个元素的idx2,而ne[idx2]就等于上一次插入的head值,即idx1。此时,head = idx2,ne[idx2] = idx1,ne[idx1] = 0。若真正理解了这个过程,你的问题就迎刃而解了。拿上述链表举例,在循环链表时,初始的i = head,除非链表为空,否则这个head的值一定不为0,其值应为链表中第一个节点的idx2值,输出e[i]后,有i = ne[i],其含义为i = ne[dix2],由上述论证可知,ne[idx2] = idx1,则i = idx1,满足i != 0,输出e[i]的值。又有i = ne[i],即为i = ne[idx1],可知ne[idx1] = 0,则i = 0,不满足i != 0的循环条件,故循环退出。这个链表的循环依次输出了e[idx2]e[idx1],即链表中的前后两个节点。


😵‍💫 双链表

因为双链表有左右两个指针,所以在实现的时候需要三个数组,一个存储元素 e[],一个存储左节点的下标 l[],一个存储右节点的下标 r[]index 表示用到的下标。

🤨 初始化

初始化数组时,给定左边界和右边界。头结点是从左边界的下一个开始,尾结点就是右边界的前一个。这样可以方便头插和尾插,所以就给定 0为左边界, 1 为右边界, index 从2开始。

因为 index 是从2开始的,所以后面的关于下标的操作都需要加上1

// 初始化
void init()
{r[0] = 1;   // 头结点l[1] = 0;   // 尾结点index = 2;  // 元素的下标从2开始,后面的下标也都需要+1
}

这样初始化可能会觉得很变扭,有点违背我们的思维方式,就会想index能不能从1开始,右边界取2。

答案是不能的,这样会导致index在向后走的时候可能取到右边界,那么对index 进行操作就会导致右边界发生变化。所以要保证 index 不能取到右边界。

🤨 插入

因为是双链表,可以直接找到前一个节点,所以在 k 的左边插入可以表示成在 k 的前一个节点的后面插入,头插就是在左边界的后面插入,尾插就是在右边界的前一个节点后面插入。因此只实现一个插入就好了。

// 在当前节点的后面插入
void insert(int k , int x)
{e[index] = x;   r[index] = r[k];l[index] = k;l[r[k]] = index;r[k] = index;index++;
}头插:insert(0, x);   // 头插就是在头结点的右边插入尾插:insert(l[1], x);    // 尾插就是在尾结点的左边插入在k的左边插入:insert(l[k + 1], x);    // 在左节点的后面插入在k后插入:insert(k + 1, x);    // 正常插入

🤨 删除元素

// 删除当前节点
void remove(int k)
{r[l[k]] = r[k]; l[r[k]] = l[k];
}

🤨 遍历

同样的,双链表的遍历只要找到右边界的位置就好了

for (int i = r[0]; i != 1; i = r[i])
{cout << e[i] << ' ';
}

完结散花🌈🌈🌈

在这里插入图片描述


http://www.ppmy.cn/news/2347.html

相关文章

什么事Jupyter Notebook?

Jupyter Notebook是基于网页的用于交互计算的应用程序。其可被应用于全过程计算&#xff1a;开发、文档编写、运行代码和展示结果。 简而言之&#xff0c;Jupyter Notebook是以网页的形式打开&#xff0c;可以在网页页面中直接编写代码和运行代码&#xff0c;代码的运行结果也…

如何使用Python连接数据库

数据分析离不开数据库&#xff0c;如何使用python连接数据库呢&#xff1f;听我娓娓道来哈 补充&#xff1a;文末增加Oracle数据库的连接方式&#xff0c;大同小异。 背景&#xff1a; 我是在Anaconda notebook中进行连接实验的&#xff0c;环境Python3.6&#xff0c;当然也…

手把手教你打造一款个人专属Android桌面

实现方式两种 1.从头到尾写一个apk然后把系统的属性加上去&#xff0c;然后启动的时候默认就指定到这个apk的包名&#xff0c;他就启动&#xff0c; 2.我们基于Androidlauncher3的源码去做一个定制化的修改 分析一下这两种的区别&#xff0c; 自定义&#xff0c;要有丰富的…

软件测试——用例

一、测试用例 1.定义 向被测试系统发起的一组集合&#xff0c;包含测试环境、测试步骤、测试数据、预期结果 2.为什么软件测试人员要写测试用例&#xff1f; &#xff08;1&#xff09;测试用例是测试执行的依据 &#xff08;2&#xff09;测试用例可以复用&#xff0c;在进行回…

springboot构建RESTful 风格应用

Spring Boot 构建 RESTful 风格应用 1.Web开发的两种模式&#xff1a; 前后端不分离&#xff1a; 以前没有移动互联网时&#xff0c;我们做的大部分应用都是前后端不分的&#xff0c;比如jsp&#xff0c;或者thymeleaf等后端分离模板&#xff0c;在这种架构的应用中&#xf…

Spring Cloud Alibaba整合Sentinel进行服务熔断降级

一、下载Sentinel Dashboard控制台服务 Releases alibaba/Sentinel GitHub 一样的&#xff0c;根据自己的Spring Cloud Alibaba版本下载相应版本的Sentinel 启动服务&#xff0c;可以指定端口 java -Dserver.port8849 -Dcsp.sentinel.dashboard.serverlocalhost:8849 -Dp…

vue学习笔记(一)-vue基础语法

视频教程&#xff1a;尚硅谷Vue2.0Vue3.0全套教程丨vuejs从入门到精通_哔哩哔哩_bilibili 相关文档&#xff1a;Vue核心 Vue简介 初识 (yuque.com) 兼容性 Vue 不支持 IE8 及以下版本&#xff0c;因为 Vue 使用了 IE8 无法模拟的 ECMAScript 5 特性。但它支持所有兼容 ECMAS…

led台灯哪个牌子效果最好?2022最新国产led灯品牌排行

目前台灯的发展非常迅速&#xff0c;已经到了全面led灯的时代&#xff0c;传统的卤素灯已经近乎完全淘汰&#xff0c;这不仅仅是跟技术的发展有关&#xff0c;也跟led灯本身的优势有关&#xff0c;各方面很适合做成护眼灯。 护眼灯为什么都是led灯&#xff1f; 护眼台灯使用le…