目录
2.1 线性表的定义和基本操作
2.1.1 线性表的定义
线性表示具有相同数据类型的n个数据元素的有限序列 ,其中n为表长,当n=0时线性表是一个空表。除第一个元素外,每个元素有且仅有一个直接前驱;除最后一个元素外,每个元素有且仅有一个直接后继。由此得出线性表特点:
- 表中元素的个数有限。
- 表中元素具有逻辑上的顺序性,元素有先后次序。
- 表中元素都是数据元素,每个元素都是单个元素。
- 表中元素的数据类型都相同,意味着每个元素占有相同大小的存储空间。
- 表中元素具有抽象性,仅讨论元素间的逻辑关系。
2.2.2 线性表的基本操作
一个数据结构的基本操作是指其最核心、最基本的操作。其他比较复杂的操作可通过调用其基本操作来实现。线性表的主要操作如下:
- InitList(&L):初始化表。构造一个空的线性表。
- Length(L):求表长。返回线性表L的长度。
- LocatElem(L,e):按值查找操作。
- GetElem(L,i):按位查找操作。获取表L中第i个位置的元素。
- ListInsert(&L,i,e):插入操作。在表中第i个位置插入元素。
- ListDelite(&L,i,&e)删除操作。删除表L中第i个位置的元素,并用e返回。
- PrintList(L):输出操作。
- Empty(L):判空操作。若L为空表,返回true,否则返回false。
- DestroyList(&L):销毁操作。销毁线性表,并释放线性表L所占用的内存空间。
2.2 线性表的顺序表示
2.2.1 顺序表的定义
线性表的顺序存储又称顺序表。它是用一组地址连续的存储单元依次存储线性表中的数据元素,从而使得逻辑上相邻的两个元素在物理位置上也相邻,存储密度高。
顺序表最主要的特点是随机存取:即通过首地址和元素序号可在时间O(1)内找到指定的元素。
假定线性表的元素类型为ElemType,则线性表的顺序存储类型描述为:
#define MAX 50
typedef struct
{
Elemtype data[MAX];
int length;
}Sqlist; //Sequence List
该顺序表为静态分配的顺序表,在静态分配时,由于数组的大小和空间事先已经固定,再加入新的数据就会产生溢出,进而导致程序崩溃。此时解决的方法是制定动态分配的顺序表。
而在动态分配时,存储数组的空间是在程序执行过程中通过动态存储分配的,一旦数据空间占满,就另外开辟一块更大的存储空间,用以替换,从而达到扩充存储数组空间的目的,而不需要一次性划分区域。
typedef struct {
ElemType* data;
int Length;
}SeqList;//Sequence List
/*C的初始动态分配语句*/
L.data = (ElemType*)malloc(sizeof(ElemType)*InitSize);
2.2.2 顺序表上基本操作的实现
1. 插入操作
在顺序表L的第i(1<=i<=L.length+1)个位置插入新元素e。若i的输入不合法,则返回false,表示插入失败;否则,将第i个元素及其后所有元素后移一个位置,腾出一个空位置插入新元素e,顺序表长度增加1,插入成功,返回true。
bool ListInsert(Sqlist& L, int i, ElemType e)
{
if (i<1 || i>L.length+1) {
return false;
}
if (L.length > MAX) {
return false;
}
for (int j = L.length; j <= i; j--) {
L.data[j + 1] = L.data[j];
}
L.data[i] = e;
L.length++;
return true;
}
最好情况:在表尾插入(i=n+1) ,元素后移语句将不执行,时间复杂度为。
最坏情况:在表头插入(i=1),全部元素后移,后移语句执行n次,时间复杂度为。
平均情况:任何一个位置被插入的概率为 ,则在长度为n的线性表中插入一个结点时,所需移动结点的平均次数:
因此,线性表插入算法的平均时间复杂度为。
2. 删除操作
删除顺序表L中第i(1<