零、说明
- 产生原因:在不使用指针的情况下实现链表功能
- 结构说明:
(1)静态链表实际上是数组,只不过数组元素是一个结构体而不是int。
(2)静态链表可以看成两条单独的链表组合在一起。
第一条叫已用链表,顾名思义,就是已经存储元素的地方组合成一条链表。这条链表的头节点是整个数组最后一个元素。这个元素还存储目前数据数量。
第二条叫备用链表,头节点是数组第一个元素,指向此时备用链表第一个元素(也就是第一个还没使用的地方)。
所以,数组的第0个元素和最后一个元素不存数
3.理解起来确实困难,画个图能更好地帮助理解
一、数据类型
#include<stdio.h>
#define MAXSIZE 1002//存1000个数,剩下两个作为两条链表的头节点
#define TYPE int
typedef struct Node
{
TYPE data;
int cur;//指向下一个节点的"指针"
}Node,staticList[MAXSIZE];
二、初始化
开始时,全是备用链表,所以备用链表头节点(就是数组第0个元素)的指针(就是cur),指向第一个元素,而第一个元素的cur指向第二个元素(像普通链表一样串起来了)。备用链表指针的最后一个随意
同时,已用链表的最后一个元素的指针应当为0,此时就是头节点(就是数组最后一个元素)。它的cur为0
void initial(staticList l)
{
for(int i=0;i<MAXSIZE-2;i++)
{
l[i].cur=i+1;
}
l[MAXSIZE-1].data=0;
l[MAXSIZE-1].cur=0;
}
三、插入与删除
- 插入:
修改三个节点:备用链表的头节点——因为备用链表第一个存数的节点此时用来插入,新增节点——注意cur要为0已用链表尾部,上一个节点——指针由0(代表末尾)换成新增节点的位置
插入到尾部和插入到中间区别只有end(就是上述的上一个节点)的寻找
①插入到尾部
“上一个节点”就是倒数第二个节点,用while找到末尾就行
void insert(staticList l,int data)
{
if(l[MAXSIZE-1].data<MAXSIZE-2)
{
l[MAXSIZE-1].data++;
int end=MAXSIZE-1;
int newNodePosition=l[0].cur;//存储新节点的位置
while(l[end].cur!=0)
{
end=l[end].cur;
}
l[0].cur=l[newNodePosition].cur;
l[newNodePosition].data=data;
l[newNodePosition].cur=0;
l[end].cur=newNodePosition;
}
else
{
printf("Insert %d failed.\n",data);
}
}
②插入中间
"上一个节点”要定位,for直接到指定位置
void insert(staticList l,int position,int data)
{
if(l[MAXSIZE-1].data<MAXSIZE-2&&position>=1&&position<=l[MAXSIZE-1].data+1)
{
l[MAXSIZE-1].data++;
int end=MAXSIZE-1;
int newNodePosition=l[0].cur;
for(int i=1;i<position;i++)
{
end=l[end].cur;
}
l[0].cur=l[newNodePosition].cur;
l[newNodePosition].data=data;
l[newNodePosition].cur=l[end].cur;
l[end].cur=newNodePosition;
}
else
{
printf("Insert %d failed.\n",data);
}
}
- 删除
先存储待删除节点的位置,再改变上一个节点的指针为0,再改变待删除节点的指针让它作为备用链表的一部分,最后修改备用链表头指针,让待删除节点加入备用链表
void remove(staticList l,int position)
{
if(position>=1&&position<=l[MAXSIZE-1].data)
{
l[MAXSIZE-1].data--;
int end=MAXSIZE-1;
int newEmptyNodePosition;
for(int i=1;i<position;i++)
{
end=l[end].cur;
}
newEmptyNodePosition=l[end].cur;//第一个步骤
l[end].cur=l[newEmptyNodePosition].cur;//第二个步骤
l[newEmptyNodePosition].cur=l[0].cur;//第三个步骤
l[0].cur=newEmptyNodePosition;//第四个步骤
}
else
{
printf("Remove data in %d failed.\n",position);
}
}
四、搜索,遍历
搜索就是从已用链表第一个开始,从头到尾遍历。找不到就返回0
int search(staticList l,int data)
{
int position=l[MAXSIZE-1].cur;
while(position!=0)
{
if(l[position].data==data)
{
return position;
}
position=l[position].cur;
}
return 0;
}
遍历就是一个一个输出。如果为空,输出一个换行了事
void traverse(staticList l)
{
int current=l[MAXSIZE-1].cur;
while(current!=0)
{
printf("%d ",l[current].data);
current=l[current].cur;
}
printf("\n");
}