05.线性表(四)链式存储结构.静态链表

链式存储结构.静态链表  

一、静态链表

1.静态链表存储结构

单链表是通过指针实现的,但是我们也可以通过数组来代替指针描述单链表,即静态链表。如何实现静态链表?构造数组的元素由两个数据域组成:data和cur,即数组的每个下标都对应一个data和一个cur。

数据域data:用来存放数据元素,即要处理的数据;

游标cur:存放该元素的后继在数组中的下标,相当于单链表中的next指针;

为了方便插入数据,我们通常会把数组建立得大一些,以便有一些空闲空间而不致于出现溢出情况。

线性表的静态链表存储结构:

#define MAXSIZE 1000    //假设链表的长度为1000(个元素)

typedef struct

{

ElemType data;    //数据域,int类型

int cur;          //游标(Cursor),为0时表示无指向

}Component,StaticLinkList(MAXSIZE);

2.备用链表

由于数组的第一个和最后一个元素作为特殊元素处理,不存数据,因此我们把未使用的数组元素称为备用链表。

因此,我们规定:

(1)数组第一个元素(即下标为0的元素)的游标cur存放第一个空闲空间元素的下标(备用链表的第一个元素);

(2)数组最后一个元素的游标cur存放第一个有数值的元素的下标(相当于单链表中的头结点作用)。当整个链表为空时则最后一个元素的游标cur为0。

(3)链表的最后一个有值元素的cur为0


升华笔记:如何将一维数组list中各分量链成一个备用链表?

typedef  int Status

Status InitList(StaticLinkList list)

{

int i;        //i为数组下标,MAXSIZE为链表长度

for(i=0;i<MAXSIZE-1;i++)

{

list[i].cur=i+1;    // 将数组第一个元素的游标cur指向备用链表的第一个结点存储位置(数组下标),依次类推

}

list[MAXSIZE-1].cur=0;    //目前静态链表为空,最后一个有值元素的cur为0

}


二、静态链表的插入/删除操作

静态链表的插入和删除操作,最关键是要解决如何用静态模拟动态链表结构的存储空间的分配,需要时申请,无用时释放。

1.静态链表的插入操作

(1)算法思路

为了辨明数组中哪些分量未被使用,解决的办法是将所有违背使用过的及已被删除的分量用游标cur链成一个备用的链表(即空链表),每当进行插入时,便可以从备用链表上取得第一个结点(即未被使用的第一个结点)最为待插入新结点。

实现获取空闲分量下标Malloc_SLL函数算法:

a.获取数组第一个元素的游标cur=i,其存放的是备用链表的第一个空闲结点;

b.将数组第i个元素的游标cur=i+1赋值给头指针

c.返回被使用的数组元素下标

int i=list[0].cur;         //如i=list[0].cur=7

list[0].cur=list[i].cur; //头指针list[0].cur=list[7].cur=8

return i;

(2)源码实现

/*1.若备用空间链表为空,则返回分配的结点下标,否则返回0*/

int Malloc_SLL(StaticLinkList list)

{

int i=list[0].cur;        //获取备用链表的第一个结点下标(当前数组第一个元素的cur存储第一个备用空闲的下标)

if(list[0].cur)            //如果list[0].cur!=0,则说明数组含有非空元素

{

list[0].cur=list[i].cur;    //由于要拿出一个备用链表的结点使用,我们需要将数组第一个元素的cur存放下一个空出来的元素作备用

}

return i;//返回被使用的下标

}

//注释:假如先前list[0].cur=7(数组下标值),当下标为7的分量(数组元素)准备被使用了,就得有接替者,所以把分量7(list[i].cur,其中i=7)的cur值=8,赋值给头元素(list[0].cur),之后就可以继续分配新的空闲分量。//

/*2.在L中第i个元素之前插入新的数据元素e*/

typedef int Status

typedef int ElemType

Status ListInsert(StaticLinkList L,int i,ElemType e)

