静态链表的操作
静态链表存储结构
typedef struct
{
int data;
int cur;
}Component,StaticLinkList[MAXSIZE];
用数组描述链表叫做静态链表
结构由存放数据元素的数据域data和存放后继节点地址的cur作为游标组成
一、静态链表的初始化
目的:初始化静态链表的状态
实现:
①对静态链表第一个和最后一个元素进行特殊处理,他们不存数据
②第一个元素保存当前链表最后一个元素的下一个下标(空闲空间的第一个位置)
③最后一个元素保存第一个有数值元素的下标,相当于单链表中的头结点
void initList(StaticLinkList &L)
{
for (int i = 0; i < MAXSIZE; i++)
{
L[i].cur=i+1;
}
L[MAXSIZE-1].cur=0;
}
在这里仅仅是初始化静态链表的状态,链表此时为空
所以第一个元素保存的是1,空闲空间的第一个位置是1,即此时链表中没有元素
最后一个元素保存第一个有数值元素的下标,因此为0
二、静态链表的插入
功能:在静态链表第l个元素前插入e
实现:
①定义j获取当前链表中第一个空闲位置的坐标(Malloc_SLL)
②将想插入的e赋值给空闲位置的data,从末位L[MAXSIZE-1]cur开始遍历找到第l-1个元素
③将第l-1个元素的cur赋值给插入元素的cur
④再将插入元素的下标赋值给第l-1个元素
void ListInsert(StaticLinkList &L,int l,int e)
{
int k=MAXSIZE-1;
if (l<1||l>ListLength(L)+1)
{
cout<<"error!"<<endl;
return ;
}
int j=Malloc_SLL(L);
if (j)
{
L[j].data=e;
for (int i = 1; i <= l-1; i++)
{
k=L[k].cur;
}
L[j].cur=L[k].cur;
L[k].cur=j;
cout<<"inserted successfully!"<<endl;
return ;
}
cout<<"error!"<<endl;
}
这样就可以不动声色地插入元素到链表中,通过cur进行遍历时,第l-1个元素的cur为插入元素的位置(即之前空闲的第一个位置),接着插入元素的cur为第l-1个元素之前的cur(即指向第l个元素的位置),继续遍历回到第l个元素,遍历是连续的
相当于从第l-1个位置跳到插入元素的位置再回到第l个元素的位置
实现Malloc_SLL()函数
功能:在这里需要自己实现类似malloc()函数分配空间的功能
实现:返回空闲空间的第一个位置的下标
并把空闲空间第二个位置下标赋给第一个元素
如果链表为空返回0
int Malloc_SLL(StaticLinkList &L)
{
int i=L[0].cur;
if (i)
{
L[0].cur=L[i].cur;
}
return i;
}
因为第一个元素的cur为空闲位置的第一个坐标,在这里Malloc_SLL()实现分配一个元素空间的功能,所以空闲位置的第一个坐标已被分配,所以此时第一个元素的cur应指向空闲位置的第二个坐标
三、静态链表的读取
功能:读取静态链表中第i个元素的值
实现:
①利用k作为游标,向后移动k,直到k为第i个元素的位置
③输出元素的值
void GetElem(StaticLinkList &L,int i)
{
int k=L[MAXSIZE-1].cur;
if(i>ListLength(L))
{
cout<<"have not found this element!"<<endl;
return ;
}
for (int j = 1; j <= i-1; j++)
{
k=L[k].cur;
}
cout<<L[k].data<<endl;
}
实现ListLength()函数
功能:返回静态链表的长度
实现:
①利用i作为游标,赋值i为第一个有数据元素的位置
②向后遍历,累加len,当i==0时说明到达链表最后一个数据元素的位置
int ListLength(StaticLinkList &L)
{
int len=0;
int i=L[MAXSIZE-1].cur;
while (i)
{
i=L[i].cur;
len++;
}
return len;
}
四、静态链表的删除
功能:删除单链表中第i个元素
实现:
①利用k作为游标,向后移动k,直到k为第i-1个元素的位置
②将第i-1个元素的cur赋值给j,此时j为第i个元素的位置
③将j的cur(即第i个元素的cur)赋值给第i-1(k)个元素
④“释放“L中第i个元素
void ListDelete(StaticLinkList &L,int i)
{
if (i<1||i>ListLength(L))
{
cout<<"error!"<<endl;
return ;
}
int k=MAXSIZE-1;
for (int j = 1; j < i; j++)
{
k=L[k].cur;
}
int j=L[k].cur;
L[k].cur=L[j].cur;
Free_SSL(L,j);
cout<<"deleted successfully"<<endl;
}
这里相当于跳过了第i个结点,使i-1的cur为第i个元素的cur,再“释放”第i个元素
实现Free_SSL()函数
功能:在这里需要自己实现类似free()函数释放空间的功能
实现:
①将当前空闲空间的第一个元素位置赋给释放元素的cur
②再将所释放元素的位置赋给第一个元素的cur作为空闲空间的第一个元素
void Free_SSL(StaticLinkList &L,int i)
{
L[i].data=0;
L[i].cur=L[0].cur;
L[0].cur=i;
}
将删除后的元素“归还“空闲空间”
五、静态链表的整表删除
功能:清空整个静态链表
实现:
①将最后一个元素的cur(指向第一个有数据的元素)赋给i
②遍历链表,释放结点
③将最后一个元素cur赋为0
void ClearList(StaticLinkList &L)
{
int i=L[MAXSIZE-1].cur;
while (i)
{
int j=i;
i=L[i].cur;
Free_SSL(L,j);
}
L[MAXSIZE-1].cur=0;
cout<<"cleared successfully!"<<endl;
}
六、显示静态链表中的数据
功能:显示所有数据
实现:将最后一个元素的cur(指向第一个有数据的元素)赋给i遍历输出即可
void show(StaticLinkList &L)
{
int i=L[MAXSIZE-1].cur;
while (i)
{
cout<<L[i].data<<"->";
i=L[i].cur;
}
cout<<"0"<<endl;
}
总结
本篇介绍了对静态链表的创建、插入、删除等操作。静态链表其实是为了没有指针的高级语言设计的一种单链表,虽然不一定能用到,但我们应该理解这种思维方式。
测试代码及运行实例
int main()
{
StaticLinkList a;
initList(a);
show(a);
for (int i = 1; i <= 7; i++)
{
ListInsert(a,i,i);
}
show(a);
ListInsert(a,5,500);
show(a);
ListDelete(a,5);
show(a);
GetElem(a,5);
show(a);
ClearList(a);
show(a);
return 0;
}