C语言有指针,可以存储下一个位置的地址,而不是所有语言都有指针。为了让这些语言也实现像链表一样的功能。就有人想出来了用数组来实现的链表。
主要理解这种思想,不一定要会写。
#define MAXSIZE 1000
typedef int ElementType;
typedef struct
{
ElementType data;
int cur;
}Component, StaticLinkList[MAXSIZE];
初始化
空表是这样的,space
是数组名
bool InitList(StaticLinkList space)
{
int i;
for (int i = 0; i < MAXSIZE - 1; i++)
{
space[i].cur = i + 1;
}
space[MAXSIZE -1 ].cur = 0;
return true;
}
右上角是cur。
加了6个元素后
可以将这个1000个容量的数组看成四部分。
- 下标为0的元素存放后面的空闲位置下标
- 最后一个元素存放链表第一个元素位置下标(链表第一个元素是甲)
- 链表的最后一个元素的cur为0
- 链表元素的每一个元素的后继存在cur中
正好解决了:
- 下一个往哪里放
- 谁是头结点
- 谁是尾结点
- 每个元素后继是谁
四个问题。
插入操作
插入丙应该要做下面几件事:
- 将空闲位置下标后移一个(7->8)
/*返回空闲位置下标*/
int Malloc_SLL(StaticLinkList space)
{
int i = space[0].cur;
if (space[0].cur)
space[0].cur = space[i].cur; //后移操作
return i;
}
- 把乙的cur指向丙,丙的cur指向丁
/*在第i个元素前插入元素e*/
bool ListInsert(StaticLinkList L, int i, ElementType e)
{
int j, k, l;
k = MAXSIZE - 1;
if (i < 1 || i > ListLength(L) + 1) //如图中是不大于7
return false;
j = Malloc_SLL(L);
if (j)
{
L[j].data = e; //丙放入第一个空闲位置
for (l = 1; l <= i - 1; l++)//找到第i个位置之前的位置,这里i是3找到是2
k = L[k].cur;
/*
k = L[999].cur = 1
k = L[1].cur = 2
*/
L[j].cur = L[k].cur; //L[7].cur = L[2].cur = 3 丙的后继为丁
L[k].cur = j;//L[2].cur = 7 乙的后继为丙
return true;
}
return false;
}
删除操作
删除,要做下面几件事
- 删除位置的前一个元素指向删除位置的后一个元素
- 后面的空闲位置结点接上删除的结点
- 删除的结点作为第一个空闲结点
bool ListDelete(StaticLinkList L, int i)
{
int j, k;
if (i < 1 || i > ListLength(L))
return false;
k = MAXSIZE - 1;
for (j = 1; j <= i - 1; j++)
k = L[k].cur;
j = L[k].cur; //要删除的下标给j,k就是其前一个位置
L[k].cur = L[j].cur; //要删除的下一个位置给要删除的前一个位置
L[j].cur = L[0].cur; //将原来的空闲结点位置接上删除结点
L[0].cur = j; //把要删除的作为第一个空闲结点
return true;
}
理解没有指针的链表是怎么来的。
L[k].cur与list->next有异曲同工之妙。下标也与每个指针链表中的node意义相同。