诸如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. 如何解决The underlying provider failed on Open问题

    转自codeproject,找了半天解决办法,这个最靠谱. 我数据库用的EF做ORM,在vs里面测试的时候不会出现这个错误,用IIS就出错了.解决方法如下 Solution for "The ...

  2. Problem G: 切煎饼

    Description 王小二自夸刀工不错,有人放一张大的圆煎饼在砧板上,问他:饼不允许离开砧板,切100刀最多能切多少块? Input 多组测试数据,每组输入1个整数,代表切的刀数 Output 每 ...

  3. Java反射机制涉及的类常见方法使用总结

    import java.lang.reflect.Constructor; import java.lang.reflect.*; /*Class:代表一个字节码文件的对象,每当有类被加载进内存,JV ...

  4. USACO 2017 FEB Platinum mincross 可持久化线段树

    题意 上下有两个位置分别对应的序列A.B,长度为n,两序列为n的一个排列.当Ai == Bj时,上下会连一条边.你可以选择序列A或者序列B进行旋转任意K步,如 3 4 1 5 2 旋转两步为 5 2 ...

  5. JavaScript学习笔记 isPrototypeOf和hasOwnProperty使用区别

    1.isPrototypeOf isPrototypeOf是用来判断指定对象object1是否存在于另一个对象object2的原型链中,是则返回true,否则返回false. 格式如下: object ...

  6. c# -- 解决FromsAuthentication上下文不存在

    使用 FormsAuthentication.HashPasswordForStoringInConfigFile("需要加密的字符串", "MD5")这个方法 ...

  7. Codeforces Round #194 (Div. 1) B. Chips 水题

    B. Chips Time Limit: 20 Sec  Memory Limit: 256 MB 题目连接 http://codeforces.com/contest/333/problem/B D ...

  8. MySQL的max_user_connections拒绝连接的一次踩雷经验

    近期线上的数据遇到一个问题,最终原因为max_user_connections和max_connections的一个bug导致,具体过程如下 现象 前端页面不断的出现错误页面. 排查处理过程 按照数据 ...

  9. HDU 4705 Y (2013多校10,1010题,简单树形DP)

    Y Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)Total Submiss ...

  10. POJ 1755 Triathlon (半平面交)

    Triathlon Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 4733   Accepted: 1166 Descrip ...