产生“静态链表”的原因是动态链表采用指针存储结构,导致内存碎片化的情况,静态链表可解决动态链表在内存分配上的问题。它适用的场景有:1、系统资源有限时;2、不支持指针的低级语言;3、数据元素数量固定不变的场景等。
一、产生“静态链表”的原因
静态链表是在数组的基础上实现的一种链式存储结构。它的出现是为了解决动态链表在内存分配上的问题。由于动态链表采用指针存储结构,每一个节点都需要开辟一个空间来存储指针,因此存在着频繁的内存分配和释放,导致内存碎片化的情况。而静态链表是将链表节点原本应该存储指针的位置变为存储数据元素的位置,在节点中增加一个指针域,用于指向链表中下一个节点在数组中的索引位置,这样就不会频繁释放和分配内存,也避免了内存碎片的问题。
二、静态链表的适用场景
1、系统资源有限时
静态链表的实现方式既可以充分利用内存空间,又可以避免动态分配内存时造成的内存碎片,因此在系统资源有限的情况下,静态链表是一个不错的选择。
2、不支持指针的低级语言
因为静态链表用数组来表示链表,用数组元素的下标来模拟链表的指针,所以可用于不支持指针的低级语言,但仅限于低级语言。
3、数据元素数量固定不变的场景
静态链表要求在定义时指定链表的元素数量,因此适用于元素数量固定的场景。
4、经常需要顺序遍历
静态链表可以使用数组下标直接访问每个节点,因此在需要经常进行顺序遍历时,静态链表的效率优于动态链表。
三、静态链表简介
静态链表是在数组的基础上实现的一种链式存储结构。对于线性链表,也可用一维数组来进行描述。这种描述方法便于在没有指针类型的高级程序设计语言中使用链表结构。在C语言中,静态链表的表现形式即为结构体数组,结构体变量包括数据域data和游标CUR。
这种存储结构,仍需要预先分配一个较大的空间,但在作为线性表的插入和删除操作时不需移动元素,仅需修改指针,故仍具有链式存储结构的主要优点。假如有如上的静态链表S中存储着线性表(a,b,c,d,f,g,h,i),Maxsize=11,要在第四个元素后插入元素e,方法是:先在当前表尾加入一个元素e,即:S[9].data = e;然后修改第四个元素的游标域,将e插入到链表中,即:S[9].cursor = S[4].cursor; S[4].cursor = 9;,接着,若要删除第7个元素h,则先顺着游标链通过计数找到第7个元素存储位置6,删除的具体做法是令S[6].cursor = S[7].cursor。
代码示例1:
short Malloc(component *L)//分配空间
{
unsigned short i;
i=L[0].cur;
if(L[0].cur){
L[0].cur=L.cur;
return i;//成功返回空间位置
}
return 0;//失败返回0
}
void Free(component *L, short i) //回收空间
{
L.cur=L[0].cur;
L[0].cur=i;
}
void Disp(component *T, component *L)//显示静态链表数据
{
while(T->cur){
T=&L[T->cur];
printf("%c", T->data);
} printf("\n");
}
void Purge(component *T, component *L) //删除重复数据
{ component *
tmp, *temp;
for(T=&L[T->cur]; T->data; T=&L[T->cur]){//若T->data中没数据,则退出循环
for(temp=T, tmp=&L[T->cur]; tmp->data;){//若tmp->data中没数据,则退出循环
if(T->data==tmp->data){
temp->cur=tmp->cur;
Free(L, (short)(tmp-L));//回收空间
tmp=&L[temp->cur];
} else{
tmp=&L[tmp->cur];
temp=&L[temp->cur];
} }
} }
void Union(component *A, component *B, component *L)//(A-B)交(B-A)
{ component *T, *ta, *tb=B;
short flag;//用于判断是否进行了删除操作
B=&L;
while(B->data){//循环判断,直到B表中所有数据都和A表比较过后才结束
代码示例2:
#include<stdio.h>
#include"definition.h"
void Init(component *L)//初始化静态链表
{
unsigned short i;
for(i=0; i<MAXSIZE-1; i++)
L[i].cur=i+1;
L[MAXSIZE-1].cur=0;
}
component* Insert(component *L)//插入数据到
链表
{
component *T, *
temp1, *temp2;
unsigned short i;
ElemType ch;
if( i=Malloc(L) ){
T=temp1=&L;
T->cur=0;
} else
return 0;
while( (ch=getchar()) != '\n' ){
if( i=Malloc(L) ){
temp2=&L;
temp2->data=ch;
temp2->cur=0;
temp1->cur=i;
temp1=temp2;
} else
return 0;
}
return T;
}
延伸阅读1:动态链表简介
动态链表在初始时不一定分配足够的空间, 但是在后续插入的时候需要动态申请存储空间,并且存储空间不一定连续,在进行插入和删除时则不需要移动元素, 修改指针域即可,所以仍然具有链表的主要优点,链表结构可以是动态地分配存储的,即在需要时才开辟结点的存储空间,实现动态链接。