2.1 线性表的类型定义.
2.2 线性表的顺序映象.
2.3 线性表的链式映象.
线性结构:是一个数据元素的有序(是指数据元素次序有序)集。
线性结构的基本特征:
1,集合中必存在唯一的一个"第一元素";
2,集合中必存在唯一的一个"最后元素"
3,除最后元素之外,均有唯一的后继;
4,除第一元素之外,均有唯一的前驱,
ADT List{
数据对象:
D = { a i ∣ a i ∈ E l e m S e t ; i = 1 , 2 , . . . , n ; n ⩾ 0 } D=\{ a_{i}| a_{i} \in ElemSet; i=1,2,...,n; n\geqslant 0 \} D={ai∣ai∈ElemSet;i=1,2,...,n;n⩾0}
数据关系:
R 1 = { < a i − 1 , a i > ∣ a i − 1 , a i ∈ D ; i = 2 , . . . , n } R1=\{ <a_{i-1},a_{i}> | a_{i-1},a_{i}\in D; i=2,...,n \} R1={<ai−1,ai>∣ai−1,ai∈D;i=2,...,n}
基本操作:
{结构初始化}
InitList(&L)
操作结果:构造一个空的线性表L。
{销毁结构}
DestroyList(&L)
初始条件:线性表L已存在。
操作结果:销毁线性表L。
{引用型操作}
ListEmpty(L)
初始条件:线性表L已存在。
操作结果:若L为空表,则返回TRUE,否则返回FALSE。
ListLength(L)
初始条件:线性表L已存在。
操作结果:返回L中数据元素个数。
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无定义。
GetElem(L, i, &e)
初始条件:线性表L已存在, 1 ⩽ i ⩽ L i s t L e n g t h ( L ) 1\leqslant i\leqslant ListLength(L) 1⩽i⩽ListLength(L)。
操作结果:用e返回L中第i个数据元素的值。
LocateElem(L, e, compare())
初始条件:线性表L已存在,compare()是数据元素判定函数。
操作结果:返回L中第1个与e满足关系compare()的数据元素的位序。若这样的数据元素不存在,则返回值为0。
ListTraverse(L, visit())
初始条件:线性表L已存在。
操作结果:依次对L的每个数据元素调用函数visit()。一旦visit()失败,则操作失败。
{加工型操作}
ClearList(&L)
初始条件:线性表L已存在。
操作结果:将L重置为空表。
PutElem(L, i, &e)
初始条件: 线性表L已存在, 1 <= i <= LengthList(L)
操作结果: L中第i个元素赋值同e的值。
ListInsert(&L, i, e)
初始条件:线性表L已存在, 1 ⩽ i ⩽ L i s t L e n g t h ( L ) + 1 1 \leqslant i\leqslant ListLength(L)+1 1⩽i⩽ListLength(L)+1。
操作结果:在L中第i个位置之前插入新的数据元素e,L的长度加1。
ListDelete(&L, i, &e)
初始条件:线性表L已存在且非空, 1 ⩽ i ⩽ L i s t L e n g t h ( L ) 1\leqslant i\leqslant ListLength(L) 1⩽i⩽ListLength(L)。
操作结果:删除L的第i个数据元素,并用e返回其值,L的长度减1。
}ADT List
例1:假设有两个集合A和B分别用两个线性表LA和LB表示(即:线性表中的数据元素即为集合中的成员)现要求一个新的集合A=AUB。
上述问题可演绎为:要求对线性表作如下操作:扩大线性表LA,将存在于线性表LB中而不存在于线性表LA中的数据元素插入到线性表LA中去。
1、从线性表LB中依次取得每个数据元素:GetElem(LB, i) -> e
2、依值在线性表LA中进行查访:LocateElem(LA, e, equal())
3、若不存在,则插入之:ListInsert(LA, n+1, e)
void union(List &La, List Lb){
La_len = Listlength(La);
Lb_len = ListLength(Lb);//求线性表的长度
for(int i=1; i<=Lb_len, i++){
GetElem(Lb, i, e); //取Lb中第i个数据元素赋给e。
if(!LocateElem(La, e, equal())){
Listlnsert(La, ++La_len, e);
//La中不存在和e相同的数据元素,则插入之
}
}
} //union
上述算法的时间复杂度:
控制结构: for循环
基本操作: LocateElem(La, e, equal())
当以顺序映像实现抽象数据类型线性表时为:
n
2
n^{2}
n2
当以链式映像实现抽象数据类型线性表时为: n 2 n^{2} n2
例2:已知一个非纯集合B,试构造一个纯集合A.使A中只包含B中所有值各不相同的数据元素。
// 若 Lb 为没有排序的线性表
void purge(Lis &La, List Lb){
//已知线性表Lb中包会非纯集合B中所有元素,
//试构造线性表La,使La中只含Lb中所有值均不相同的元素
InitList(La);//设置空的线性表La
La_len = ListLength(La);
Lb_len = ListLength(Lb);//求线性表的长度
for(i=l;i<=Lb_len; i++){
GetElem(Lb, i, e);//从线性表Lb中取第i个元素
if(!LocateElem(La, e, cqual())){
++La_len;
ListInsert(La, La_len, e);//元素e插入线性表La
}//if
}//for
}//purge
上述算法的时间复杂度:
控制结构: for循环
基本操作: GetElem(Lb, i, e)
当以顺序映像实现抽象数据类型线性表时为:
当以链式映像实现抽象数据类型线性表时为:
// 若 Lb 为按关键字排序后的线性表
void purge(List &La, List Lb){
InitList(La);
La_len = ListLength(La);
Lb_len = ListLength(Lb); //求线性表的长度
for(i=1, i<=Lb_len; i++){
GetElem(Lb, i, e);//取Lb中第i个数据元素赋给e
if(ListEmpty(La) || !equal(en, e)){
ListInsert(La, ++La_len, e);
en = e; //en为刚刚插入的最后一个元素
}//La不存在和e相同的数据元索,则插入之
}
}//purge
例3:归并两个”其数据元素按值非递减有序排列的“线性表LA和LB,求得线性表LC也具有同样特性。
void MergeList(List La, List Lb, List &Lc){
InitList(Lc);
i = j = 1;
k = 0;
La_len = ListLength(La);
Lb_len = ListLength(Lb);
while((i<=La_len) && (j<=Lb_len)){
//La和Lb均非空
GetElem(La, i, ai);
GetElem(Lb, j, bj):
if(ai <= bj){
ListInsert(Lc, ++k, ai);
++i;
}else{
ListInsert(Lc, ++k, bj);
++j;
}
}
while(i<=La_len){
GetElem(La, i++, ai);
ListInsert(Lc, ++k, ai);
}
while(j<=Lb_len){
GetElem(Lb, j++, bj);
ListInsert(Lc, ++k, bj);
}
}//MergeList
上述算法的时间复杂度
控制结构:三个并列的while循环
基本操作:ListInsert(Lc, ++k, e)
当以顺序映像实现抽象数据类型线性表时为:
当以链式映像实现抽象数据类型线性表时为: