在C语言中用指针可以实现线性单链表,而有些语言不支持指针,我们可以利用两个并行的数组或者结构体数组来模拟指针,这样子的链表称之为静态链表。
在我看来,静态链表的优点就是,虽然没有指针,但通过游标操作,同样实现了指针具有的一些优点,比如插入删除操作不需要像顺序存储结构那样移动很多的元素。
它的缺点就是在不知道需要多少存储空间时,预先分配了一个很大的数组,这样还是比较浪费的。静态链表主要是给没有指针的高级语言设计的,这种思想非常巧妙,值得我们学习。
下面,我给出了C语言下的实现方法,并给出了基本的操作函数,以及针对每种操作,都进行了打印输出的验证。
/*******************************************************************/
//描述:使用结构体数组静态链表的创建,插入,删除等基本操作的函数,以及对这些操作进行验证
//时间:2017.12.29 11:00
//作者:Liu ZhenHua
//*****************************************************************/
#include <stdio.h>
#include <stdlib.h>
#define MAXSIZE 1000
#define OK 1
#define TRUE 1
#define FALSE 0
#define ERROR 0
typedef char ElemType;
typedef int Status;
typedef struct{
ElemType data;
int cur;
}Component,StaticLinkList[MAXSIZE];
Status InitList(StaticLinkList space); //初始化静态链表
int malloc_SLL(StaticLinkList L); //分配新的空间
int listLength(StaticLinkList sl); //读取链表长度,即链表存储有几个数据
Status GetElem(StaticLinkList L,int i,ElemType *e);
void printStaticLinkList(StaticLinkList L); //顺序打印链表
//在第i个元素之前插入元素e
Status InsertElem(StaticLinkList L,int i,ElemType e);
//删除掉第i个元素
Status DeleteElem(StaticLinkList L,int i,ElemType *e);
void printSL(void); //打印一行分割线
int main()
{
char cv = 'a';int listlen;
StaticLinkList sl;
char tempchar,*cp;cp = &tempchar;
if(InitList(sl))printf("静态链表创建成功!\n");
//初始化后生成一个包含4个元素的新链表
sl[1].data=cv;sl[2].data=cv+1;sl[3].data=cv+2;sl[4].data=cv+3;sl[4].data=cv+3;
sl[0].cur=5;sl[4].cur=0;sl[MAXSIZE-1].cur=1;
listlen = listLength(sl);
printf("链表长度为: %d\n",listlen);
printStaticLinkList(sl);
printSL();
if(GetElem(sl,3,cp)){
printf("取出第三个元素为:%c\n",*cp);
}else{
printf("取出元素失败!\n");
}
printSL(); //插入操作
if(InsertElem(sl,2,'e'))printf("在第二个插入元素'e'之后\n");
listlen = listLength(sl);
printf("链表长度为: %d\n",listlen);
printStaticLinkList(sl);
printSL(); //删除操作
if(DeleteElem(sl,3,cp))printf("删除第三个元素成功!\n");
listlen = listLength(sl);
printf("链表长度为: %d\n",listlen);
printStaticLinkList(sl);
return 0;
}
/**********************************************/
//函数名:InitList
//描述 : 初始化静态链表
//参数 :结构体数组space
//返回值:状态值
//作者 :LiuZhenHua
/**********************************************/
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;
}
/**********************************************/
//函数名:malloc_SLL
//描述 : 分配一个新空间,并且第一个元素的下标指向新的未使用空间
//参数 :结构体数组space
//返回值:新的元素的数组下标
//作者 :LiuZhenHua
/**********************************************/
int malloc_SLL(StaticLinkList L){
int k;
k = L[0].cur;
L[0].cur = L[k].cur; //分配一个新的单位,第一个元素下标依然指向空链表
return k; //返回分配的空单位的数组下标,注意数组下标!=元素的下标
}
/**********************************************/
//函数名:listLength
//描述 : 返回静态链表长度
//参数 :结构体数组名
//返回值:链表长度
//作者 :LiuZhenHua
/**********************************************/
int listLength(StaticLinkList sl){
int k;int i = 0;
k = MAXSIZE - 1;
k = sl[k].cur;
while(k){
k = sl[k].cur;
i++;
}
return i;
}
/**********************************************/
//函数名: printStaticLinkList
//描述 : 顺序打印链表存储的元素值
//参数 :结构体数组名
//返回值:无
//作者 :LiuZhenHua
/**********************************************/
void printStaticLinkList(StaticLinkList L){
int k,i,m=0;
ElemType value;
k = MAXSIZE - 1;
i = L[k].cur;
while(i!=0){
value = L[i].data;
printf("链表元素%d: %c\n",++m,value);
i = L[i].cur;
}
printf("链表打印完毕!\n");
}
/**********************************************/
//函数名: InsertElem
//描述 : 在第i个元素前插入元素e
//参数 :结构体数组名
//返回值:状态值
//作者 :LiuZhenHua
/**********************************************/
Status InsertElem(StaticLinkList L,int i,ElemType e){
int j,k,m;
k = MAXSIZE - 1;
if(i > MAXSIZE || i<1 || L[k].cur==0){
return ERROR; //插入位置不对或者链表为空链表
}
for(j = 0; j < i-1; j++){ //循环,得到插入位置左邻元素的数组下标
k = L[k].cur;
}
m = malloc_SLL(L); //开辟一个新空间,并返回要插
L[m].data = e; //将数据存入元素的数据域
L[m].cur = L[k].cur; //更换元素下标
L[k].cur = m;
return OK;
}
/**********************************************/
//函数名: DeleteElem
//描述 : 在第i个元素前删除元素e
//参数 :结构体数组名,位置i,返回元素指针*e
//返回值:状态值
//作者 :LiuZhenHua
/**********************************************/
Status DeleteElem(StaticLinkList L,int i,ElemType *e){
int j,k,n1,n2;
k = MAXSIZE - 1;
if(i > MAXSIZE || i<1 || L[k].cur==0){
return ERROR; //删除位置不对或者链表为空链表
}
for(j = 0; j < i-1; j++){ //循环,得到插入位置左邻元素的数组下标
k = L[k].cur;
}
n1 = k;
k = L[k].cur;
*e = L[k].data;
n2 = L[k].cur;
L[n1].cur = n2;
L[k].cur=L[0].cur; //交换元素的下标,更换空链表
L[0].cur=k;
return OK;
}
/**********************************************/
//函数名: printSL
//描述 : 打印一行分割线Print Split Line
//参数 :结无
//返回值:无
//作者 :LiuZhenHua
/**********************************************/
void printSL(void){
int i;
for(i = 0; i < 20; i++){
printf("-");
}
printf("\n");
}
/**********************************************/
//函数名: GetElem
//描述 : 取出在第i个位置的元素e
//参数 :结构体数组名,位置i,返回元素指针*e
//返回值:状态值
//作者 :LiuZhenHua
/**********************************************/
Status GetElem(StaticLinkList L,int i,ElemType *e){
int j,k;
k = MAXSIZE - 1; //最后一个元素的数组下标
if(i > MAXSIZE || i<1 || L[k].cur==0){
return ERROR; //插入位置不对或者链表为空链表
}
for(j = 0; j < i; j++){ //循环,得到插入取出元素的数组下标
k = L[k].cur;
}
*e = L[k].data;
return OK;
}