【Data】数据结构之线性表(1)
1、线性表的定义
线性表是最常用且最简单的一种数据结构。
一个线性表是n个数据元素的有限序列。
数据元素可以是一个数、一个符号、也可以是一幅图、一页书或更复杂的信息。
1.1线性表的类型定义
抽象数据类型线性表的定义如下:
ADT List
{ 数据对象:D={ ai | ai ∈ElemSet, i=1,2,...,n, n≥0 }
{称n为线性表的表长;称n=0时的线性表为空表}
数据关系:R1={ |ai-1 ,ai∈D, i=2,...,n }
{设线性表为(a1,a2,...ai,....an),称i为A在线性表中的位序}
基本操作:
{ 初始化 } InitList( &L )
操作结果:构造一个空的线性表L。
{ 结构销毁 } DestroyList( &L )
初始条件:线性表L已存在。 操作结果:销毁线性表L。
{ 引用型操作 }ListEmpty( L )
初始条件:线性表L已存在。 操作结果:若L为空表,则返回TRUE, 否则FALSE。
ListLength( L )
初始条件:线性表L已存在。 操作结果:返回L中元素个数。
GetElem( L, i, &e )
初始条件:线性表L已存在, 1≤i≤LengthList(L) 操作结果:用e返回L中第i个元素的值。
LocateElem( L, e, compare( ) )
初始条件:线性表L已存在,compare( ) 是元素判定函数。 操作结果:返回L中第1个与e满足关系 compare( )的元素的位序。若这样的元 素不存在,则返回值为0。
PriorElem( L, cur_e, &pre_e )
初始条件:线性表L已存在。 操作结果:若cur_e是L的元素,但不是 第一个,则用pre_e 返回它的前驱, 否则操作失败,pre_e无定义。
NextElem( L, cur_e, &next_e )
初始条件:线性表L已存在。 操作结果:若cur_e是L的元素,但不是 最后一个,则用next_e返回它的后继, 否则操作失败,next_e无定义。
ListTraverse(L, visit( ))
初始条件:线性表L已存在。 操作结果:依次对L的每个元素调用函数 visit( )。一旦visit( )失败,则操作失败。
{ 加工型操作 }
ClearList( &L )
初始条件:线性表L已存在。 操作结果:将L重置为空表。
PutElem( L, i, &e )
初始条件:线性表L已存在, 1≤i≤ListLength(L) 操作结果:L中第i个元素赋值同e的值。
ListInsert( &L, i, e )
初始条件:线性表L已存在, 1≤i≤ListLength(L)+1 操作结果:在L的第i个元素之前插入新 的元素e,L的长度增1。
ListDelete(&L, i, &e)
初始条件:线性表L已存在且非空, 1≤i≤ListLength(L) 操作结果:删除L的第i个元素,并用e 返回其值,L的长度减1。
} ADT List
2、线性结构的特点:
在数据元素的非空有限集中,
(1)存在唯一的一个被称做“第一个”的数据元素;
(2)存在唯一的一个被称做“最后一个”的数据元素;
(3)除第一个之外,集合中的每个数据元素均只有一个前驱;
(4)除最后一个之外,集合中每个数据元素均只有一个后继。
3、线性表的顺序表示:
(下一篇再研究线性表的链式表示)
用一组地址连续的存储单元依次存储线性表的数据元素。C语言中的数组即采用顺序存储方式。
LOC(ai) = LOC(ai-1) + l
(l 为一个数据元素所占存储量 )
线性表中任意一个数据元素的存储位置都可以线性表中 第一个数据元素 a1的存储地址来表示,
LOC(a i) = LOC(a 1 ) + (i-1)*I
l称第一个数据元素的存储地址为 线性表的起始地址,称作线性表的 基地址
#define LIST_INIT_SIZE 100 #define LISTINCREMENT 10 typedef struct{ ElemType *elem; //存储空间基址 int length; //当前长度 int listsize; //当前分配的存储容量以一数据元素存储长度为单位 }SqList;
(下面这几段代码,我觉得可能在面试的时候会让写上一段儿的。我猜的)
status ListInsert(List *L,int i,ElemType e) { struct STU *p,*q; if (i<1||i>L->length+1) return ERROR; q=&(L->elem[i-1]); for(p=&L->elem[L->length-1];p>=q;--p) *(p+1)=*p; *q=e; ++L->length; return OK; }/*ListInsert Before i */
void MergeList(List *La,List *Lb,List *Lc) { ElemType *pa,*pb,*pc,*pa_last,*pb_last; pa=La->elem;pb=Lb->elem; Lc->listsize = Lc->length = La->length + Lb->length; pc = Lc->elem = (ElemType *)malloc(Lc->listsize * sizeof(ElemType)); if(!Lc->elem) exit(OVERFLOW); pa_last = La->elem + La->length - 1; pb_last = Lb->elem + Lb->length - 1; while(pa<=pa_last && pb<=pb_last) { if(Less_EqualList(pa,pb)) *pc++=*pa++; else *pc++=*pb++; } while(pa<=pa_last) *pc++=*pa++; while(pb<=pb_last) *pc++=*pb++; }
int LocateElem(List *La,ElemType e,int type) { int i; switch (type) { case EQUAL: for(i=0;i<length;i++) if(EqualList(&La->elem[i],&e)) return i; break; default: break; } return 0; }
void UnionList(List *La, List *Lb) { int La_len,Lb_len; int i; ElemType e; La_len=ListLength(La); Lb_len=ListLength(Lb); for(i=0;i<Lb_len;i++) { GetElem(*Lb,i,&e); if(!LocateElem(La,e,EQUAL)) ListInsert(La,++La_len,e); } }