四、算法的存储空间需求
算法的空间复杂度S(n)=O(g(n))
表示随着问题规模n的增大,算法运行所需存存储量的增长率与g(n)的增长率相同。
算法的存储量包括:
1.输入数据所占空间;
2.程序本身所占空间;
3.辅助变量所占空间。
若输入数据所占空间只取决于问题本身,和算法无关,则只需要分析除输入和程序之外的辅助变量所占额外空间。
若所需额外空间相对于输入数据量来说是常数,则称次算法为原地工作。
若所所需存储量依赖于特定的输入,则通常按最坏情况考虑。
本章学习要点
1.熟悉各名词、术语的含义,掌握基本概念。
2.理解算法五个要素的确切含义
3.掌握计算语句频度和估算算法时间复杂度的方法。
思考题:
比较n^2 5log2 n 两个函数
第二章 线性表
线性结构是一个数据元素的有序(次序)集
线性结构的基本特征:
1. 集合中必须存在唯一的一个“第一元素”;
2. 集合中必须存在为一的一个“最后元素”;
3. 除最后元素在外,均有唯一的后继;
4. 除第一元素在外,均有唯一的前驱。
2.1线性表类型定义
2.2 线性表的实现 –顺序映象
2.3 线性表类型的实现 –链式映象
2.4 一元多项式的表示
2.1线性表类型定义
抽象数据类型线性表的定义如下:
ADT List
{数据对象:
D = {ai|ai{ElemSet,i=1,2,…n, n≥0}
{称n为线性表的表长;称n=0时线性表为空表。}}
}
数据关系:
R1={<ai-1,ai>|ai-1,ai∈D,i=2,…,n}
{设线性表为{a1,a2,…,ai,…,an}称i为ai在线性表中的位序。}
基本操作:
{结构初始化}
InitList(&L)
操作结果:构造一个空的线性表。
{销毁结构}
DestroyList(&L)
初始条件:线性表L已存在。
操作结果:销毁线性表L。
{引用型操作}
ListEmpty(L)
ListLength(L)
PriorElem(L,cur_e,&pre_e)
NextElem(L,cur_e,&next_e)
GetElem(L,i,&e)
LocateElem(L,e,compare())
ListTrayerse(L,visit())
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≤LengthList(L)
操作结果:用e返回L中第i个元素的值。
LocateElem(L,e,compare())
初始条件:线性表L已存在,compare()是元素判定函数。
操作结果:返回L中第一个与e满足关系compare()的元素的位序。若这样的元素不存在,则返回值为0。
ListTrayerse(L,visit())
初始条件:线性表L已存在。
操作结果:依次对L的每个元素调用visit()。一旦visit()失败,则操作失败。
利用上述定义的线性表可以完成其它更为复杂的操作。
{加工型操作}
ClearList(&L)
PutElem(L,i,&e)
ListInsert(&L,i,e)
ListDelete(&L,i,&e)
ClearList(&L)
初始条件:线性表L已存在。
操作结果:将L重置为空表。
PutElem(L,i,&e)
初始条件:线性表L已存在,1≤i≤LengthList(L)
操作结果:L中第i个元素赋值同时e的值。
ListInsert(&L,i,e)
初始条件:线性表L已存在,1≤i≤LengthList(L)+1
操作结果:在L的第i个元素之前插入新的元素e,L的长度增1。
ListDelete(&L,i,&e)
初始条件:线性表L已存在且非空,1≤i≤LengthList(L)-1。
操作结果:删除L的第i个元素,并用e返回其值,L的长度减1。
利用上述定义的线性表可以完成其它更复杂的操作。
例2-1
假设:有两个集合A和B分别用两个线性表LA和LB表示(线性表中的数据元素即集合中的成员)先要求一个新的集合A=A∪B。
上述问题可演绎为,要求对线性表作如下操作:扩大线性表LA,将存在于线性表LB中而不存在线性表LA中的数据元素插入到线性表LA中去。
1. 从线性表LB中依次取得每个数据元素;GetElem(LB,i) à e
2. 依值在线性表LA中进行查访;LocateElem(LA,e,equal())
3. 若不存在,则插入之。ListInsert(LA,n+1,e)
03_001 |
void union(List &La, List Lb) { La_len = ListLength(La); Lb_len = ListLength(Lb); //求线性表的长度 for(i = 1; i < Lb_len; i ++) { GetElem(Lb, i, e); //取Lb中的第i个元素赋给e if(!LocateElem(La, e, equal()) { ListInsert(La, ++La_len, e); //La中不存在和e相同的数据元素,则插入之 } } }//union |
例2-2
已知一个非纯集合B,试构造一个纯集合A,使A中只包含B中所有各不相同的数据元素。
03_002 |
void purge(List &La, List Lb) { //已知线性表Lb中包含非纯集合B中所有元素,试构造线性表La, //使La中只含有Lb中所有值均不相同的元素 InitList(La); //设置空的线性表La La_len = ListLength(La); La_len = ListLength(Lb); //求线性表的长度 for(i = 1; i < Lb_len; i ++) { GetElem(Lb, i, e); //从线性表Lb中取得第i个元素 if(! LocateElem(La, e, equal()) { ++ La_len; ListInsert(La, La_len, e); //元素e插入线性表La } // if } //for } //purge |
03_003 |
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; } //La中不存在和e相同的数据元素,则插入之 } } |
例2-3
归并两个“其中数据元素按值非递减有序排列的”线性表LA和LB,求得线性表LC也具有同样的特征。
设La = (a1,…,ai,…,an) Lb = (b1,…,bj,…,bm)Lc = (c1,…,ck,…,cm+n)
则 Ck = 1,2,…,m+m
1. 分别从LA和LB中取得当前元素ai和bj;
2. 若ai≤bj则将ai插入到LC中,否则将bj插入到LC中。
03_004 |
void MergerList(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); } }//merger list |