静态链表的初始化插入删除操作
代码收获
- 静态链表有一个备用链表和数据两条链在一个数组空间里。
- 比较特别的是需要对是否空链进行讨论,只有在空链时,-1游标对应的索引的数据是无效数据。
- 用scanf记得后面要把回车吃掉。
- 插入和删除需要考虑备用链表的操作。一般需要知道另一个变量操作位置的前一个数据的索引。
线性表归档
线性表顺序存储
线性表链式存储一——单链表
线性表链式存储二——循环链表
线性表链式存储三——双向链表
线性表链式存储四——静态链表
#include <stdio.h>
#include <stdlib.h>
//静态链表,一个游标和一个数据
#define MAXSIZE 100
typedef struct staticlist{
char data;
int cursor;
}Node,stlst[MAXSIZE];
// ap指向备用链表头
void InitialList(stlst L,int* ap) {
*ap = 1;
L[0].cursor = -1;
int i;
for(i=1;i<MAXSIZE-1;i++){
L[i].cursor=i+1; //每个空闲空间指向下一个空间做成链表
} //注意 0位置是头节点不是第一个元素
L[MAXSIZE-1].cursor=-1;//[ 0,1,2,3,4,5,6…………99]
// [-1,2,3,4,5,6,7…………-1]
}
//插入数据
int InsertData(stlst L,int*ap){
printf("输入要插入的数据,'$'结束\n");
int flag =1;
char c;
while(flag){
c = getchar();
if(c!='$'){
int i;
for(i =0;L[i].cursor!=-1;i=L[i].cursor);//i就是有数据的最后个节点(除了头节点)
int k=L[*ap].cursor;//把ap变成新节点,k是备用链表的首个元素
if (k==-1){
printf("链表已满,无法插入\n");
return 1;
} else{
L[*ap].data=c;
L[*ap].cursor=-1;
L[i].cursor=*ap;//把最后一个节点接上新节点
*ap=k;} //把ap指向备用第一个元素
}else{
flag=0;
}
}getchar();
return 0;
}
//打印数据
void PrintLst(stlst L){
printf("链表为\n");
int i;
if (L[0].cursor!=-1){//判断如果不是空链 ,如果不是,-1对应的data是要输出的
for(i=0;L[i].cursor!=-1;i=L[i].cursor){
int k = L[i].cursor ;
printf("%c",L[k].data);
}
}else{
printf("空\n");
}
}
//删除数据
int DeleteData(stlst L,int ap){
int flag = 1;
while(flag){
printf("输入删除第几个元素(从1开始)\n");
int num,k,ff,pp=0;
scanf("%d",&num);
getchar();
for (k=0;k<num;k++){
ff=pp; //ff是pp前一个元素
pp=L[pp].cursor;//pp就是num处的元素
if (pp==-1&&k!=num){//走到最后一个元素时,k还不等于num,说明输的数过大
printf("索引输入错误\n");
return 1;
}
}L[ff].cursor=L[pp].cursor ; //pp前一个游标直接指向pp下一个游标
int ss;
for (ss=ap;L[ss].cursor!=-1;ss=L[ss].cursor);//找备用链表最后一个元素
L[pp].cursor=-1;//让卸下来的变为备用最末的
L[ss].cursor=pp;//让-1的那个游标等于卸下来那个
PrintLst(L);
printf("是否继续?(y/n)\n");
char sig;
sig = getchar();
if(sig=='n'){
flag=0;
}getchar();
} return 0;
}
void main(){
stlst L;
int ap;
InitialList(L,&ap);
InsertData(L,&ap);
PrintLst(L);
DeleteData(L,ap);
InsertData(L,&ap);
PrintLst(L);
}