这么有趣的线性表你不学还是不会?
线性表的顺序表示又称为顺序存储结构或顺序映像。
顺序表的定义:把逻辑上相邻的数据元素存储在物理上相邻的存储单元中的存储结构。
简而言之,逻辑上相邻,物理上也相邻。
顺序存储方法:用一组地址连续的存储单元依次存储线性表的元素,可通过数组V[n] 来实现。
顺序表类型的定义
define MAXSIZE 100 //最大长度
typedef struct
{
ElemType *elem; //指向数据元素的基地址
int length; //线性表的当前长度
}SqList;
图书表的顺序存储结构类型定义
define MAXSIZE 10000 //图书表可能达到的最大长度
typedef struct //图书信息定义
{
char no[20]; //图书ISBN
char name[50]; //图书名字
float price; //图书价格
}Book;
typedef struct
{
Book *elem; //存储空间的基地址
int length; //图书表中当前图书个数
}SqList; //图书表的顺序存储结构类型为SqList
补充:C语言的动态分配函数(stdlib.h)
malloc(m):开辟m字节长度的地址空间,并返回这段空间的首地址
sizeof(x):计算变量x的长度
free(p): 释放指针p所指变量的存储空间,即彻底删除一个变量
/
C++的动态存储分配
new 类型名 T(初值列表)
int *p1=new int;
或 int *p1=new int(10);
功能:
申请用于存放T类型对象的内存空间,并依初值列表赋以初值
结构值:
成功:T类型的指针,指向新分配的内存
失败:0 (NULL)
delete 指针p
功能:释放指针p所指向的内存。p必须是new操作的返回值
线性表的重要基本操作
1、初始化
2、取值
3、查找
4、插入
5、删除
重要基本操作的算法实现
1、初始化线性表L (参数用引用)
Status InitList_Sq(SqList &L){ //构造一个空的顺序表
L.elem=new ElemType[MAXSIZE]; //为顺序表分配空间
if(!L.elem)exit(OVERFLOW); //存储分配失败
L.lenth=0; //空间长度为0
return OK;
}
1、初始化链表L (参数用指针)
Status InitList_Sq(SqList *L){ //构造一个空的顺序表
L->elem=new ElemType[MAXSIZE]; //为顺序表分配空间
if(!L->elem)exit(OVERFLOW); //存储分配失败
L->lenth=0; //空间长度为0
return OK;
}
补充:几个简单基本操作的算法实现
销毁线性表L
void DestroyList(SqList &L)
{
if(L.elem) delete[]L.elem; //释放存储空间
}
清空线性表L
void ClearList(SqList &L)
{
L.length=0; //将线性表的长度置为0
}
求线性表的长度
int Getlength(SqList L)
{
return (L.length);
}
判断线性表是否为空
int IsEmpty(SqList L)
{
if(L.length==0)
return 1;
else return 0;
}
2、取值 (根据位置i获取相应位置数据元素的内容)
获取线性表L中的某个数据元素的内容
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;
}
3、查找 (根据指定数据获取数据所在的位置)
在线性表L中查找值为e的数据元素
int LocateElem(SqList L,ElemType e)
{
for(i=0;i<L.length;i++)
if(L.elem[i]==e) return i+1;
return 0;
}
4、插入(插在第i个结点之前)
算法步骤
(1)判断插入位置i是否合法。
(2)判断顺序表的存储空间是否已满。
(3)将第n至第i位的元素依次向后移动一个位置,空出第i个位置。
(4)将要插入的新元素e放入第i个位置。
(5)表长加1,插入成功返回OK。
算法描述
在线性表L中第i个数据元素之前插入数据元素e
Status ListInsert_Sq(SqList &L,int i,ElemType e){
if(i<1||i>L.length) return ERROR; //i值不合法
if(L.length==MAXSIZE) return ERROR; //当前存储空间已满
for(j=L.length-1;j>=i-1lj--)
L.elem[j+1]=L.elem[j]; //插入位置及之后的元素后移
L.elem[i-1]=e; //将新元素e放入第个位置
++L.length; //表长增1
return OK;
}
算法分析
算法主要耗费在移动元素的操作上
若插入在尾结点之后。则根本无需移动(特别快);
若插入在首结点之前,则表中元素全部后移(特别慢);
若要考虑在各种位置插入(共n+1种可能)的平均移动次数,该如何计算?
5、删除(删除第i个结点)
算法步骤
(1)判断删除位置i是否合法(合法值为1<=i<=n)。
(2)将欲删除的元素保留在e中。
(3)将第i+1至第n位的元素依次向前移动一个位置。
(4)表长减1,删除成功返回OK。
算法描述
将线性表L中第i个数据元素删除
Status List Delect_Sq(SqList &L,int i){
if(i<1||i>L.length) return ERROR; //i值不合法
for(j=i;j<=L.length-1;j++)
L.elem[j-1]=L.elem[j]; //被删除元素之后的元素前移
--L.length; // 表长减1
return OK;
}
算法分析
算法时间主要耗费在移动元素的操作上
若删除尾结点,则根本无需移动(特别快);
若删除首结点,则表中n-1个元素全部前移(特别慢);
若要考虑在各种位置删除(共n种可能)的平均移动次数,该如何计算?
查找、插入、删除算法的平均时间复杂度为O(n)
显然,顺序表的空间复杂度S(n)=O(1)
(没有占用辅助空间)
顺序表的特点
(1)利用数据元素的存储位置表示线性表中相邻数据元素之间的前后关系,即线性表的逻辑结构与存储结构一致。
(2)在访问线性表时,可以快速地计算出任何一个数据元素的存储地址。因此可以粗略地认为,访问每个元素所花时间相等。
这种存取元素的方法被称为随机存取法。
顺序表的优缺点
优点:
1、存储密度大(结点本身所占存储量/结点结构所占存储量)。
2、可以随机存取表中任一元素。
缺点:
1、在插入、删除某一元素时,需要移动大量元素。
2、浪费存储空间。
3、属于静态存储形式,数据元素的个数不能自由扩充。