您的位置:首页 > 理论基础 > 数据结构算法

数据结构---线性表----静态链表

2016-03-23 13:02 417 查看
1.静态链表的定义
        
对于一些高级语言,由于没有指针,链表结构按照前面的结构无法实现。故有人提出了用数组的元素来代替指针,来描述单链表。
        首先我们让数组的元素都是由两个数据域组成。data和cur。也就是说,数组的每个下标都对应一个Data和一个cur。数据域data,用来存放数据元素,也就是通常我们要处理的数据;而cur相当于单链表中next指针,存放该元素的后继在数组中的小标,我们把cur叫做游标。
        我们把这种用数组描述的链表叫做静态链表。我们把这种描述方法还有起名叫做游标实现法。
        
/*线性表的静态链表存储结构*/
#define MAXSIZE 1000
typedef struct
{
Elemtype data;
int cur;          /*游标(Cursor),为0时表示无指向*/
}component, StaticLinkList[MAXSIZE];


       我们对数组的第一个和最后一个元素作为特殊元素处理,不存数据。我们通常把未被使用的数据元素称为备用链表。而数组第一个元素,即小标为0的元素的则存放在备用链表。而数组的最后一个元素的cur则存在第一个有数值的元素的下标,相当于单链表中的头结点作用,当整个链表为空时,则为0*0。
 
     


     
/*将一维数组space中各分量链成一备用链表,*/
/*space[0].cur为头指针,“0”表示空指针*/
Status InitList(StaticLinkList space)
{
int i;
for (i = 0; i < MAXSIZE - 1;i++)
space[i].cur = i+1;
space[MAXSIZE-1].cur = 0;
return OK;

}

现在我们将数据存入静态链表。



2.静态链表的插入操作
       静态链表中要解决的是:如何用静态模拟动态链表结构的存储空间的分配,需要时申请,无用时释放。
       动态链表中,结点申请和释放分别借用malloc()和free()两个函数来实现。在静态链表中操作的是数组,不存在像动态链表的结点申请和释放问题,所以我们需要自己实现这两个函数,才可以进行插入和删除操作。
        解决办法:将所有未被使用过的及已经删除的分量用游标链成一个备用的链表,每当进行插入时,便可以从备用链表上去得第一个结点作为待插入的新结点。

/*若备用链表非空,则返回分配的结点下标,否则返回0*/
int Malloc_SLL(StaticLinkList space)
{
int i = space[0].cur;      /*当前数组第一个元素的cur存的值*/
/*就是要返回的第一个备用空闲的下标*/
if (space[0].cur)
space[0].cur = space[i].cur;/*由于要拿出一个分量来使用了,所以我们就得把他的下一个分量当作备用*/
return i;
}


这段代码其实就是:返回一个下标值,就是数组头元素的cur存的第一个空闲的下标。同时把该分量的cur值给头元素之后就可以继续分配新的空闲分量。

插入操作的实现代码:
    

/*在L中第i个元素之前插入新的数据元素e*/
int ListInsert(StaticLinkList L, int i, ElemType e)
{
int j ,k, l;
k = MAXSIZE - 1 ;                           /*注意首先是最后一个元素的下标*/
if (i<1 || i> Listlength(L) + 1)
return ERROR;
j = Malloc_SLL(L);                            /*获得空闲下来的下标*/
if (j)
{
L[j].data = e;                             /*将数据赋值给次分量的data*/
for (l =1 ; l <= i -1; l++)          /*找到第i个元素之前的位置*/
k = L[k].cur;
L[j].cur = L[i].cur;             /*把第i个元素之前的cur赋值给新元素的cur*/
L[k].cur = j;               /*把新元素的下标赋值给第i个元素之前的元的cur*/
return OK;
}
return ERROR;
}




3.静态链表的删除操作


要执行删除操作时,原来要释放结点的函数free().现在我们也得自己实现这个操作;
/*删除在L中第i个数据元素e*/
Status ListDelete(StaticLinkList L, int i)
{
int j , k;
if (i < 1 || i > ListLength(L))
return ERROR;
k = MAXSIZE - 1;
for(j = 1, j <= i - 1; j ++ )
k = L[k].cur;
j = L[k].cur;
L[k].cur = L[j].cur;
Free_SSL(L, j);
return OK;
}


/*将下标为k的空闲节点回收到备用链表*/
void Free_SSL(StaticLinkList space, int k)
{
space[k].cur = spce[0].cur;       /*把第一个元素cur值给赋给要删除的分量cur*/
space[0].cur = k;                        /*把要删除的分量下标赋值给第一个元素的cur*/
}


3.得到静态链表的元素个数

/*初始条件,静态链表L已经存在,操作结果,返回L中的数据元素个数*/
int ListLength(StaticLinkList L)
{
int j = 0;
int i = L[MAXSIZE - 1].cur;
while(i)
{
i = L[i].cur;
j++;
}
return j;
}


4.静态链表优缺点
        总结下他的优缺点:
        优点: 在插入和删除操作时,只需要修改游标,不需要移动元素,从而改变了在顺序存储结构中的插入和删除操作需要移动大量的元素。
        缺点: 1.没有解决连续存储分配带来的的表长难以确定的问题。
                    2.失去了顺序存储结构随机存取的特性。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: