线性表是平时一直会用到的数据结构,像python里面的list这种高级数据结构,其实也是对这种底层结构的封装。
这篇文章写了整整4天........
线性表的储存结构主要分两大类,一类一类来看。
在这之前,先用伪代码来形容一下线性表拥有的基本功能
1 :顺序储存结构
听名字就知道,这是按照顺序来排的,简单来说,就是在用顺序储存结构来建立线性表的时候,他是在内存里面先申请一块空地
然后,所有的相同类型的数据元素按照顺序,放进去,并且,在内存中的存放,也是连续的!
也就是打个比方a,b,c三个元素的内存地址,如果按照顺序储存结构的话就会是0x00001 ---> 0x00002 ---> 0x00003
另外,顺序储存的时候,由于是先申请内存空间,再放入线性表,所以,正常来说,数组长度(也就是申请的空间大小)是大于等于线性表长度的
其次,数组内元素的下标,是要比第i个元素的i少一位的,如下图.
概括一下,线性表的储存结构可以用以下代码来抽象表示
#define MAXSIZE 20 /* 存储空间初始分配量 */
typedef struct
{
ElemType data[MAXSIZE]; /* 数组,存储数据元素 */
int length; /* 线性表当前长度 */
}SqList;
每个数据元素,其实在内存中都有他的固定地址的
然后由于顺序线性表的都是连续固定的,所以根据每种元素的数据类型的不同,你可以看出后面元素的不同内存地址
假设我们存放的是整数int,他每个元素要占用c个空间,那么我们用LOC(a)来表示a这个元素的内存地址的话
那么LOC(ai+1)=LOC(ai)+C
那么LOC(ai)可以根据a1的LOC来推算出他的内存地址LOC(ai)=LOC(a1)+(i-1)*c
所以,由于内存地址都是连续的,所以你完全可以通过第一个元素就知道其中第i个元素的值,所以,读取或存放的时间复杂度为O(1)
1 顺序储存线性表的元素获取
#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0
typedef int Status; /* Status是函数的类型,其值是函数结果状态代码,如OK等 */
/* 初始条件: 顺序线性表L已经存在,1≤i≤ListLength(L) */
/* 操作结果: 用e返回L 中第i个数据元素的值 */
Status GetElem(SqList L,int i,ElemType *e) /* 这里等于是定义GetElem返回时整型 ,这句函数其实等于int GetElem */
{
if(L.length==0 || i<1 || i>L.length)
return ERROR;
*e=L.data[i-1];
return OK;
}
如果数组长度为0 或 i小于1 或 i 大于数组长度最大位的后一位,直接返回ERROR
否则,代表能读到这个数,则给 *e 赋值,值为数组数据的第i-1下标位的数值,并返回OK
2 顺序储存线性表的元素插入
这个原理和插队是一样的,比如一共10个人的队伍,你认识第4个人,你让他给你插下队,那你认识的人就变成第5个了,你变成了第4个,队列长度要加1
/* 初始条件:顺序线性表L已存在,1≤i≤ListLength(L), */
/* 操作结果:在L中第i个位置之前插入新的数据元素e,L的长度加1 */
Status ListInsert(SqList *L,int i,ElemType e)
{
int k;
if (L->length==MAXSIZE) /* 顺序线性表已经满 */
return ERROR;
if (i<1 || i>L->length+1)/* 当i比第一位置小或者比最后一位置后一位置还要大时 */
return ERROR;
if (i<=L->length) /* 若插入数据位置不在表尾 */
{
for(k=L->length-1;k>=i-1;k--) /* 将要插入位置之后的数据元素向后移动一位,k>=i-1等于是说明