在实际程序设计过程在,手撸链表及单链表的单向遍历和双链表的复杂操作带来很多不便。其实,为了模仿链式结构可用两个数组代替,及前驱数组pre和后继数组next。这种方法方便了我们对于链式结构的建立与处理,但其不足之处在于占用了较多的空间,有较高的空间复杂度,且其只是单纯的逻辑模拟,只支持删除操作,不支持插入操作,即使如此,其作为逻辑跳转表也是可取的,下面以一道简单题为例:
#include <iostream>
#include <cstring>
using namespace std; //使用名称空间std
//内联函数声明及定义区(定义在其他无main函数的文件中会发生链接错误)
int main()
{
int prime[3010]; //幸运数字存储数组
int pre[50010], next[50010]; //模拟结点前驱和后继
int n;
int i, j;
int ans = 0;//prime数组位置标记
int count; //循环计数器
for (i = 1;i<50000;i++)
{
pre[i] = i - 1; //设置前驱数组
next[i] = i + 1; //设置后继数组
}
for (i = next[1];i < 50000;i = next[i]) //使用后继而非i++
{//i本身看做逻辑链表,i即为对应结点,使用了前驱和后继数组设定的逻辑结构
prime[++ans] = i;//找到此阶段的第一个数(幸运数字)
if (ans == 3000) break;
count = 1;
for (j = next[i];j < 50000;j = next[j])
{//排除此阶段的非幸运数字,修改逻辑结构
if (count == i)
{//找到计数位置(待删除的非幸运数字)
pre[next[j]] = pre[j]; //删除计数点处j结点
next[pre[j]] = next[j];
count = 1;//进行下一次计数循环
}
else //未到计数点
count++;
}
}
while (cin >> n)
{
cout << prime[n] << endl; //第一个数从下标1开始
}
return 0;
}
删除j结点时的逻辑:
pre[j]->j->next[j]
要删除j,只需改变前驱与后继的逻辑顺序,
next[j]的前驱指向pre[j],pre[j]的后继指向next[j],即:
pre[next[j]]=pre[j];
next[pre[j]]=next[j];
总结:
用数组模拟链式结构的本质在于前驱与后继的逻辑模拟,此法用于只有删除操作的情形,模拟跳跃,作为逻辑跳跃表较为合适。