学习过程中记录的学习笔记,望大佬指出错误。
1.声明一个静态链表的结点
#define MAXSIZE 100 //链表的最大长度
typedef struct{
int data;
int cur; //静态的游标代替动态的指针,cur的值为后继元素的下标
}SLnode,SLinkList[MAXSIZE+1];//链表最大长度为MAXSIZE,但其中有两个结点分别为备用链表头结点,和数据链表头结点。
2.初始化(备用链表)
即开辟空间备用 ,头尾元素节点作为两个表(数据表和备用表)的头结点
备用链表表头通常是首节点;有效数据链表表头可以使用任意节点,为了方便管理,一般使用末尾节点或者第二个节点
void InitList_SL(SLinkList &space){
for(int i=0; i<MAXSIZE; ++i){
space[i].cur=i+1 ; //将每个结点前后链接
}
space[MAXSIZE].cur= 0; //备用表的倒数第二个cur为0,表示结束。
space[MAXSIZE+1].cur= 0; //一般链表最后一个结点代表数据链表的头结点
}
3.因为静态链表不具备开辟地址和删除的函数所以自行定义。
//取备用链接第一个结点,作为新的数据结点
int Malloc_SL(SLinkList &space){
int i=space[0].cur; //i为新的数据链表结点的下标
if(space[0].cur) space[0].cur=space[i].cur;//只要不是备用链接的最后一个结点,都能被调用
return i; //返回新结点的下标
}
//将删除的数据结点回收为备用结点(相当于在备用链表中插入一个结点)
void Free_SL(SLinkList &space,int i){
space[i].cur=space[0].cur;
space[0].cur=i;
}
4.建立链表(与普通单链表的尾插法思路一样)
Status CreateList_SL(SLinkList &space){ //Create创建 ,参数LinkList &L为头指针,参数n为链表的结点个数
InitList_SL(space);
int h;
h=MAXSIZE+1; //h作为数据表头结点的下标
int r=h;//定义一个r作为尾结点,初始化指向头结点(只有一个结点是头结点则为尾结点)
int n;
printf("请输入你想添加的数据成员的数量:");
scanf("%d",&n);
if(n<1||n>MAXSIZE) return OVERFLOW;
for(int i=1;i<=n;i++){
int p;
p=Malloc_SL(space);//为下标p开辟一个结点*/
printf("请输入第%d个数据成员:",i);
scanf("%d",&space[p].data); //为结点p的数据域赋值
space[r].cur=p; //r原来的游标指的尾结点成为倒数第二个结点,所以该结点的指针域指向尾结点p
r=p; //让r指向新建结点 作为尾结点
}
space[r].cur=0; //最后创建的结点为尾结点,则游标为空即为0
return OK;
}
5.(查找)定位函数:返回指定数据的位置
void LocateElem_SL(SLinkList SL,int e){
int i=SL[MAXSIZE+1].cur;//i表示首元结点的下标
while(i&&SL[i].data!=e) i=SL[i].cur;//循环直到找到e,并返回其游标cur
if(i==0){
printf("未找到\n");
}
else printf("数据链表第%d个位置为%d\n",i,e);
}
6.删除
void ListDelete_SL(SLinkList &SL,int i){
int p=MAXSIZE+1;//让p指向头结点
int count=0;//计算器为了找打第i个元素
while(p!=0&&count<i-1){ //寻找第i-1个元素
p=SL[p].cur;
count++;
}
if(p==0||count>i-1)printf("不在区间内\n");
else{
int q=SL[p].cur;//q为下一个结点即2号结点,我们要删的结点
SL[p].cur=SL[q].cur;//将为2号结点的游标给1号结点
Free_SL(SL,q);//删除2号结点,回收到备用链接
printf("删除成功\n");
}
}
7.输出静态链表的数据表
void PrintList_SL(SLinkList SL){
int count=0;
int h=MAXSIZE+1;//h为数据表头结点的下标
int i=SL[h].cur;//i为数据表头结点的游标
if(i==0) printf("数据表为空链表\n");
else{
for(i;i!=0;i=SL[i].cur){
printf("%d ",SL[i].data);
count++;
}
printf("\n链表的长度为%d(不包含头结点)",count);
printf("\n-----------------------------------------\n");
}
}
实例:
#include<stdio.h>
#include<stdlib.h>
#define TRUE 1
#define ERROR 0
#define FALSE 0
#define OK 1
#define INFEASIBLE -1
#define OVERFLOW -2
typedef int Status;
//声明一个静态链表的结点
#define MAXSIZE 100 //链表的最大长度
typedef struct{
int data;
int cur; //静态的游标代替动态的指针,cur的值为后继元素的下标
}SLnode,SLinkList[MAXSIZE+1];//链表最大长度为MAXSIZE,但其中有两个结点分别为备用链表头结点,和数据链表头结点。
/*初始化(备用链接) space空间,即开辟空间备用 ,头尾元素节点作为两个表(数据表和备用表)的头结点
备用链表表头通常是首节点;有效数据链表表头可以使用任意节点,为了方便管理,一般使用末尾节点或者第二个节点。*/
void InitList_SL(SLinkList &space){
for(int i=0; i<MAXSIZE; ++i){
space[i].cur=i+1 ; //将每个结点前后链接
}
space[MAXSIZE].cur= 0; //备用表的倒数第二个cur为0,表示结束。
space[MAXSIZE+1].cur= 0; //一般链表最后一个结点代表数据链表的头结点
}
//取备用链接第一个结点,作为新的数据结点
int Malloc_SL(SLinkList &space){
int i=space[0].cur; //i为新的数据链表结点的下标
if(space[0].cur) space[0].cur=space[i].cur;//只要不是备用链接的最后一个结点,都能被调用
return i; //返回新结点的下标
}
//将删除的数据结点回收为备用结点(相当于在备用链表中插入一个结点)
void Free_SL(SLinkList &space,int i){
space[i].cur=space[0].cur;
space[0].cur=i;
}
//建立链表(与普通单链表的尾插法思路一样)
Status CreateList_SL(SLinkList &space){ //Create创建 ,参数LinkList &L为头指针,参数n为链表的结点个数
InitList_SL(space);
int h;
h=MAXSIZE+1; //h作为数据表头结点的下标
int r=h;//定义一个r作为尾结点,初始化指向头结点(只有一个结点是头结点则为尾结点)
int n;
printf("请输入你想添加的数据成员的数量:");
scanf("%d",&n);
if(n<1||n>MAXSIZE) return OVERFLOW;
for(int i=1;i<=n;i++){
int p;
p=Malloc_SL(space);//为下标p开辟一个结点*/
printf("请输入第%d个数据成员:",i);
scanf("%d",&space[p].data); //为结点p的数据域赋值
space[r].cur=p; //r原来的游标指的尾结点成为倒数第二个结点,所以该结点的指针域指向尾结点p
r=p; //让r指向新建结点 作为尾结点
}
space[r].cur=0; //最后创建的结点为尾结点,则游标为空即为0
return OK;
}
//(查找)定位函数:返回指定数据的位置
void LocateElem_SL(SLinkList SL,int e){
int i=SL[MAXSIZE+1].cur;//i表示首元结点的下标
while(i&&SL[i].data!=e) i=SL[i].cur;//循环直到找到e,并返回其游标cur
if(i==0){
printf("未找到\n");
}
else printf("数据链表第%d个位置为%d\n",i,e);
}
//删除
void ListDelete_SL(SLinkList &SL,int i){
int p=MAXSIZE+1;//让p指向头结点
int count=0;//计算器为了找打第i个元素
while(p!=0&&count<i-1){ //寻找第i-1个元素
p=SL[p].cur;
count++;
}
if(p==0||count>i-1)printf("不在区间内\n");
else{
int q=SL[p].cur;//q为下一个结点即2号结点,我们要删的结点
SL[p].cur=SL[q].cur;//将为2号结点的游标给1号结点
Free_SL(SL,q);//删除2号结点,回收到备用链接
printf("删除成功\n");
}
}
// 输出静态链表的数据表
void PrintList_SL(SLinkList SL){
int count=0;
int h=MAXSIZE+1;//h为数据表头结点的下标
int i=SL[h].cur;//i为数据表头结点的游标
if(i==0) printf("数据表为空链表\n");
else{
for(i;i!=0;i=SL[i].cur){
printf("%d ",SL[i].data);
count++;
}
printf("\n链表的长度为%d(不包含头结点)",count);
printf("\n-----------------------------------------\n");
}
}
int main(){
//声明一个静态链表的数组
SLinkList SL,SLA,SLB;
//初始化
InitList_SL(SL);
InitList_SL(SLA);
InitList_SL(SLB);
//创建静态链表
CreateList_SL(SL);
CreateList_SL(SLA);
CreateList_SL(SLB);
//输出静态链表
PrintList_SL(SL);
PrintList_SL(SLA);
PrintList_SL(SLB);
int e=3;
//输出数据e的位置
LocateElem_SL(SL,e);
}