算法导论11.2-4未占用槽分配存储

来源:互联网 发布:淘宝积分兑换优酷会员 编辑:程序博客网 时间:2024/04/29 21:38

一、题目

说明在散列表内部,如何通过将所有未占用的槽连接成一个自由链表,来分配和存储元素所占的存储空间。假定一个槽可以存储一个标志、一个元素、一个或两个指针。所有的字典和自由链表操作均应具有O(1)的期望运行时间。该自由链表需要是双向链表吗?或者单链表就足够了?

二、思路整理(参考官方答案)

    每个槽slot有一个布尔值flag属性,表明是否已占用;

    未占用slot:一个双向链表把空闲slot都连接起来,每个free slot有两个指针;

    已占用slot:包含一个元素element和两个指针(参考答案是使用一个指针,这里为了方便)(可能nil),分别指向上一个和下一个散列到这个slot的元素,也就是是指向另一个slot。(因为所有element都存储在slot中)

    一个slot定义如下:

struct node(){    bool flag;//1为已占用,0未占用    int key;//未占用:没意义,-1;已占用:元素关键字    int prev;//未占用:上一个空槽;<span style="font-family: Arial, Helvetica, sans-serif;">已占用:上一个具有相同散列值的元素</span>    int next;//未占用:下一个空slot ;已占用:下一个具有相同散列值的元素}


    插入操作:

    1、如果元素x散列到一个空slot,将这个空slot从Free List移除,把x放到这个slot里,next指针指向nil,然后维护FreeList指针;

    2、如果元素x散列到一个非空slot槽位j,该slot已存储元素y,分两种情况:

       a、hash(y)=j:FreeList分配一个新slot存储x,将其插入y与y.next元素之间,即新slot指向y.next,y的指针指向新slot;

       b、hash(y)≠j:FreeList分配新slot,用于存储y(包括元素、指针),指向旧slot的指针指向新slot,腾出的slot j存放x;

   查找操作:

   查找元素x,首先查找槽hash(x),如果不是,沿着链表指针一次查找。

   删除操作:分三种情况,假设hash(x)=j,x散列到j

   1、j.next=nil,即只有一个元素x散列到slot j,只需将j释放到自由表;

   2、j.key=x,且j.next!=nil,x位于j槽,后面还有其他元素,把j.next移动到j,原j.next所占空间释放到自由表

   3、j.key!=x且j.next!=nil,x位于j的next指针指向的后面的slot中,修改x前后元素指针,释放x所占slot.

   

//伪代码

//分配新slot

RemoveFromFreeSlot(s){//s为slot下标,代表槽对象

    if(s.prev!=nil)

       s.prev.next=s.next;

    else free = s.next;

    if(s.next!=nil)

       s.next.prev=s.prev;

    s.flag=1;

    return s;    

}

//释放slot到FreeList

FreeSlotToFreeList(s){

   s.flag=0;

   s.next=free;

   free.prev=s;

   free=s;

   s.prev=nil;

}


Insertion(x){

     j=hash(x);

   if(j.flag==0)//插入一个空槽

     RemoveFromFreeSlot(j);

      j.next=nil;

      j.prev=nil

      j.key=x;

   else

      t=RemoveFromFreeSlot(free);//获取自由链表首位置

      if(hash(j.key)==j)//2.a情况,把新元素放到t,修改前后元素指针

         t.prev=j;t.key=x;t.next=j.next;

         j.next=t;

      else             //2.b情况 

         t.key=j.key;t.prev=j.prev;t.next=j.next;//把j中原先的移到t,修改原先元素指针

         if(t.next!=nil)t.next.prev=t;

         if(t.prev!=nil)t.prev.next=t;

         j.key=x;j.next=nil;j.prev=nil;//把x放到j

}


Search(x){

    j=hash(x);

    //x散列到槽为空,所以不存在x

    //j存储的值不属于j,所以不存在x

    if(j.flag==0||hash(j.key)!=j)return -1;

    while(j!=nil&& j.key!=x)

       j=j.next;

    return j;

}

Delete(x){

    j=hash(x);r=search(x);

    if(r<0)return false;//不存在x

    if(r==j && j.next==nil){

       FreeSlotToFreeList(j);

    }

    else if(r==j && j.next!=nil){//把j下一位元素移到j,释放下一位元素位置

       i=j.next;

       j.key=i.key;

       j.next=i.next;

       if(i.next!=nil)i.next.prev=j;

       FreeSlotToFreeList(i);

    }

    else 

        r.prev.next=r.next;

        if(r.next!=nil)

          r.next.prev=r.prev;

        FreeSlotToFreeList(r);

    

}


0 0
原创粉丝点击