【数据结构】链表-1
数组
数组在分配内存的时候需要先告诉系统它有多大,为什么呢?打个比方,我们有以一列的凳子,按顺序排布,一个位置只放一个,数组呢,是一个家庭,数组这个家庭呢,他们得挨着坐,不能分开。如果说,只有一个家庭来的时候,他们想坐哪就可以坐哪,但是呢,倘若在他们来之前就有很多个家庭,那他们就不一定能挨着坐了,他们得先告诉管理员,他们有几个人,管理员才能按照他们的人数多少来给他们分配相应的位置。
链表
同样是坐凳子这一个例子,但列表和数组这个家庭呢不太一样,他们呢,不需要都挨着坐,他们每个人有空位就坐下了。那假如妈妈想要找到她的孩子,又该怎么办呢?机智的妈妈想出了一个好点子,那就是让前一个人记住下一个坐的位置,下一个人再记住下下一个人的位置,通过位置去找寻他们。因此,链表里头每个数据都由两部份组成,分别是自己本身所携带的信息和下一个人的位置,最后一个数据因为没有下一个了,所以它所携带的位置一般为null。
数组VS链表
访问各个元素的成本
- 对于数组而言,我们拿到它的位置,接着按顺序遍历一遍就可以访问到每一个元素了,因此,它的时间复杂度是O(1)
- 对于链表来说,我们通过拿到它第一个位置,按照地址去遍历一遍,假设一共有n个元素,那它的时间复杂度为O(n)
内存的使用
-
对于数组来说,我们想要创建一个大的数组,那我们就得用一块更大的内存空间来承载。假设数组里面的一个数据的大小是4个字节,一共有4个数据,我们的内存空间为7个数据,这就占据了28个字节。还有一种情形就是,内存空间已经填满了,可是数组又想去扩大,那我们只能够创建一块更大的数据空间。
-
对于链表而言,我们不存在什么多余的空间,但每一个数据都要包含一个4字节的地址和一个不知道多少字节的内容。所占内存的大小就是数据量再乘上内容所需的字节与储存地址所需的字节之和。数组和链表两者之间其实并不存在哪一个所占内存大哪一个小,这主要取决于数据量的多少,数组所需内存的字节数,内容所要的字节数,我们进行相应的计算后比对。我们需要根据相应的情形对其进行分析。
插入数据的成本
在开头处进行插入
-
数组:开头插入数据就意味着现有的数据每一个都得后移一个位,因此它的时间复杂度为O(n)
-
链表:开头插入的话,我们就只需要在最前面添加内容,并储存此前第一个数据的位置。
在结尾处插入
-
数组:我们讨论的是动态数组,如果还没填满的话,时间复杂度就是O(1),如果已经填满了,那我们就需要遍历全部数据再在最后的位置添加,此时的时间复杂度是O(N)
-
链表:我们需要遍历一遍数据,再在最后添加一个数据,因此此时的时间复杂度就是O(n)
在中间处插入
无论是数组还是链表,我们都得去遍历到这个数据前面的每一项,因此他们的时间复杂度都为O(n)
简易性
在编程语言中,数组的实现会更为简单,而链表的实现则为比较容易出错和复杂
代码
//创建链表
#define _CRT_SECURE_NO_WARNINGS
#include<stdlib.h>
#include<stdio.h>
//定义节点,节点内包含数据和指向下一个数据的地址
struct Node {int data;struct Node* next;//指针
};
//建一个头,有了头就能找到其他的数据
struct Node* head;//全局变量
void insert(int x) {struct Node* temp = (struct Node*)malloc(sizeof(struct Node)); temp->data = x;temp->next = NULL;if (head != NULL)temp->next = head;head = temp;
}
void print() {struct Node* temp = head;printf("List is:");while (temp != NULL){printf("%d", temp->data);temp = temp->next;}printf("\n");
}
int main() {head = NULL; //空链表//做一个交互,知道要填几个数据 printf("How many numbers do yop want to input\n");//拿一个变量n来接住这个填充数int n;//填入数据scanf("%d", &n);int x;for(int i = 0; i < n; i++) {printf("please input the number\n");scanf("%d", &x);insert(x);print();}}
在ds中给出的示例代码为:
#ifndef LIST_H
#define LIST_H#include <algorithm>
using namespace std;template <typename Object>
class List
{private: // The basic doubly linked list node.// Nested inside of List, can be public// because the Node is itself privatestruct Node{Object data;Node *prev;Node *next;Node( const Object & d = Object{ }, Node * p = nullptr, Node * n = nullptr ): data{ d }, prev{ p }, next{ n } { }Node( Object && d, Node * p = nullptr, Node * n = nullptr ): data{ std::move( d ) }, prev{ p }, next{ n } { }};public:class const_iterator{public:// Public constructor for const_iterator.const_iterator( ) : current{ nullptr }{ }// Return the object stored at the current position.// For const_iterator, this is an accessor with a// const reference return type.const Object & operator* ( ) const{ return retrieve( ); }const_iterator & operator++ ( ){current = current->next;return *this;}const_iterator operator++ ( int ){const_iterator old = *this;++( *this );return old;}const_iterator & operator-- ( ){current = current->prev;return *this;}const_iterator operator-- ( int ){const_iterator old = *this;--( *this );return old;}bool operator== ( const const_iterator & rhs ) const{ return current == rhs.current; }bool operator!= ( const const_iterator & rhs ) const{ return !( *this == rhs ); }protected:Node *current;// Protected helper in const_iterator that returns the object// stored at the current position. Can be called by all// three versions of operator* without any type conversions.Object & retrieve( ) const{ return current->data; }// Protected constructor for const_iterator.// Expects a pointer that represents the current position.const_iterator( Node *p ) : current{ p }{ }friend class List<Object>;};class iterator : public const_iterator{public:// Public constructor for iterator.// Calls the base-class constructor.// Must be provided because the private constructor// is written; otherwise zero-parameter constructor// would be disabled.iterator( ){ }Object & operator* ( ){ return const_iterator::retrieve( ); }// Return the object stored at the current position.// For iterator, there is an accessor with a// const reference return type and a mutator with// a reference return type. The accessor is shown first.const Object & operator* ( ) const{ return const_iterator::operator*( ); }iterator & operator++ ( ){this->current = this->current->next;return *this;}iterator operator++ ( int ){iterator old = *this;++( *this );return old;}iterator & operator-- ( ){this->current = this->current->prev;return *this;}iterator operator-- ( int ){iterator old = *this;--( *this );return old;}protected:// Protected constructor for iterator.// Expects the current position.iterator( Node *p ) : const_iterator{ p }{ }friend class List<Object>;};public:List( ){ init( ); }~List( ){clear( );delete head;delete tail;}List( const List & rhs ){init( );for( auto & x : rhs )push_back( x );}List & operator= ( const List & rhs ){List copy = rhs;std::swap( *this, copy );return *this;}List( List && rhs ): theSize{ rhs.theSize }, head{ rhs.head }, tail{ rhs.tail }{rhs.theSize = 0;rhs.head = nullptr;rhs.tail = nullptr;}List & operator= ( List && rhs ){ std::swap( theSize, rhs.theSize );std::swap( head, rhs.head );std::swap( tail, rhs.tail );return *this;}// Return iterator representing beginning of list.// Mutator version is first, then accessor version.iterator begin( ){ return iterator( head->next ); }const_iterator begin( ) const{ return const_iterator( head->next ); }// Return iterator representing endmarker of list.// Mutator version is first, then accessor version.iterator end( ){ return iterator( tail ); }const_iterator end( ) const{ return const_iterator( tail ); }// Return number of elements currently in the list.int size( ) const{ return theSize; }// Return true if the list is empty, false otherwise.bool empty( ) const{ return size( ) == 0; }void clear( ){while( !empty( ) )pop_front( );}// front, back, push_front, push_back, pop_front, and pop_back// are the basic double-ended queue operations.Object & front( ){ return *begin( ); }const Object & front( ) const{ return *begin( ); }Object & back( ){ return *--end( ); }const Object & back( ) const{ return *--end( ); }void push_front( const Object & x ){ insert( begin( ), x ); }void push_back( const Object & x ){ insert( end( ), x ); }void push_front( Object && x ){ insert( begin( ), std::move( x ) ); }void push_back( Object && x ){ insert( end( ), std::move( x ) ); }void pop_front( ){ erase( begin( ) ); }void pop_back( ){ erase( --end( ) ); }// Insert x before itr.iterator insert( iterator itr, const Object & x ){Node *p = itr.current;++theSize;return iterator( p->prev = p->prev->next = new Node{ x, p->prev, p } );}// Insert x before itr.iterator insert( iterator itr, Object && x ){Node *p = itr.current;++theSize;return iterator( p->prev = p->prev->next = new Node{ std::move( x ), p->prev, p } );}// Erase item at itr.iterator erase( iterator itr ){Node *p = itr.current;iterator retVal( p->next );p->prev->next = p->next;p->next->prev = p->prev;delete p;--theSize;return retVal;}iterator erase( iterator from, iterator to ){for( iterator itr = from; itr != to; )itr = erase( itr );return to;}private:int theSize;Node *head;Node *tail;void init( ){theSize = 0;head = new Node;tail = new Node;head->next = tail;tail->prev = head;}
};#endif
相关文章:
【数据结构】链表-1
数组 数组在分配内存的时候需要先告诉系统它有多大,为什么呢?打个比方,我们有以一列的凳子,按顺序排布,一个位置只放一个,数组呢,是一个家庭,数组这个家庭呢,他们得挨着…...

Python进阶--正则表达式
目录 1. 基础匹配 2. 元字符匹配 1. 基础匹配 正则表达式,又称规则表达式(Regular Expression),是使用单个字符串来描述、匹配某个句法规则的字符串,常被用来检索、替换那些符合某个模式(规则ÿ…...
富格林:发现潜在欺诈安全交易
富格林指出,在全球经济不确定性加剧的背景下,黄金的避险优势再次吸引了投资者的关注。尤其是在今年,随着多种因素的变化,金价的走势引发了市场的广泛讨论。但事实上黄金与其他投资品类相似,也存在潜在的欺诈套路导致我…...

Linux复习--Linux服务管理类(SSH服务、DHCP+FTP、DNS服务、Apache服务、Nginx服务、HTTP状态码)
前言:本博客仅作记录学习使用,部分图片出自网络,如有侵犯您的权益,请联系删除 一、SSH服务 1、问题引出 哪些设置能够提升SSH远程管理的安全等级? 2、SSH的登录验证方式-口令登录 3、SSH的登录验证方式-密钥登录 4、…...

如何用大模型来提升学习效率?
自从2022年底ChatGPT横空出世以来,在过去的十几个月里,生成式人工智能的浪潮席卷并改变着各行各业。 2023年一月,在线课程供应商Study.com曾向1000名18岁以上的学生发起的一项调查显示,当时就已经有超过89%的学生使用ChatGPT来完…...
SQL进阶技巧:如何优雅求解指标累计去重问题?
目录 0 需求概述 1 数据准备 2 问题分析 3 小结 0 需求概述 近期公司开发某项学习功能,改功能有很多学习内容(如java,C,python等方向),每天都会有众多学习用户学习某一项或者多项学习内容。产生数据如下表: 产生数据如下表: 日期 内容 学习用户 2022…...

大数据毕业设计选题推荐-国产电影数据分析-Python数据可视化-Hive-Hadoop-Spark
✨作者主页:IT研究室✨ 个人简介:曾从事计算机专业培训教学,擅长Java、Python、微信小程序、Golang、安卓Android等项目实战。接项目定制开发、代码讲解、答辩教学、文档编写、降重等。 ☑文末获取源码☑ 精彩专栏推荐⬇⬇⬇ Java项目 Python…...

Linux:无法为立即文档创建临时文件: 设备上没有空间
虚拟机磁盘空间不足解决记录 1、问题描述2、问题解决 1、问题描述 在命令行输入命令按Tab键时出现如下报错: 很明显,设备上没有空间,即磁盘空间不足。通过命令查看具体情况如下: df -h2、问题解决 首先想到的是虚拟机扩容。关机虚…...
【SQL】掌握SQL查询技巧:数据筛选与限制
目录 1. DISTINCT:避免重复记录1.1 示意图1.2 使用场景 2. LIMIT:控制查询结果的数量2.1 示意图2.2 使用场景 3. OFFSET:跳过前几行3.1 示意图3.2 使用场景 4. WHERE子句:精细控制数据过滤4.1 示意图4.2 运算符详细说明4.3 基本条…...

大学生社团活动系统小程序的设计
管理员账户功能包括:系统首页,个人中心,学生管理,社长管理,社团分类管理,社团信息管理,社团加入管理,社团活动管理,轮播图信息 微信端账号功能包括:系统首页…...

codetop标签双指针题目大全解析(三),双指针刷穿地心!!!!!
复习比学习更重要,更需要投入时间,更需要花费精力 1.字符串的排列2.找出字符串中第一个匹配的下标3.最大连续1的个数II4.数组中的山脉5.移除元素6.两个数组的交集II7.有序数组的平方8.删除有序数组中的重复项II9.寻找重复数10.水果成篮 1.字符串的排列 …...

HarmonyOS应用六之应用程序进阶一
目录: 1、UIAbility的冷启动和UIAbility热启动2、静态资源和动态资源的访问3、页面跳转3.1、页面返回跳转 4、HAR的ArkUI组件、接口、资源,供其他应用或当前应用的其他模块引用4.1、导出HAR的ArkUI组件4.2、引用HAR的ArkUI组件 5、循环渲染6、状态管理最…...
vue开发中变量第一次双向绑定无效,界面并没有变化,第二次则又好了。
这个问题出现的太频繁了,基本大部分用户都遇到这个情况。大部分是弹框的情况。代码如下: <el-dialog:visible.sync="isShowCode" @close="closeCode()"><div class="u4259f"><edite-edite-code isNoShowClose="true"…...
C++基础(8)——string的相关面试题
目录 1.字符串转成整数 2.字符串相加 3.高精度加法模板(acwing) 4.验证回文串 1.字符串转成整数 题目:将一个字符串转换成一个整数,要求不能使用字符串转换整数的库函数。数值为0或者字符串不是一个合法的数值则返回0。输入的…...

【Docker】06-DockerCompose
1. Docker compose 2. Docker Compose部署项目 docker-compose.yml version: "3.8"services:mysql:image: mysqlcontainer_name: mysqlports:- "3307:3306"environment:TZ: Asia/ShanghaiMYSQL_ROOT_PASSWORD: 123volumes:- "/root/docker/mysql/…...

代码随想录训练营Day27 | 77. 组合 | 216.组合总和III | 17.电话号码的字母组合
学习文档:代码随想录 (programmercarl.com) 视频链接:代码随想录算法公开课 | 最强算法公开课 | 代码随想录 (programmercarl.com) Leetcode 77. 组合 题目描述 给定两个整数 n 和 k,返回范围 [1, n] 中所有可能的 k 个数的组合。 你可以…...

Linux文件重定向文件缓冲区
目录 一、C文件接口 二、系统文件I/O 2.1认识系统文件I/O 2.2系统文件I/O 2.3系统调用和库函数 2.4open( )的返回值--文件描述符 2.5访问文件的本质 三、文件重定向 3.1认识文件重定向 3.2文件重定向的本质 3.3在shell中添加重定向功能 3.4stdout和stderr 3.5如何理…...

训练贪吃蛇ai的后续记录
发现可以结合遗传算法的思路,产生更好的效果。 即每训练一段时间,就停下来测试一下新模型的效果。如果效果优于记录中最好的,则继续导入该模型并训练。重复几次,效果可能更好。 例如,昨晚我便通过唯一一个在十次测试中…...

WPF 手撸插件 八 操作数据库一
1、本文将使用SqlSugar创建Sqlite数据库,进行入门的增删改查等操作。擦,咋写着写着凌乱起来了。 SqlSugar官方文档:简单示例,1分钟入门 - SqlSugar 5x - .NET果糖网 2、环境SqlSugar V5.0版本需要.Net Framework 4.6 ࿰…...

代数结构基础 - 离散数学系列(八)
目录 1. 群(Group) 群的定义 群的示例 2. 环(Ring) 环的定义 环的示例 3. 域(Field) 域的定义 域的示例 域在密码学中的应用 4. 实际应用场景 1. 对称性与加密 2. 误差检测与纠正 3. 数据编码…...

阿里云ACP云计算备考笔记 (5)——弹性伸缩
目录 第一章 概述 第二章 弹性伸缩简介 1、弹性伸缩 2、垂直伸缩 3、优势 4、应用场景 ① 无规律的业务量波动 ② 有规律的业务量波动 ③ 无明显业务量波动 ④ 混合型业务 ⑤ 消息通知 ⑥ 生命周期挂钩 ⑦ 自定义方式 ⑧ 滚的升级 5、使用限制 第三章 主要定义 …...

python/java环境配置
环境变量放一起 python: 1.首先下载Python Python下载地址:Download Python | Python.org downloads ---windows -- 64 2.安装Python 下面两个,然后自定义,全选 可以把前4个选上 3.环境配置 1)搜高级系统设置 2…...

Mybatis逆向工程,动态创建实体类、条件扩展类、Mapper接口、Mapper.xml映射文件
今天呢,博主的学习进度也是步入了Java Mybatis 框架,目前正在逐步杨帆旗航。 那么接下来就给大家出一期有关 Mybatis 逆向工程的教学,希望能对大家有所帮助,也特别欢迎大家指点不足之处,小生很乐意接受正确的建议&…...

理解 MCP 工作流:使用 Ollama 和 LangChain 构建本地 MCP 客户端
🌟 什么是 MCP? 模型控制协议 (MCP) 是一种创新的协议,旨在无缝连接 AI 模型与应用程序。 MCP 是一个开源协议,它标准化了我们的 LLM 应用程序连接所需工具和数据源并与之协作的方式。 可以把它想象成你的 AI 模型 和想要使用它…...

关于iview组件中使用 table , 绑定序号分页后序号从1开始的解决方案
问题描述:iview使用table 中type: "index",分页之后 ,索引还是从1开始,试过绑定后台返回数据的id, 这种方法可行,就是后台返回数据的每个页面id都不完全是按照从1开始的升序,因此百度了下,找到了…...
电脑插入多块移动硬盘后经常出现卡顿和蓝屏
当电脑在插入多块移动硬盘后频繁出现卡顿和蓝屏问题时,可能涉及硬件资源冲突、驱动兼容性、供电不足或系统设置等多方面原因。以下是逐步排查和解决方案: 1. 检查电源供电问题 问题原因:多块移动硬盘同时运行可能导致USB接口供电不足&#x…...
python如何将word的doc另存为docx
将 DOCX 文件另存为 DOCX 格式(Python 实现) 在 Python 中,你可以使用 python-docx 库来操作 Word 文档。不过需要注意的是,.doc 是旧的 Word 格式,而 .docx 是新的基于 XML 的格式。python-docx 只能处理 .docx 格式…...

零基础设计模式——行为型模式 - 责任链模式
第四部分:行为型模式 - 责任链模式 (Chain of Responsibility Pattern) 欢迎来到行为型模式的学习!行为型模式关注对象之间的职责分配、算法封装和对象间的交互。我们将学习的第一个行为型模式是责任链模式。 核心思想:使多个对象都有机会处…...
OpenPrompt 和直接对提示词的嵌入向量进行训练有什么区别
OpenPrompt 和直接对提示词的嵌入向量进行训练有什么区别 直接训练提示词嵌入向量的核心区别 您提到的代码: prompt_embedding = initial_embedding.clone().requires_grad_(True) optimizer = torch.optim.Adam([prompt_embedding...
JVM暂停(Stop-The-World,STW)的原因分类及对应排查方案
JVM暂停(Stop-The-World,STW)的完整原因分类及对应排查方案,结合JVM运行机制和常见故障场景整理而成: 一、GC相关暂停 1. 安全点(Safepoint)阻塞 现象:JVM暂停但无GC日志,日志显示No GCs detected。原因:JVM等待所有线程进入安全点(如…...