这是本次学习的第一个数据结构:线性表。
首先通过图片感受一下,线性表的特征。
——大家姑且可以把这幅图想象为老师带领同学们外出野营。因为咱们的队伍比较强大,要记住每一位同学并且区分还真是一件不容易的事。
——所以咱们想到了一个办法,让大家按照一个约定排成一队,以后大家要怎么记住自己的位置呢?没错,大家只需要记住自己前面的同学就可以了。
——老师也可以很容易的清点人数,万一有人走丢,也能在最快时间内知道是谁不见了,因为只需要问哪一位同学的“前驱”不见了即可。
线性表,从刚才描述的例子中我们很容易感受到是像排队一样,具有线一样性质的结构。
如果是下面这样,我们就不能说是线性表了:
线性表(List):由零个或者多个数组元素组成的有限序列。
——它是一个序列,有一个“先来后到”,不能没有顺序
——若存在多个元素,则第一个元素没有前驱,而最后一个元素没有后继,其他元素都有且只有一个前驱和后继
——另外,线性表强调是有限的
线性表的基本操作:
函数 | 作用 |
---|---|
InitList(*L) | 初始化操作,建立一个空的线性表L |
ListEmpty(L) | 判断线性表是否为空表,若线性表为空,返回ture,否则返回false |
ClearList(*L) | 将线性表清空 |
GetElem(L,i,*e) | 将线性表L中的第i个位置元素值返回给e |
LocateElem(L,e) | 在线性表L中查找与给定值e相等的元素,如果查找成功,返回该元素在表中序号;否则返回0表示失败 |
举例:
实现两个线性表A、B的并集操作,即要使得集合A=A∪B。
(说白了,就是把存在集合B中但不存在集合A中的元素插入到A中即可)
综合分析,我们需要运用到几个基本的操作组合即可:
代码如下:
void unionL(List *La, List Lb)
{
int La_len, Lb_len, i;
ElemType e;
La_len = ListLength(*La);
Lb_len = ListLength(Lb);
for(i=1; i<=Lb_len; i++)
{
GetElem(Lb, i, &e);
if( !LocateElem(*La, e) )
{
ListInsert(La, ++La_len, e);
}
}
}
1.首先看一下线性表顺序存储的结构代码:
#define MAXSIZE 20
typedef int ElemType;
typedef struct
{
ElemType data[MAXSIZE];
int length; // 线性表当前长度
}SqList;
由上面的代码可知,这里封装了一个结构体,事实上就是对数组进行封装,增加了当前长度的变量罢了。
总结一下,顺序存储结构封装需要三个属性:
注意一下,数组的长度与线性表的当前长度需要区分一下,数组的长度是存放线性表的存储空间的总长度,一般初始化后不变。而线性表的当前长度是线性表中元素的个数,是会变化的。数组下标要从0开始,线性表从1开始。两者之间有点区别。
2.地址计算方法
对于第i个数据元素ai的存储位置可以由a1推算得出:LOC(ai) = LOC(a1) + (i-1)*c
实现代码:
int ListInsert(SqList *L, int i, ElemType e)
{
int k;
if( L->length == MAXSIZE ) // 顺序线性表已经满了
{
return 0;
}
if( i<1 || i > L->length+1 ) // 当i不在范围内时
{
return 0;
}
if( i <= L->length ) // 若插入数据位置不在表尾
{
for( k=L->length-1; k >= i-1; k-- )
{
/* 将第i个位置后面的元素都往后移一位 */
L->data[K+1] = L->data[k];
}
}
L->data[i-1] = e; // 将新元素插入
L->length++;
return 1;
}
删除算法的思路:
实现代码:
int ListDelete(SqList *L, int i, ElemType *e)
{
int k;
if( L->length == 0 )
{
return 0;
}
if( i<1 || i > L->length )
{
return 0;
}
*e = L->data[i-1];
if( i < L->length )
{
for( k=i; k < L->length; k++ )
{
/* 分别将后面的元素的值赋给前一个元素 */
L->data[K-1] = L->data[k];
}
}
L->length--;
return 1;
}
线性表的顺序存储结构,在存、读数据时,不管是在哪个位置,时间复杂度都是O(1)。而在插入和删除时,时间复杂度都是O(n)。
这就说明,它比较适合元素个数比较稳定,不经常插入和删除元素,而更多的操作是存储数据的应用。
优点:
缺点: