您的位置:首页 > 其它

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

2015-04-20 17:11 162 查看
一、题目

说明在散列表内部,如何通过将所有未占用的槽连接成一个自由链表,来分配和存储元素所占的存储空间。假定一个槽可以存储一个标志、一个元素、一个或两个指针。所有的字典和自由链表操作均应具有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);

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: