一.静态链表的基本概念:
1.上图说明:索引为0处是头结点,头结点不存储数据,但存储下一个结点的数组下标,本例中头结点里存储的下一个结点的数组下标为2,即索引为2的结点为头结点后的第一个结点,以此类推;
2.上图中计算结点地址的公式中数据元素的大小和游标的大小不是固定的,可能是16B不等。
二.用代码定义一个静态链表:
1.方式一:
图示:
代码:
#include<stdio.h>
#define MaxSize 10 //定义静态链表的最大长度
struct Node //定义静态链表结构类型
{int data; //存储数据元素int next; //下一个元素的数组下标
};
void testSLinkList()
{struct Node a[MaxSize]; //数组a作为静态链表(静态链表是连续的)
}
int main()
{return 0;
}
2.方式二:
图示:
代码:
#include<stdio.h>
#define MaxSize 10 //静态链表的最大长度
typedef struct //定义静态链表结构类型
{int data; //存储数据元素int next; //下一个元素的数组下标
}SLinkList[MaxSize]; /*相当于定义了一个SLinkList类型的数组,当中的元素是SLinkList型,也就意味着有了SLinkList型的变量,testSLinkList函数里的SLinkList a也就合法了*/
void testSLinkList()
{SLinkList a; //a其实就是一个长度为10的数组,类型为SLinkList /*该数组的类型是SLinkList,每一个元素里包含data(占4B)和next(占4B),共8B大小,所以数组a总内存大小为80*/
}
int main()
{return 0;
}
#include<stdio.h>
#define MaxSize 10 //静态链表的最大长度
struct Node //定义静态链表结构类型,类型为struct Node
{int data; //存储数据元素int next; //下一个元素的数组下标
};
typedef struct Node SLinkList[MaxSize];
/*typedef为重新定义类型名符号,把struct Node重新定义为SLinkList型数组*/
void testSLinkList()
{struct Node a[MaxSize]; //struct Node为类型,a为数组名
}
int main()
{return 0;
}
3.解读:
三.简述基本操作的实现:
1.初始化静态链表:
-
头结点a[0]的next指针设为-1相当于没指向任何一个元素,等价于NULL
2.查找某个结点&插入某个结点&删除某个结点:
-
查找只能从头结点遍历查找,因此查找结点的时间复杂度为O(n)
-
注:查找的是某个位序的结点,而不是某个数组下标的结点,位序是指各个结点在逻辑上的顺序,而静态链表里的数组下标只是反应了各个结点在物理上的顺序
-
插入元素前需要遍历找到一个空位置才能插入
-
以上图为例插入一个元素,此时已经有4个元素了(头结点里的不算一个元素),那么下一个要插入的元素就是第5个元素(位序为5的元素),需要插在表尾即e4后面,此时要找的第5个元素的前驱结点即第4个元素e4,把第4个元素e4的next指针改为4,再把新插入的元素e5的next指针设为-1,因为e5是最后一个元素,后面没有其他元素了
-
注:实际上从计算机的角度看,上图中没有存数据的结点只是没有存所需要的数据,实际上会有脏数据,为了识别出结点中真正不存在数据即没有脏数据和所需要的数据,在初始化时应该把不存在数据的结点的next指针设为一个特殊的值如-2(或字符或字符串等),这样以来在判断是否有数据时只需要看索引是否为指定的不存在数据的索引如-2:
-
在删除一个结点时,需要把所删除的结点的next指针设为-2,代表此时该结点中已经没有数据了:
四.总结:
-
虽然静态链表是连续的存储空间,但在这一片连续的存储空间内各个逻辑上相邻的数据元素也可以在物理上不相邻,各个元素的关系是通过数组下标(游标)联系起来的
-
静态链表在增,删操作上不需要大量移动元素,只需要修改相关结点的数组下标(游标)即可
-
静态链表的容量是固定的,不能改变
-
文件分配表FAT本质是静态链表