6.2 链表

6.2 链表

首先还是一个问题,什么叫做链表呢?

我们已经学过了数组,和很多的容器,不过可以知道的是,无论选用什么样的容器,里面存储的元素都是按照下标顺序,连续地存储在开辟的空间里。
在这里插入图片描述

链表,在这里又可称为线性表的链式存储,是一种非顺序的存储结构。每个数据元素在存储的同时,要配备一个指针,用于指向它的直接后继元素,即每一个数据元素都指向下一个数据元素(最后一个指向NULL(空))

在这里插入图片描述
每个元素本身由两部分组成:

1.本身的信息,称为数据域
2.指向后继的指针(下标),称为指针域

这两部分信息组成数据元素的存储结构,称之为“结点”。n个结点通过指针域相互链接,组成一个链表。

每个结点只包含一个指针域,生成的链表,我们即可称为线性链表或者单链表。

头结点:有时,在链表的第一个结点之前会额外增设一个结点,结点的数据域一般不存放数据(有些情况下也可以存放链表的长度等信息),此结点被称为头结点。

首元结点:链表中第一个元素所在的结点,它是头结点后边的第一个结点。

头结点:永远指向链表中第一个结点的位置(如果链表有头结点,头指针指向头结点;否则,头指针指向首元结点)。
在这里插入图片描述
数组比较省空间,并且在查询一个元素的时候更加优势,但是删除一个元素,或者添加一个元素时的时间复杂度为o(n),链表的话插入数据和删除数据就比较快,不过查询的时候比较麻烦,空间开销也比较大。


6-4 破损的键盘 (UVA 11988)

你有一个破损的键盘(哎我知道它坏了,我就是不换,就是玩)。键盘上的所有键都是可以正常工作的,但有时Home键或者End键会自动按下。但是你不知道发生了这个情况,你在专心打稿子,甚至显示器都没有开(有眼睛我不用,就是玩)。你的任务就是在打开显示之前计算出这段悲剧文本。

输入一个长度不超过100000个字母,下划线,字符“[”和“]”,其中“[”表示Home键,“]”表示End键,输出对应的文本。

例如:
输入:This_is_a_[Beiju]_text
输出:BeijuThis_is_a__text

分析:不会有人不知道编辑文本时,Home和End是干嘛用的吧?我这里解释一下,当你进行文本编辑时,Home会将光标移动到文本的最开始,同理,End会将光标移动到最后。

最简单的想法就是用一个数组去保存这个文本,pos表示光标位置。然后Home表示在文本前进行插入。(将后面的字符全部右移)

但这样做会超时,因为前面说了,数组插入元素的复杂度为o(n),极端情况下,250000的a和[交替出现,操作次数会超过6*1012次。

这里使用我们刚刚学的链表:

准备条件:

int next[250000];//next表示指针域,这里的next[i]表示s的第i个字符
//同时next[i]通过不断地迭代,从0到1到2最后到文本的结束 
int last=0,pos=0;//last表示当前文本的末尾光标,pos表示当前光标所在位置 
char s[250000];//这道题的数据量比较大,为了节省时间考虑用char数组

遇到方括号的两种情况:

if (s[i]=='[') pos=0;//home,光标移至队首
		else if (s[i]=']') pos=last;//end,光标移至队尾

接下来我自己写的时候,写下来这三行代码:

	next[pos]=i+1;//指针里存入地址
	if (pos==last) last=i+1;//update最后一个字符的光标位置
	pos=i+1;//移动光标 

表示更新pos和last的值,并且存入当前字符数据的指针,但结果始终不对。后来发现链表最为关键的一点在于,指针不是像数组一样连续排序的,而是通过上一个指针去指向下一个结点的数据,然后通过类似于映射的方法,得到下一个结点的指针,再去指向下一个结点·······

也就是说这里缺少了指针的互相连接:

//建立上一个pos到这一个pos的联系 
next[i+1]=next[pos];

就这两行代码,我看了一个下午都看不明白它的实际意义,然后我把i用后面的next[pos]代替:

next[next[pos]]=next[pos]

这一下就很清晰了。

完整代码如下:

#include<cstring>
#include<iostream>
using namespace std;
int next[250000];//next表示指针域,这里的next[i]表示s的第i个字符
//同时next[i]通过不断地迭代,从0到1到2最后到文本的结束 
int last=0,pos=0;
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值