{

int j,k,m;

k=MAX_SIZE-1;    //注意:k首先是最后一个元素的下标

if(j<1 || j>ListLength(L)+1)

return ERROR;

j=Malloc_SLL(L);        //a.获得空闲分量的下标

if(j)

{

L[j].data=e;              //b.将数据赋值给此分量的data

for(m=1;m<i-1;i++)  //c.找到第i个元素之前的位置,将数组最后一个元素的cur(=1)存到变量k

k=L[k].cur;    //k=1

L[j].cur=L[k].cur;    //将第i个元素之前的cur赋值给新元素的cur

L[k].cur=j;          //把新元素的下标赋值给第i个元素

return OK;

}

return ERROR;

}

注释:第i个元素,是指链表的第i个元素,非数组下标存储位置。

i-插入静态链表位置;j-存储空间空闲位置;

2.静态链表的删除操作

源码实现

/*1.将下标为k的空闲结点回收到备用链表*/

void Free_SSL(StaticLinkList space,int k)

{

space[k].cur=space[0].cur;    //将数据的第一个元素cur(其值为备用链表的第一个空闲元素下标),赋值给要删除分量的cur

space[0].cur=k;    //把要删除的分量下标赋值给第一个元素的cur

}

/*2.删除在L中第i个数据元素e*/

typedef int Status

Status ListDelete(StaticLinkList L,int i)

{

int i,k;

if(i<1 || i>ListLength(L))

return ERROR;

k=MAXSIZE-1;            //存储链表最后一个元素的下标

for(j=1;j<=i-1;j++)

k=L[k].cur;            //找到要删除元素的前一个元素,并将其cur值赋值给k(即要删除元素的下标)

j=L[k].cur;                     //将删除元素的游标值赋值给j,即值为下一个元素的下标

L[k].cur=L[j].cur;

Free_SSL(L,j);

}

/*3.初始条件:静态链表L已经存在。操作结果:返回L中数据元素个数*/

int ListLength(StaticLinkList L)

{

int j=0;

int i=L[MAXSIZE-1].cur;

while(i)

{

i=L[i].cur;

j++;

}

return j;

}

三、静态链表的优缺点

1.优点

在插入和删除操作时只需要修改游标,不需要移动元素,从而改进了在顺序存储结构中的插入和删除操作需要移动大量元素的缺点;

2.缺点

(1)没有解决连续存储分配带来的表长度难以确定的问题;

(2)失去了顺序存储结构随机存取的特性;

时间: 2024-08-02 15:47:59

05.线性表(四)链式存储结构.静态链表的相关文章

03.线性表(二)链式存储结构.单链表1

链式存储结构.单链表1 1.基本概念 为了表示每个数据元素ai与其直接后继数据元素ai+1之间的逻辑关系,对数据元素ai来说,除了存储其本身的信息之外,还需存储一个指示其直接后继的信息(即直接后继的存储位置) (1)数据域:存储线性表数据元素数据信息的域称为数据域: (2)指针域:把存储直接后继位置(下一个数据元素的地址)的域称为指针域,指针域中存储的信息为指针或链: (3)结点(Node):由数据域和指针域两部分信息组成数据元素ai的存储映像,称为结点. (4)头指针:把链表中第一个结点的存储

04.线性表(三)链式存储结构.单链表2

链式存储结构.单链表2 顺序存储结构的创建实质是一个数组的初始化,存储空间连续且其大小和类型已经固定:单链表存储空间不连续,是一种动态结构且它所占用空间的大小和位置是不需要预先分配划定的,可以根据系统的情况和实际的需求即时生成. 一.单链表的整表创建 创建单链表的过程就是一个动态生成链表的过程,即从"空表"的初始化起,依次建立各元素结点,并逐个插入链表. 1.算法思路 (1)声明一个结点p和计数器变量i; (2)初始化一空链表L (3)让链表L的头结点的指针指向NULL,即建立一个带头

线性表的链式存储结构(链表)

链表:基于来链式存储的线性表 链式逻辑存储结构:基于链式存储结构的线性表中,每个节点都包含数据域和指针域(数据域:存储数据元素本身.指针域:存储相邻节点的地址.) 单链表:链表的每个节点只包含后一个元素的地址信息  循环链表:链表的最后一个元素的包含第一个元素的地址信息 双向链表:链表的节点中包含后驱和前驱的地址信息 链表基本概念: 头节点(辅助节点.不包含数据域,指针域指向第0个数据元素)+ 数据节点(数据域+地址域)+  尾节点(指针域为空或某一值,只有数据域) 单链表节点定义: struc

