从之前两种线性表的存储结构来看,顺序存储和链式存储各具优点和缺点,顺序存储在查找元素方面比较方便,但是在插入和删除操作时会花费较长的时间;而链式存储则在插入和删除操作方面比较简单。 孟子说过:“鱼和熊掌不可兼得”,但是我们想能不能有一种存储结构真的能既结合了顺序存储在查找方面的优势又在插入和删除操作上面节省时间呢?于是,我们聪明的程序员们便创造了这样一种存储结构——静态链表。
照例我们来看看静态链表的存储结构
#define MAXSIZE 100 //链表的最大长度
typedef struct
{
ElemType data;
int cur; //游标
} component,SLinkList[MAXSIZE];
我们可以看到,静态链表类似结构体数组,但是在结构体中添加了一个游标,作用就是代替链表中的指针指示结点在数组中的相对位置。这样我们就把一个结构体改造成了一个类似链表的数组。数组的第零分量可以看成是链表中的头结点,游标指示第一个结点。我们可以看到,这样的存储结构事实上是一个结构体数组,但是在插入和删除操作上又是通过移动游标来完成的,所以它也具有链表的优点。既具有顺序存储的优点又具有链式存储的优点,太棒了!!
类似的我们可以写出删除和插入的操作。在讲链式存储的时候,我们在插入和新建的操作中运用了malloc函数,在删除操作中运用了free函数。但是在顺序存储中并没有这两个函数,因此这就要求我们必须自己写专门针对静态链表的malloc和free函数。
为了分辨使用了的和未使用的分量,将所有未使用的分量和被删除的分量链成一个备用链表。插入的时候直接从备用链表取头结点后第一个结点作为可供插入的一个结点。反过来说,如果要删除结点,就将结点重新链接到备用链表上。
第一个malloc函数(`・ω・´)
int Malloc_SL(SLinkList &space)
{//若备用空间链表非空,则返回非陪的结点下标,否则返回0
int i;
i=space[0].cur;
if(space[0].cur) space[0].cur=space[i].cur; //把i提取出来
return i;
}
第二个free函数(`・ω・´)
void Free_SL(SLinkList &space,int k)
{//将下标为k的空闲结点回收到备用链表
space[k].cur=space[0].cur;
space[0].cur=k;
}
下面写到的就是新建一个静态链表的代码实现。可以看到,我们使用了“0”来代表链表中的空指针。则我们在遍历的时候就可以通过判断数组的下标是否为0来结束循环。
void InitSpace_SL(SLinkList &space)
{
int i;
for(i=0; i<MAXSIZE-1; ++i) space[i].cur=i+1;
space[MAXSIZE].cur=0;
}
下面我们来看看一个 简单的功能实现——查找元素
int LocateElem_SL(SLinkList space,int S,ElemType e)
{
int i;
Pre_i=S;
i=space[S].cur;
while(i&&space[i].data!=e)
{
Pre_i=i;
i=space[i].cur;
}
return i;
}