表的游标实现

    所谓游标就是指示数组单元地址的下标值,它属整数类型。我们可以用游标来模拟指针,将TElement类型的元素所组成的表用一个数组来实现,数组单元是记录类型,记录中包含一个表元素和一个作为游标的整数;具体说明如下:

Var
SPACE: array[1..maxlength] of
                       record
                         element:TElement;
                         next:integer;
                       end;

    对于一个表L,我们用一个整型变量Lhead作为L的表头游标。SPACE[Lhead]就是L的表头单元,其中的elemnt域是空的,next域中的游标指示L的第一个元素在数组SPACE中的存储地址(数组下标值)。这样,我们就可以用游标来模拟指针,实现单链表中的各种运算。照此,我们虽然是用数组来存储表中的元素,但在作表的插人和删除运算时,不需要移动元素,只要修改游标,从而保持了用指针实现表的优点。因此,有时也将这种用游标实现的表称为静态链表

    下面我们介绍用游标实现表的另一种方式。这种方式不用表头单元,因此在表的第一个位置进行插入或删除时,需要进行特殊处理。这与在单链表中不用表头单元的情形类似。设L是一个表。我们用Lhead指示L的第一个元素,即L的第一个元素存放于SPACE[Lhead].element中,而SPACE[Lhead].next为L的第二个元素所在单元的下标值。其后每个元素的后继元素所在单元以类似的方式给出。如果Lhead或者某单元中next域的值为0,则表示这是一个空指针,即该游标不指示任何单元。表L可以用它的表头变量Lhead来代表。由于表头变量是整型变量,所以表的类型为整型。位置变量类型TPosition也是整型。与单链表中位置变量的意义相类似。我们约定,当i>1时,表示第i个位置的位置变量pi的值是数组SPACE中存储表L的第i-1个元素的单元的下标值,即SPACE[pi].next是指示第i个元素在SPACE中的下标。当i=1时,pi=O。

类型定义如下:

Type
  TList=integer;
  TPosition=integer;
   SPACE
d7
 4
c0
 6
a8
 0
e0
b3
 10
 2

图4  用游标实现表

    在图4中,两个表L(包含元素依次为a,b,c)和M(包含元素依次为d,e)存放于同一数组SPACE中,其中的maxlength=10。数组SPACE中末被占用的所有单元组成了另一个表available,由这个表提供L和M的备用单元。当我们要在表L或M中插入一个元素时,所用的新单元就取自表available。反之,从两个表中删除的单元要回收(插入)到表available中备用。

    初始时,我们将数组SPACE中所有单元链接成表available备用。这个过程可实现如下。

procedure Initialize;

Var

     i:Integer;

begin

     for i:=maxlength-l downto 1 do SPACE[i].next:=i+l;

     available:=1;

     {表available的第一个可用单元即表头在SPACE中的下标为1}

     SPACE[maxlength].next:=0;

end;

    要在表L中插入一个元素x,可将表available的第一个单元摘除,并将这个备用单元插入L的适当位置,再将这个新单元的element域赋值为x。

procedure Insert(x:TElement;p:TPosition;var L:TLIST);

begin

 if p=O then    (在第一个位置插入)

  begin

   if move(available,L) then SPACE[L].element:=x

                        else error;

      end

      else   {不在第一个位置插入}

         if  move(available,SPACE[p].next)

         then SPACE[SPACE[p].next].element:=x

         else error

end;

 

    由于我们没有使用表头单元,所以必须单独处理在第一个位置插入的情形。另外,上述过程中用到了一个函数move(p,q),其功能是从某一链表中将游标p所指的单元C摘除,并将这个单元C插入到另一链表中游标q所指的单元之前,成功则返回true。我们可以先将q改为指向单元C,然后再将p改为指向单元C的下一单元,最后再将C中的游标改为指向q原来所指的单元即可。这个游标的修改过程如图5所示。

图5  两个链表之间的单元转移

    图5中的实线和虚线分别表示单元转移前后的游标。当单元C存在时,函数move取值为true,并施行单元C的转移;当单元C不存在时,函数move取值为false。

function move(var p,q;integer):boolean;

var

   temp:integer;

begin

   if p=0 then return(false)

      e1se

         begin

           temp:=q;

           q:=p;

           p:=SPACE[p].next;

           SPACE[q].next:=temp;

           return(true);

        end

end;

    要从表中删除位置p的元素,可以将L中位置p所指示的那个单元摘除,并将它插入表available的头一个位置备用。

procedrue Delete(p:TPosition;var L:TList);

begin

if p=O then move(L,available)

                else move(SPACE[p]^.next,available)

end;

    与单链表中的情形类似,为要删除表L中的一个元素x,先要找到x在表L中的位置。这可以用下面的函数Locate来实现。在表L中找到第一个与x相同的元素时,Locate返回x所在单元的位置,否则返回表尾位置。

function Locate (x:TElement;L:TList):TPosition;

Var

  p:TPosition;

begin

  p:=L;

  if p=0 then error('List is empty.');

  if SPACE[p].element=x then return(0);

  while SPACE[P].next<>0 do

      if SPACE[SPACE[P].next].element=x then return(p)

                                                               else  p:=SPACE[P].next;

   return(p);

end;

    由于我们是用游标来模拟指针的,上述各运算的复杂性分析与单链表中的情形是类似的。另外,上述程序中都省略了检查错误的语句。

<script src="../../../lib/footer.js" type="text/javascript"> </script>
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值