目录
前言
参考数据
- 数据结构C语言版(严蔚敏,李冬梅,吴伟民)
- 大话数据结构(程杰)
参考课程
线性表
线性表是具有相同特性的数据元素的一个有限序列
- 存在唯一一个被称作“第一个”的数据元素
- 存在唯一一个被称作“最后一个”的数据元素
- 除第一个之外,结构中的每个数据元素均只有一个直接前驱
- 除最后一个之外,结构中的每个数据元素均只有一个直接后继
线性表的存储结构
在计算机内,线性表有两种基本的存储结构,分别是顺序存储结构和链式存储结构
顺序存储表示
线性表的顺序表示又称为顺序存储结构和顺序映像
顺序存储定义:把逻辑上相邻的数据元素存储在物理上相邻的存储单元中的存储结构。
简而言之,逻辑上相邻,物理上也相邻。
线性表的第1个数据元素a1的存储位置,称为线性表的起始位置或基地址 或 基地址。
我们假设线性表的每个元素需占L个存储单元,则第i+1个数据元素的存储位置和第i个数据元素的存储位置之间的关系是:
LOC(
a
i
+
1
a_i+1
ai+1)=LOC(
a
i
a_i
ai)+L
由此,我们可以推出所有数据元素的存储位置均可由第一个数据元素的存储位置得到:
LOC(
a
i
a_i
ai)=LOC(
a
1
a_1
a1)+(i-1)*L
例子
多项式的顺序存储结构类型定义
#define MAXSIZE 1000 //多项式可能到达的最大长度
typedef struct{ //多项式非零项的定义
float p; //系数
int e; //指数
}Polynomial;
typedef struct{
Polynomial *elem; //存储空间的基地址
int length; //多项式中当前项的个数
}SqList; //多项式的顺序存储结构类型为SqList
顺序表中基本操作的实现
在这之前,我们需要先了解一下C++中的new和delete的用法,以及引用类型做形参的用法
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define INFEASIBLE -1
#define OVERFLOW -2
typedef int Status;
typedef char ElemType;
线性表L的初始化
//线性表L的初始化(参数用引用)
Status InitList_Sq(SqList &L) //构建一个空的顺序表L
{
L.elem=new ElemType[MAXSIZE]; //为顺序表分配空间
if(!L.elem) exit(OVERFLOW); //存储分配失败
L.length=0; //空表长度为0
return OK;
}
销毁线性表
void DestoryList(SqList &L)
{
if(L.elem) delete L.elem; //释放存储空间
}
清空线性表
void ClearList(SqList &L)
{
L.length=0; //将线性表的长度置为0
}
求线性表L的长度
int GetLength(SqList L)
{
return (L.length);
}
判断线性表L是否为空
int IsEmpty(SqList L)
{
if(L.length==0) return 1;
else return 0;
}
顺序表的取值
int GetElem(SqList L,int i,ElemType &e)
{
if(i<1||i>L.length) return ERROR; //判断i是否合理,若不合理,返回ERROR
e=L.elem[i-1]; //第i-1的单元存储着第i个元素
return OK;
}
显然,该算法的时间复杂度为O(1)
顺序表的查找
//顺序表的查找
int LocateElem(SqList L,ElemType e)
{
for(i=0;i<L.length;i++)
if(L.elem[i]==e) return i+1;
return 0;
}
对含有n个记录的表,查找成功时:ASL=
∑
i
=
1
n
P
i
C
i
\displaystyle\sum_{i=1}^{n} P_iC_i
i=1∑nPiCi
其中
P
i
P_i
Pi为第i个记录被查找的概率,
C
i
C_i
Ci为找到第i个记录需要比较的次数
我们假设每个元素的查找概率相等,即
P
i
P_i
Pi=1 / n;则原式可化简为ASL=
1
n
\frac{1}{n}
n1
∑
i
=
1
n
i
\displaystyle\sum_{i=1}^{n} i
i=1∑ni =
n
+
1
2
\frac{n+1}{2}
2n+1.
由此可见,时间复杂度为O(n)。
顺序表的插入
Status ListInsert(SqList &L,int i,ElemType e)
{
if(i<1||i>L.length+1) return ERROR; //i值不合法
if(L.length==MAXSIZE) return ERROR; //当前储存空间已满
for(j=L.length-1;j>=i-1;j--)
L.elem[j+1]=L.elem[j]; //插入位置及之后的元素后移
L.elem[i-1]=e; //将新元素e放到第i个位置
++L.length; //表长加1
return OK;
}
顺序表的删除
Status ListDelete(SqList &L,int i)
{
if(i<1||i>L.length) return ERROR;
for(j=i;j<=L.length-1;j++)
L.elem[j-1]=L.elem[j]; //将被删除元素之后的元素前移
--L.length; //表长减一
return OK;
}
分析可得
1
n
\frac{1}{n}
n1
∑
i
=
1
n
(
n
−
i
)
\displaystyle\sum_{i=1}^{n} (n-i)
i=1∑n(n−i) =
n
−
1
2
\frac{n-1}{2}
2n−1.
故时间复杂度为O(n).
顺序存储优缺点
优点
- 存储密度大(结点本身所占存储量/结点结构所占存储量)
- 可以随机存储表中任一元素
缺点
- 插入和删除操作需要移动大量元素
- 浪费存储空间
- 属于静态存储结构,数据元素的个数不能自由扩充