线性表
定义:
线性表是一个有n个同类型(具有相同特性)数据元素的有限序列。
注:一个数据元素可由若干个数据项组成
- 序列元素个数称为线性表的长度
- 线性表没有元素时,称为空表
- 表起始位置称表头,表结束位置称表尾
类型名称:线性表(List)
数据对象集:线性表是n (≥0)个元素构成的有序序列( a1, a2, …,an)
操作集:线性表L ∈List,整数i表示位置,元素X ∈ElementType,线性表基本操作主要有:
- List MakeEmpty():初始化一个空线性表L;
- ElementTypeFindKth( intK, List L ):根据位序K,返回相应元素;
- intFind( ElementTypeX, List L ):在线性表L中查找X的第一次出现位置;
- void Insert( ElementTypeX, inti, List L):在位序i前插入一个新元素X;
- void Delete( inti, List L ):删除指定位序i的元素;
- intLength( List L ):返回线性表L的长度n。
线性表的存储结构
线性表的存储结构有顺序存储结构和线性存储结构两种。前者为顺序表,后者为链表。
1. 顺序表
- 把线性表中所有元素按其逻辑顺序,依次存储到从指定的存储位置开始的一块连续空间中。
- 实现方式为:利用数组的连续存储空间顺序存放线性表的各元素。
结构体定义
typedef struct LNode*List;
struct LNode
{
ElementType Data[MAXSIZE];
int Last;
} ;
struct LNode L;
List PtrL;
//访问下标为i 的元素:L.Data[i] 或PtrL->Data[i]
//线性表的长度:L.Last+1 或PtrL->Last+1
2. 链表
- 每个结点不仅包含所存元素的信息,还包含元素之间逻辑关系的信息。如单链表中前驱节点包含后继结点的地址信息,这样就可以通过前驱结点中的地址信息找到后继结点位置。
- 不要求逻辑上相邻的两个元素物理上也相邻;通过“链”建立起数据元素之间的逻辑关系。插入、删除不需要移动数据元素,只需要修改“链”。
链表的分类
1.单链表
- 每个节点中除了包含数据域外,还包含一个指针域,用以指向其后继节点。
- 带头结点的单链表中,头指针head指向头结点,头结点的值域不含信息,从头结点的后继节点开始存储信息。头指针head始终不等于null,
head->next==NULL
时,链表为空。 - 不带头结点的单链表中的头指针head直接指向开始结点,head等于NULL时,链表为空
结点定义
typedef struct LNode *List;
struct LNode
{
ElementType Data;
List Next;
};
struct Lnode L;
List PtrL;
2.双链表
- 每个链表元素既有指向下一个元素的指针,又有指向前一个元素的指针,其中每个结点都有两种指针,即prior和next,prior指针指向前驱结点,next指针指向后继结点。
- 同样,双链表也有带头不带头之分,情况类似于单链表
结点定义
typedef struct LNode *List;
struct LNode
{
ElementType Data;
List Next;
List Prior;
}
struct Lnode L;
List PtrL;
3.循环链表
- 循环单链表,链表中的最后一个指针域指向第一个结点(带头结点则指向头结点,不带头结点则指向开始节点)。
- 循环双链表,终端节点的next指针指向链表中的第一个结点,链表中第一个结点的prior指针指向终端节点。
以下四句语句都可以判断循环双链表为空
head->next==head;
head->prior==head;
head->next==head&&head->prior==head;
head->next==head||head->prior==head;
3. 静态链表
- 静态链表是一种链式存储结构,借助一维数组来表示,用数组元素下标来模拟指针,需要预先申请足够大的存储空间,不可随机存取。
- 数据元素至少要包含以下两部分信息:
- 数据域:用于存储数据元素的值;
- 指针域:游标cur,存放下一个元素的数组下标,表示直接后继元素所在数组中的位置。
结构体定义
typedef struct LNode
{
ElementType date;
int cur;
}List ;
List L[maxsize];
备用链表
- 静态链表中,除了数据本身通过游标组成的链表外,还需要有一条连接各个空闲位置的链表,称为备用链表。
- 备用链表的作用是回收数组中未使用或之前使用过(目前未使用) 的存储空间,留待后期使用。也就是说,静态链表使用数组申请的物理空间中,存有两个链表,一条连接数据,另一条连接数组中未使用的空间。
- 静态链表中设置备用链表的好处是,可以清楚地知道数组中是否有空闲位置,以便数据链表添加新数据时使用。
- 在数据链表未初始化之前,数组中所有位置都处于空闲状态,因此都应被链接在备用链表上,当向静态链表中添加数据时,需提前从备用链表中摘除节点,以供新数据使用。
下面给出了创建静态链表的 C 语言实现代码:
#include <stdio.h> #define maxSize 6 typedef struct { int data; int cur; }component; //将结构体数组中所有分量链接到备用链表中 void reserveArr(component *array); //初始化静态链表 int initArr(component *array); //输出函数 void displayArr(component * array,int body);