一、题目:
我们常常希望一个双链表中的所有元素在存储器中能够紧凑地排列在一起,例如使用多重数组表示中的前m个下标位置(在一个分页的虚拟计算机环境中情况就是这样的)。假设链表以外没有指向链表元素的指针,请说明如何实现过程ALLOCATE_OBJECT和FREE_OBJECT,才能使这种表比较紧凑。(提示:使用栈的数组实现)
思考:
假设当前的数组是紧凑的,即数组中有f个元素,都位于数组的前f个位置
分配一个新的元素时,把f+1的位置分配给它
删除一个元素时,假设待删除的元素的位置是i,先修改元素prev[i]的next指针和元素next[i]的prev指针,删除这个元素。这里数组中间就留下一个空位,让第f个元素填充这个空位,具体方法是修改元素prev[f]的next指针和元素next[f]和prev指针
代码:
#include <iostream>
#include <string>
#include <stdio.h>
using namespace std;
int n, head, f;
//在链表中插入一个元素
void Insert(int *key, int *next, int *prev, int x)
{
//链表已满
if(f == n-1)
{
cout<<"error:overflow"<<endl;
return;
}
//向上扩充一位,类似于栈
++f;
//在新的位置中填入信息,在这里,新元素放在链表首位,在物理空间是在f+1位置
key[f] = x;
prev[f] = -1;
next[f] = head;
if(head >= 0)
prev[head] = f;
head = f;
}
//删除一个元素
void Delete(int *key, int *next, int *prev, int x)
{
//链表为空时无法删除
if(f == -1)
{
cout<<"error:underflow"<<endl;
return;
}
int i;
//找到待删除元素的位置
for(i = 0; i <= f; i++)
{
if(key[i] != x)continue;
//设元素位于数组第i个位置
//修改指针,删除第i个元素
if(prev[i] != -1)
next[prev[i]] = next[i];
if(next[i] != -1)
prev[next[i]] = prev[i];
//如果i中第f个元素,直接删除即可,不需要特殊处理
//如果i不是第f个元素,就让第f个元素来补第i个元素的空缺
if(i < f)
{
//把第f个元素放到第i个位置
key[i] = key[f];
next[i] = next[f];
prev[i] = prev[f];
//修改指向f的指针,改为指向i
if(prev[f] != -1)
next[prev[f]] = i;
if(next[f] != -1)
prev[next[f]] = i;
}
//删去第一个元素,类似于栈
f--;
break;
}
}
//输出,按数组顺序输出,不是按链表顺序输出
void Print(int *key, int *next, int *prev)
{
int i;
for(i = 0; i <= f; i++)
cout<<i<<": "<<key[i]<<' '<<next[i]<<' '<<prev[i]<<endl;
}
int main()
{
cin>>n;
int x;
string str;
//构造随机数据
int *key = new int[n];
int *next = new int[n];
int *prev = new int[n];
head = -1;f = -1;
while(1)
{
cin>>str;
if(str == "I")
{
x = rand() % 100;
cout<<x<<endl;
Insert(key, next, prev, x);
}
else if(str == "D")
{
cin>>x;
Delete(key, next, prev, x);
}
else if(str == "P")
{
Print(key, next, prev);
}
}
return 0;
}