算法简介
1.什么是链表?
链表是一种物理存储单元上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。链表由一系列结点(链表中每一个元素称为结点)组成,结点可以在运行时动态生成。每个结点包括两个部分:一个是存储数据元素的数据域,另一个是存储下一个结点地址的指针域。链表有很多种不同的类型:单向链表,双向链表以及循环链表。
2.链表结构的优点
相比较普通的线性结构,链表结构的优点非常突出:
- 单个结点创建(插入)非常方便,普通的线性内存通常在创建的时候就需要设定数据的大小,而链表可以在 O ( 1 ) O(1) O(1)的时间复杂度里实现;
- 结点的删除*非常方便,不需要像线性结构那样移动剩下的数据,同样可以在 O ( 1 ) O(1) O(1)的时间复杂度里实现;
- 结点的访问方便,可以通过循环或者递归的方法访问到任意数据;
3.链表结构的缺点
.相比较普通的线性结构,链表结构的缺点也很明显:
- 链表平均的访问效率较低。
- 链表结构的调试相对复杂。
单向链表
例题 1 UVA11988 破损的键盘 Broken Keyboard (a.k.a. Beiju Text)
思路
本题采用单向链表解决。每输入一个字符就把它存起来,设输入字符串是 s [ 1 ~ n ] s[1~n] s[1~n],则可以用 n e x t [ i ] next[i] next[i]表示在当前显示屏中 s [ i ] s[i] s[i]右边的字符编号(即在 s s s中的下标)。
为了方便起见,假设字符串s的最前面还有一个虚拟的 s [ 0 ] s[0] s[0],则 n e x t [ 0 ] next[0] next[0]就可以表示显示屏中最左边的字符。再用一个变量 c u r cur cur表示光标位置:即当前光标位于 s [ c u r ] s[cur] s[cur]的右边。 c u r = 0 cur=0 cur=0说明光标位于“虚拟字符” s [ 0 ] s[0] s[0]的右边,即显示屏的最左边。
为了移动光标,还需要用一个变量 l a s t last last表示显示屏的最后一个字符是 s [ l a s t ] s[last] s[last]。
代码如下:
#include <bits/stdc++.h>
#define next pre
using namespace std;
const int MAXN=100005;
int last,cur,next[MAXN];
char str[MAXN];
int main()
{
while(scanf("%s",str+1)!=EOF)
{
int n=strlen(str+1);
cur=last=0;
next[0]=0;
for(int i=1;i<=n;++i)
{
if(str[i]=='[') cur=0;
else if(str[i]==']') cur=last;
else
{
next[i]=next[cur];
next[cur]=i;
if(cur==last) last=i;//更新“最后一个字符”的编号
cur=i;//移动光标
}
}
for(int i=next[0