诸如BASIC和FORTRAN等许多语言都不支持指针。如果需要链表而又不能使用指针,这时我们可以使用游标(cursor)实现法来实现链表。

在链表的实现中有两个重要的特点:

数据存储在一组结构体中。每一个结构体包含有数据以及指向下一个结构体的指针。

一个新的结构体可以通过调用malloc而从系统全局内存(global memory)得到,并可以通过free而被释放。

游标法必须能够模仿实现这两条特性:

定义一个全局的结构体数组(模拟系统全局内存)。对于数组中的任何单元,其数组下标可以用来代表一个地址。

typedef int ptr_to_node;
typedef ptr_to_node list;
typedef ptr_to_node position; struct node
{
element_type element;
position next;
}; struct node cursor_space[spacesize];

在这个全局的结构体数组中,保留一个表freelist作为备用单链表,用来malloc或free游标可用空间,该表用0作为表头。刚开始时,freelist就是整个结构体数组。

需要理解的是:所有的链表,包括备用表和已用表,全部都在我们定义的全局结构体数组中,只是它们的表头不同,从不同的表头出发形成了不同的单链表。

假设我们定义了一个大小为11的游标空间,其初始化状态如下:

Slot Element Next
0

1

2

3

4

5

6

7

8

9

10

  1

2

3

4

5

6

7

8

9

10

0

注:对于Next, 0的值等价于NULL指针。

上面的状态用链表形式表示为:cursor_space[0]—>cursor_space[1]—>cursor_space[2]—>cursor_space[3]—>cursor_space[4]—>cursor_space[5]—>cursor_space[6]—>cursor_space[7]—>cursor_space[8]—>cursor_space[9]—>cursor_space[10]—>NULL.

为执行malloc功能,将(在表头后面的)第一个元素从freelist中删除。为了执行free功能,我们将该单元放在freelist的前端。

malloc和free的游标实现如下:

static position
cursor_alloc(void)
{
position p; p = cursor_space[0].next;
cursor_space[0].next = cursor_space[p].next; return p;
} static void
cursor_free(position p)
{
cursor_space[p].next = cursor_space[0].next;
cursor_space[0].next = p;
}

为加深理解,请参考如下实例:

Slot Element Next
0

1

2

3

4

5

6

7

8

9

10

-

b

f

header

-

header

-

c

d

e

a

6

9

0

7

0

10

4

8

2

0

1

如果单链表L的值是5,M的值是3,我们又规定了freelist表头为0,因此,从上表中我们可以得到三个链表:

freelist:cursor_space[0]—>cursor_space[6]—>cursor_space[4]—>NULL 

L:header—>a—>b—>e—>NULL

M:header—>c—>d—>f—>NULL

freelist是分配L、M链表后还剩余的可分配空间。

 

游标实现

/* return ture if L is empty */
int isempty(list L)
{
return cursor_space[L].next = 0;
}
/* return true if P is the last position in list L */

int islast(position p, list L)
{
return cursor_space[P].next == 0;
}
/* return position of X in L; 0 if not found */
/* uses a header node */ position find(element_type X, list L)
{
position p; p = cursor_space[L].next;
while(p && cursor_space[p].element != X)
p = cursor_space[p].next; return p;
}
/* delete first occurence of X from a list */
/* assume use of a header node */ void delete(element_type X, list L)
{
position p, tmpcell; p = find_previous(X, L); if(!islast(p, L))
{
tmpcell = cursor_space[p].next;
cursor_space[p].next = cursor_space[tmpcell].next;
cursor_free(tmpcell);
}
}
/* insert (after legal position P) */

void insert(element_type X, list L, position P)
{
position tmpcell; tmpcell = cursor_alloc();
if(tmpcell == 0)
fatal_error("out of sapce!!!"); cursor_space[tmpcell].element = X;
cursor_space[tmpcell].next = cursor_space[P].next;
cursor_space[P].next = tmpcell;
}

