块状链表基本操作及其相关例题

http://blog.csdn.net/bin314/article/details/7899934

部分内容参考自 论文 苏煜《对块状链表的一点研究》

1. 数组和链表对比:

 

数组和链表对比
操作数组链表

存储结构

地址连续的存储单元,物理位置相邻

地址不连续,物理位置不相邻

定位

O(1)

O(N)

添加

O(N)

O(1)

删除

O(N)

O(1)

数组有很好的定位功能,一般对应于固定的长度,不适合添加/删除等操作,当数组有序时,可二分查找某值,效率很好,O(logN)。

链表添加删除效率极高,很适合这类操作。但定位效率很低。

2.块状链表

块状链表是对数组和链表的折中,集两者之长,在定位,添加删除的效率上都有大幅提升。

整体上使用链表,链表节点是一个大小适当的数组。

如下图:

3.基本操作

①:定位

从链表头开始往后扫,每个节点记录本节点合法数据的长度,最终会定位为某一个块及块内偏移。

②:分裂

将指定的块在指定的位置分裂成2个块。

③:合并

本块合并掉之后的那一块,前提是2块的有效数据长度之和 <= N (array的长度)

定位,插入,删除的时候对本块进行合并将会减少块元素过少,否则有可能退化成普通的链表。

④:插入

在指定位置分裂,然后在本块后面插入若干个块,示意图如下:

⑤:删除

在指定的位置分裂,删除本块之后的若干块,示意图如下:

4.效率分析:

设数组大小为x,数据总数为N,则理想状况下分块树为N/x,则定位的时间复杂度为O(N/x),插入删除的时间复杂度为O(x)

令N/x = x , x = sqrt(N),即每次操作的时间复杂度大致为O(sqrt(N))

和平衡树O(logN)等相比还是有较大差距,但是其附加空间很少,仅为O(sqrt(N)),平衡树的附加空间为O(N)。

5.几道例题:

①:NOI2003 editor(经典)

【题目大意】

一些定义:

文本:由0个或多个ASCII码在闭区间[32, 126]内的字符(即空格和可见字符)构成的序列。

光标:在一段文本中用于指示位置的标记,可以位于文本首部,文本尾部或文本的某两个字符之间。

文本编辑器:为一个包含一段文本和该文本中的一个光标的,并可以对其进行如下六条操作的程序。如果这段文本为空,我们就说这个文本编辑器是空的。

操作名称

输入文件中的格式

功能

MOVE(k)

Move k

将光标移动到第k个字符之后,如果k=0,将光标移到文本开头

INSERT(n, s)

Insert n¿

S

在光标处插入长度为n的字符串s,光标位置不变,n ³ 1

DELETE(n)

Delete n

删除光标后的n个字符,光标位置不变,n ³ 1

GET(n)

Get n

输出光标后的n个字符,光标位置不变,n ³ 1

PREV()

Prev

光标前移一个字符

NEXT()

Next

光标后移一个字符

比如一个空的文本编辑器依次执行操作INSERT(13, “Balanced tree”)MOVE(2)DELETE(5)NEXT()INSERT(7, “ editor”)MOVE(0)GET(16)后,会输出“Bad editor tree”。

你的任务是:

建立一个空的文本编辑器。

从输入文件中读入一些操作并执行。

对所有执行过的GET操作,将指定的内容写入输出文件。

ps:这些操作仅仅是定位,添加,删除,采用块状链表可以轻松搞定,splay等各种也可以。

有兴趣的可以在下oj上测试下自己的代码:

http://zerojudge.tw/ShowProblem?problemid=a105

②:反转序列

【题目大意】

一个长度为 n 的整数序列初始时从左到右为1,2,3,……,n,现在对这个序列进行 m 次操作,每次把 p 到 q 的子序列反转
求最后的序列

ps:操作很简单,每次对一个区间进行反转,求若干次反转之后的序列。

这里需要在每个节点维护一个域rev,rev=true代表本区间需要反转,false表示不需要反转

在区间合并、分裂以及最后的输出上需要维护rev,操作很简单,反转该区间的值即可。

在反转若干的区间的时候问题等价于将链表反转。

有兴趣的可以在下oj上测试下自己的代码:

http://cstest.scu.edu.cn/soj/problem.action?id=3035


ps:用一个数组维护每一块的长度,查找时可以二分,添加、删除时采用顺序操作。

删除是二分定位可以跳过中间的直接删掉所有待删除块。

因为移位效率低,用平衡树来维护就舍本逐末了,目测效率也没多大改进。

不过对于反转序列来说,因为不涉及添加删除,效果还是可观的。

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值