静态链表是数据结构线性表中的一种,因为其每一个结点只有一个直接前驱和直接后继,对于开头结点和末尾结点只有一个直接前驱或直接后继。
本人听老师讲课,看老师关于静态链表PPT时有些许不懂,看了CSDN其他关于静态链表的帖子后也还存在许多疑惑,现在自己明白之后试着把它的逻辑写出来。
我们说链表是一种链式存储结构,是因为它每一个结构体节点中存放着下一个结构体节点的地址,通过指针与地址使得链表被称作链。那么在一些语言中,因为封装较完备,我们无法对地址直接进行操作,例如java。所以静态链表可以在某种意义上替代链表。
我们知道但凡一种语言,可能没有指针,但是数组这种基本的数据类型一定会有,静态链表就是利用数组来模拟实现链表的功能。
静态链表有两种形式,第一种是以结构体为基本单元,一个结构体对应一个节点,结构体中有两个元素,一个是该节点存放的数据data,另一个是该节点存放的游标cur(注意cur中存放的是下一个节点的下标,等同于链表中的指针域,都是表示下一个节点的位置信息的);一种是构建两个同步的数组,一个数组存放data,一个数组同步存放该下标对应的cur。其实这俩差不多,第一种更加好理解一点,我们用第一种来举例:
其实我们能将静态链表这一个数组拆成两个链表来看,因为一开始创建数组没有元素存储,所以一开始待存储链表很长,已存储链表为空。我们需要存储数据的时候,就把带存储链表的第一个节点取下,用来存放数据,并把它接到已存储链表上,这样带存储链表越来越短,已存储链表越来越长。
基本思路是:第一个节点(下标index=0)的data不存放数据,cur存放待存储链表的第一个节点下标(注意,是还没有利用过的节点下标)最后一个节点的(下标为length-1)的data不存放数据,cur存放已存储链表的第一个节点的下标。
如图可看大概存储原理↑
下面展示具体代码:
构建静态链表
struct L
{
int data;
int cur;
}arr[100];//创建一百个节点大小的静态链表,并定义标签为L的结构体数据类型
#include<stdio.h>
struct L* initlist(struct L* arr,int n)//返回这个结构体数组的首地址
{
for(int i=1;i<99;i++)
{
arr[i].cur=i+1;
}
arr[0].cur=2;
arr[99].cur=1;
arr[1].data=n;
arr[1].cur=0;
return arr;
}
插入操作
插入操作涉及到几部
第一,一定会更改arr[0].cur的值,因为待存储数组的首元素被拿来存储数据,所以值会变更。
第二,可能会更改最后一个节点的cur值(即arr[99].cur),如果插入的元素存储在链表的第一个位置,则会更改。
第三,a->b –> a->c->b,更改指针指向,需要两步操作
struct L* listInsert(struct L* arr,int n,int i)
{
if(i<=0)
{
printf("错误");
return arr;
}
int k=99;
for(int j=1;j<=i-1;j++)
{
k=arr[k].cur;
if(arr[k].cur==0)
{
break;
}
}
int temp=arr[0].cur;
arr[0].cur=arr[temp].cur;
arr[temp].data=n;
arr[temp].cur=arr[k].cur;
arr[k].cur=temp;
return arr;
}
删除元素
struct L* listDelete(struct L* arr,int i)
{
if(i<=0)
{
printf("错误");
return arr;
}
int k=99;
for(int j=1;j<=i-1;j++)
{
k=arr[k].cur;
if(arr[k].cur==0)
{
printf("错误");
return arr;
}
}
int j=arr[k].cur;
arr[k].cur=arr[j].cur;
arr[j].cur=arr[0].cur;
arr[0].cur=j;
return arr;
}
就这么多吧