数据结构--线性表的链式存储结构

一 线性表的链式存储结构 A.链式存储的定义为了表示每个数据元素与直接后继元素之间的逻辑关系:数据元素除了存储本身的信息外,还需要存储其直接后继的信息图示B链式存储逻辑结构基于链式存储结构的线性表中,每个结点都包含数据域和指针域1.数据域:存储数据元素本身2.指针域:存储相邻结点的地址图示C链表中的基本概念1.头结点--链表中的辅助结点,包含指向第一个数据元素的指针(方便插入和删除)2.数据结点--链表中代表数据元素的结点,表现形式为:(数据元素,地址)3.尾节点--链表中的最后一个数据结点,包

线性表的链式存储结构

1 n个结点链结成一个链表,即为线性表的链式存储结构,由于每一个结点只包含一个指针域,因此称为单链表. 链表中第一个结点的存储位置成为头指针,那么整个链表的存取就必须是从头指针开始了. 有时候会在单链表的第一个结点前附设一个结点,称为头结点. 头指针与头结点的区别: 头指针: (1)头指针是指链表指向第一个结点的指针,若链表有头结点,则是指向头结点的指针. (2)头指针具有标识作用,所以常用头指针冠以链表的名字. (3)无论链表是否为空,头指针都不为空.头指针是链表的必要元素. 头结点: (1)

数据结构之线性表(链式存储结构)

线性表的实现分顺序存储结构和链式存储结构 上一节我们主要介绍了顺序存储结构,在最后我们还分别总结了顺序存储结构的优缺点, 对于顺序结构的缺点,我们有没有什么好的解决方法呢? 我们今天要介绍的线性表的链式存储结构就可以很好的解决顺序结构的缺点,一起来看. 顺序结构最大的缺点就是在进行插入和删除操作的时候,如果插入位置不理想,那么我们需要移动大量的元素,那产生这一问题的原因是什么呢? 仔细分析后,我们可以发现在顺序存储结构中,他们相邻的元素的存储位置也是相邻的,我们在申请内存的的时候,是一次性申请一

【数据结构】-线性表的链式存储结构

引言:由于线性表的顺序存储结构在插入和删除时需要大量移动数据元素,从而引入线性表的链式存储结构. 线性表的链式存储结构:用一组任意的存储单元(可以连续也可以不连续)存储线性表的数据元素. 为了表示数据元素ai和其直接后继ai+1之间的逻辑关系,对ai来说,除了存储其本身的数据信息外,还需要存储其直接后继的存储位置.这两部分信息组成数据元素ai的存储映像(结点).它包含两个域:其中存储数据元素信息的域称为数据域:存储直接后继存储位置的域称为指针域. n个结点链接成一个链表,称为线性链表,由于此链表

数据结构开发(5):线性表的链式存储结构

0.目录 1.线性表的链式存储结构 2.单链表的具体实现 3.顺序表和单链表的对比分析 4.小结 1.线性表的链式存储结构 顺序存储结构线性表的最大问题是: 插入和删除需要移动大量的元素!如何解决? 链式存储的定义: 为了表示每个数据元素与其直接后继元素之间的逻辑关系:数据元素除了存储本身的信息外,还需要存储其直接后继的信息. 链式存储逻辑结构: 基于链式存储结构的线性表中,每个结点都包含数据域和指针域 数据域:存储数据元素本身 指针域:存储相邻结点的地址 专业术语的统一: 顺序表 基于顺序存储

《数据结构 - 线性表》链式存储 (单链表)

一:线性表定义 -<数据结构 - 线性表>顺序存储结构 二:为什么要 链式存储 线性表? - 因为在使用 顺序结构 存储方式存储的时候,每次进行 插入/删除 都需要大量移动元素的位置. - 所以设计出一种 存储空间不连续 的存储结构. - 这个线性表可能是这样的(存储位置不固定) -  三:链式存储 定义 -  因为链式存储,不是连续空间,所以需要两个信息 - 一个用于 存储数据元素,也叫做 数据域 - 一个用于 指向 下一个位置 的 指示信息,叫做指针域. - 指针域中存储的信息叫指针/链