链表的游标(cursor)实现的更多相关文章

  1. SQL Server 数据库的维护(四)__游标(cursor)

    --维护数据库-- --游标(cursor)-- --概述: 注:使用select语句查询结果的结果集是一个整体,如果想每次处理一行或一部分行数据,游标可以提供这种处理机制.可以将游标理解为指针.指针 ...

  2. 分组PARTITION BY及游标CURSOR的用法

    基础数据表: select * from dbo.RecommendationChanelVersionRelation: 数据如下: 要求按照ChannelVersionID分组,对每组中的Orde ...

  3. MySQL游标(cursor) 定义及使用

    概念 游标(Cursor)它使用户可逐行访问由SQL Server返回的结果集. 使用游标(cursor)的一个主要的原因就是把集合操作转换成单个记录处理方式. 用SQL语言从数据库中检索数据后,结果 ...

  4. ORACLE中的游标Cursor总结

    游标(Cursor):用来查询数据库,获取记录集合(结果集)的指针,可以让开发者一次访问一行结果集,在每条结果集上作操作. 游标可分为: 1.       静态游标:分为显式(explicit)游标和 ...

  5. PL/SQL使用游标CURSOR

    一.使用游标 对于DML语句和单行select into ,oracle自动分配隐形游标.处理select返回多行语句,可以使用显式游标. 使用显示游标处理多行数据,也可使用SELECT..BULK ...

  6. 游标cursor

    if exists(select * from sys.objects where name='info_one') drop table info_one go create table info_ ...

  7. SQL游标(cursor)详细说明及内部循环使用示例

    游标 游标(cursor)是系统为用户开设的一个数据缓冲区,存放SQL语句的执行结果.每个游标区都有一个名字,用户可以用SQL语句逐一从游标中获取记录,并赋给主变量,交由主语言进一步处理. 游标是处理 ...

  8. SQLServer游标(Cursor) (B)

    游标(Cursor)是处理数据的一种方法,为了查看或者处理结果集中的数据,游标提供了在结果集中一次以行或者多行前进或向后浏览数据的能力.我们可以把游标当作一个指针,它可以指定结果中的任何位置,然后允许 ...

  9. MySql使用游标Cursor循环(While)更新数据

    #要修改的变量 DECLARE var_ID VARCHAR(50) DEFAULT ''; #需要修改的数据的数量 DECLARE var_UpdateCount INT; #当前循环次数 DECL ...

随机推荐

  1. Linux中mysql的操作

    一.mysql服务操作 二.数据库操作 三.数据表操作 四.修改表结构 五.数据备份和恢复 六.卸载数据库

  2. PHP视频教程 字符串处理函数(二)

    1.字符串输出:echo()输出一个或者多个字符串 2.截取 chunk_split(); 3.

  3. Hibernate 过滤查询(hibernate过滤器的使用)

    我们在开发过程中过滤查询使用的还是挺多的,今天来学习一下hibernate的过滤器的使用,首先学习在配置文件中如何使用,然后再介绍如何使用注解配置. 1.使用配置文件配置过滤器  1)首先我们使用my ...

  4. java 同步 异步

    韩梦飞沙  韩亚飞  313134555@qq.com  yue31313  han_meng_fei_sha 同步 就是  讲究顺序 异步 就是  可以同时进行. 不知道那个家伙起得名字.. 讲究 ...

  5. 关于dp骗分

    1.样例2.搜索3.大小->贪心:<1>每次选代价最小的两个矩阵                      <2> 每次选最大....                   ...

  6. [BZOJ4016][FJOI2014]最短路径树问题(dijkstra+点分治)

    4016: [FJOI2014]最短路径树问题 Time Limit: 5 Sec  Memory Limit: 512 MBSubmit: 1796  Solved: 625[Submit][Sta ...

  7. [BZOJ 2821] 作诗

    Link: BZOJ 2821 传送门 Solution: 一道类似区间众数的经典分块 由于个数为偶数这样的条件不能支持快速合并 因此要先$O(n*sqrt(n))$预处理出$pre[i][j]$表示 ...

  8. 【并查集】BZOJ4668-冷战

    [题目大意] 给出N个军工厂和M 个操作,操作分为两类: • 0 u v,这次操作苏联会修建一条连接 u 号军工厂及 v 号军工厂的铁路,注意铁路都是双向的; • 1 u v, Reddington ...

  9. 精通android体系架构、mvc、常见的设计模式、控制反转(ioc)

    1.请看某个著名的it公司一则招聘信息的其中一条要求:“熟悉android系统架构及相关技术,1年以上实际android平台开发经验:”,里面非常明确的说道要求熟练android系统架构,这从某种程度 ...

  10. 斐波那契数列(python实现)

    描述 一个斐波那契序列,F(0) = 0, F(1) = 1, F(n) = F(n-1) + F(n-2) (n>=2),根据n的值,计算斐波那契数F(n),其中0≤n≤1000. 输入 输入 ...