




版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
第二章线性表线性表的类型定义线性表的顺序表示线性表的链式表示线性链表循环链表双向链表一元多项式的表示及相加12.1
线性表的类型定义例126个英文字母组成的字母表(A,B,C,…,Z)例2
中国男篮队员情况登记表如下:号码
生日
身
置陈
4
1989
1.85
后卫……
……
……
……
……11
1987
2.12
大前锋/中锋14
1977
2.16
大前锋/中锋姚 明
13
1980
2.26
中锋…………
……
……
……2线性表的定义线性表:由n(n≧0)个数据元素(结点)a1,a2,…an组成的有限序列,其中数据元素的个数n定义为表的长度。当n=0时称为空表,常常将非空的线性表(n>0)记作:(a1,a2,…an)这里的数据元素ai(1≦i≦n)只是一个抽象的符号,其具体含义在不同的情况下可以不同。3线性表的逻辑特征对非空的线性表,有且仅有一个开始结点a1,它没有直接前趋;有且仅有一个终端结点an,它没有直接后继;其余的 结点ai(2≦i≦n-1,
n>3)都有且仅有一个直接前趋a
i-1和一个直接后继ai+1。线性表是一种典型的线性结构。4抽象数据类型线性表ADT
List{数据对象:D={ai|
ai∈ElemSet,
i=1,2,…,n,
n≥0}数据关系:R1={<ai-1,ai>|
ai-1
,ai∈D,i=2,3,…,n}数据操作:InitList(&L);DestroyList(&L);ClearList(&L);ListEmpty(L);ListLength(L);Ge em(L,
i,
&e);LocateElem(L,
e,
compare(
)
);ListInsert(&L,
i,
e);ListDelete(&L,
i,
&e);…………}ADT
List线性表的合并例2-1
假设两个线性表LA和LB分别表示两个集合A和B,求新的集合A∪B分析:将所有
到LA中。性表LB中但不在LA中的元素6线性表的合并算法假定Ge em与ListInsert执行时间与表长无关,LocateElem执行时间与表长成正比,则该算法的时间复杂度为
O(ListLength(La)*
ListLength(Lb))voidunion(List
&La,
List
Lb){La_len=ListLength(La);Lb_len=ListLength(Lb);for(
i=1;
i<=Lb_len;
i++){Ge em(Lb,
i,
&e)
;}}if(!LocateElem(La,e,
equal))ListInsert(La,
++La len,
e);先增1,然后再传递给函数这里equal是数据元素判定函数78有序线性表的合并例2-2假设两个线性表LA和LB的数据元素按值非递减有序排列,将它们合并成一个新表LC,其元素仍然按值非递减有序排列。分析:书P20-21有序线性表的合并算法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)){Ge em(La,
i,
&ai);
Ge em(Lb,
j,
&bj);if(ai<=bj){ListInsert(Lc,
++k,
ai);
++i;}else{ListInsert(Lc,
++k,
bj);
++j;}}while(i<=La.len){Ge em(La,
i++,
&ai);
ListInsert(Lc,
++k,
ai);}while(j<=Lb.len){Ge em(Lb,
j++,
&bj);
ListInsert(Lc,++k,
bj);}}时间复杂度为:O(ListLength(La)+ListLength(Lb))92.2
线性表的顺序表示顺序表
把线性表的结点按逻辑顺序依次存放在一组地址连续的 单元里。用这种方法的线性表简称顺序表。假设线性表的每个元素需占用m个 单元,并以所占的第一个单元的
地址作为数据元素的 位置作为参考点。则线性表中第i+1个数据元素的 位置Loc(ai+1)和第i个数据元素的 位置Loc(ai)之间满足下列关系:Loc(ai+1)=Loc(ai)+m10线性表的位置Loc(ai)=(i-1)*m+Loc(a1)=Loc(a1)-m+i*maiai+1m个字节i-1个元素Loc(ai+1)Loc(ai)a1a2aianLoc(a1)11用数组类型来描述顺序表由于在高级语言中的一维数组也是采用顺序 表示,故可以用数组类型来描述顺序表。又因为除了用数组来 线性表的元 外,顺序表还应该用一个变量来表示线性表的长度属性,利用C++语言的结构类型来定义顺序表类型如下:#
define
ListSize
100 //表容量typedef
int
DataType;
//以int为例struct
Sqlist{DataType
data[ListSize];};Sqlistlengthdata………int length;//当前表中元素数ListSize个此定义SqList与书上的定义(p22)相似12顺序表上实现的基本操作操作线性表的运算是指在表的i(1≦i≦n+1)个位置上,一个新结点x,使长度为n的线性表(a1,…a
i-1,ai,…,an)变成长度为n+1的线性表(a1,…a
i-1,x,ai,…,an)13操作分析a1a2…ai-1ai…ana1a2…ai-1xai…an<ai-1,ai><ai-1,x>, <x,
ai>表的长度增加14操作算法注意:C/C++语言中的数组下标从“0”开始,因此,若
L是Sqlist类型的顺序表,则表中第i个元素位置是
L.data[i-1]。voidInsertList(&L,x,i)//
性表L中第i个位置 元素x{ if(i<1
||
i>L.length+1){cout<<“
序号错误”<<endl;returnERROR;}if(L.length>=ListSize)溢出处理;else
{for(j=L.length-1;j>=i-1;j--)//第i个元素(下标为i-1)开始L.data[j+1]=L.data[j];//顺序后移
L.data[i-1]=x;L.length++;
}}15操作算法分析设表的长度为n。该算法的时间主要化费在 结点
i后移语句上,该语句的执行次数(即移动结点的次数)是n-i+1。由此,所需移动结点的次数依赖于表的长度位置。当当情况x位置=n+1时,不移动->最好情况;位置=1时,需移动表中所有结点->移动数据:n-i+1a1,…a
i-1,ai,…,an16操作算法的平均移动次数由于
可能在表中任何位置上进行,在长度为n的线性表中第i个位置上一个结点,则在第i个位置上插入一个结点的移动次数为n-i+1。令Eis(n)表示移动结点的期望值(即移动的平均次数),
Pi代表在第i个位置概率,则Eis(n)=
p1
*
n+p2*(n-1)+
….+
pn*1+pn+1
*0结点的概率是均等的,若表中任何位置(1≦i≦n+1)上则p1=p2=p3=…=p
n+1=1/(n+1)因此,在等概率 的情况下:Eis(n)=1/(n+1)[n+(n-1)+…+1+0]=n/217操作算法的时间复杂度在顺序表上做 运算,平均要移动表上一半结点。当表长
n较大时,算法的效率相当低。虽然Eis(n)中n的的系数较小,但就数量级而言,它仍然是线性阶的。因此算法的平均时间复杂度为O(n)。18删除操作线性表的删除运算是指将表的第i(1≦i≦n)结点删除,使长度为n的线性表:(a1,…a
i-1,ai,a
i+1…,an)变成长度为n-1的线性表(a1,…a
i-1,a
i+1,…,an)19删除操作分析<ai-1,
ai>,
<ai,
ai+1><ai-1,
ai+1>表的长度减少a1a2…ai-1aiai+1…an20a1a2…ai-1ai+1…an删除操作的算法voiddele
ist(&L,i)//表L中删除第i个元素{if(i<1
||
i>L.length){cout<<“删除序号错”<<endl;return
ERROR;}for(j=i;j<=L.length-1;
j++)L.data[j-1]=L.data[j];L.length--;}21删除操作算法分析算法分析与 算法相似,结点的移动次数也是由表长n和位置i决定。若i=n,无需移动结点;若i=1,则前移元素n-1个令Edl表示所需移动结点的平均次数,删除表中第i个结点的移动次数为n-i,pi是删除i个元素的概率,则Edl=p1*(n-1)+p2(n-2)+
….+pn-1*1+pn*0等概率的假设下:p1=p2=p3=…=pn=1/nEdl=1/n[(n-1)+(n-2)+…+1+0]=(n-1)/2即在顺序表上做删除运算,平均要移动表中约一半的结点,平均时间复杂度也是O(n)。2223思考题:逆序操作试写出在顺序 结构下逆转线性表的算法,要求使用最小的附加空间。voidInvList(&L){DataType
t;int
n=L.length;for(int
i=1; i<=n/2;
i++){t=L.data[i-1];L.data[i-1]=
L.data[n-i];L.data[n-i]=t;}return;}//
上的定义p22查找操作typedef
struct{ElemType
*elem;int
length;int
listsize;}SqList;int
LocateElem_Sq(SqListL,
ElemType
e,Status
(*compare)
(ElemType,
ElemType)){
在顺序线性表
中查找第
个值与
满足
pare(
)的元素的位序//若找到,则返回其在L中的位序,否则返回0i=1;
//第1个元素的位序}//p=L.elem;
//第1个元素的
位置while(i<=L.length
&&
!(*compare)(*p++,e))++i;if(i<=L.length)return
i;elsereturn
0;P25-26作业2.22.2.1以下算法中的错误和低效(即费时)之处,并将它改写成一个既正确又高效的算法。(用C++语言)Status
DeleteK(SqList
&a,
int
i,
int
k)
{//本过程从顺序
结构的线性表a中删除第i个元素起的k个元素if(i<1
||
k<0
||
i+k>a.length)return
INFEASIBLE;else{for(count=1;
count<k;
count++)
{//删除第一个元素for(j=a.length;j>=i+1;
j--)a.elem[j-1]=a.elem[j];a.length--;}return
OK;}//DeleteK//
上的定义
p22typedef
struct{ElemType
*elem;int
length;int
listsize;}SqList;作业2.22.2.2
设顺序表L中的数据元素非递减有序。试写一算法,将x
到顺序表的适当位置上,以保持该表的有序性。262.3
线性表的链式表示与实现线性链表结点和单链表的C语言描述线性表的操作在单链表中的实现循环链表双向链表272.3.1
线性链表用一组地址任意的
单元存放线性表中的数据元素。以元素(数据元素的映象)+
指针(指示后继元素
位置)=
结点(表示数据元素
或
数据元素的映象)以“结点的序列”表示线性表
称作链表2829以线性表中第一个数据元素
的存a1储地址作为线性表的地址,称作线性表的头指针。有时为了操作方便,在第一个结点之前虚加一个“头结点”,以指向头结点的a2a1
…...an^头指针头结点指针为链表的头指针。空指针线性表为空表时,头结点的指针域为空30结点和单链表的C语言描述Typedef
struct LNode
{ElemTypestruct
Lnodedata;
//数据域*next;
//指针域}
LNode,
*LinkList;LinkList L;//L
为单链表的头指针单链表操作的实现//取第i个数据元素Ge em(L,
i,&e)ListInsert(&L,
i,
e)
//ListDelete(&L,
i,
e)数据元素//删除数据元素ClearList(&L)
//重置线性表为空表Creaist(&L,n)//生成含
n个数据元素的链表3132线性表的操作Ge em(L,
i,
&e)在单链表中的实现:L211830754256∧pj3令指针p
始终指向线性表中第j
个数据元素。33因此,查找第i个数据元素的基本操作为:移动指针,比较j
和i
。单链表是一种顺序存取的结构,为找第i
个数据元素,必须先找到第i-1
个数据元素。34Status
Ge//L是em_L(LinkList
L,
int
i,
ElemType
&e)
{结点的链表的头指针,以e
返回第i
个元素p=L->next; j=1;
//p指向第一个结点,j为计数器while
(p
&&
j<i) {
p
=
p->next;
++j;
}//顺指针向后查找,直到p指向第i个元素//或p为空if
(
!p
||
j>i
)//
第i个元素不存在//
取得第i个元素算法时间复杂度为:O(ListLength(L))return
ERROR;e=
p->data;return
OK;}
//
Ge
em_Lai-1线性表的操作
ListInsert(&L,
i,
e)在单链表中的实现:有序对<ai-1,ai>改变为<ai-1,e>
和<e,
ai>eaiai-135可见,在链表中 结点只需要修改指针。但同时,若要在第
i
个结点之前元素,修改的是第i-1
个结点的指针。因此,在单链表中第i个结点之前进行
的基本操作为:找到线性表中第i-1个结点,然后修改其指向后继的指针。36O(ListLength(L37
))Status
ListInsert_L(LinkList
&L,
int
i,
ElemType
e)
{//
L
为
结点的单链表的头指针,本算法//
在链表中第i
个结点之前
新的元素
ep
=
L; j
=
0;return
ERROR;……}
//
LinstInsert_L算法的时间复杂度为:while
(p
&&
j
<
i-1){
p
=
p->next; ++j;
}if
(!p
||
j
>
i-1)//寻找第i-1
个结点//i
大于表长或者小于1s
=
(LinkList)
malloc
(
sizeof
(LNode));//生成新结点s->data
=e;s->next
=
p->next; p->next
=
s;//return
OK;eai-1aiai-1sp38线性表的操作ListDelete
(&L,i,
&e)在链表中的实现:有序对<ai-1,ai>和<ai,ai+1>改变为<ai-1,ai+1>ai-1ai+1ai-139在单链表中删除第i个结点的基本操作为:找到线性表中第i-1个结点,修改其指向后继的指针。ai-1ai+1ai-1q
=
p->next;
p->next
=
q->next;pe=
q->data;
free(q);q40Status
ListDelete_L(LinkList
&L,
int
i,
ElemType
&e)
{//删除以L
为头指针(p
=
L; j
=
0;结点)的单链表中第i
个结点while
(p->next
&&
j
<
i-1)
{
p
=
p->next; ++j;
}//寻找第i
个结点,并令p
指向其前趋if
(!(p->next)
||
j
>
i-1)return
ERROR;//删除位置不合理q
=
p->next;
p->next
=
q->next;//删除并结点e=
q->data;
free(q);return
OK;}
//
ListDelete_L算法的时间复杂度为:
O(ListLength(L)41)42操作ClearList(&L)在链表中的实现:void
ClearList(&L)
{//将单链表重新置为一个空表while
(L->next){p=L->next; L->next=p->next;free(p);}}
//ClearList算法时间复杂度:O(ListLength(L))如何从线性表得到单链表?链表是一个动态的结构,它不需要予分配空间,因此生成链表的过程是一个结点“逐个”的过程。43例如:逆位序输入n
个数据元素的值,建立
结点的单链表。操作步骤:立一个“空表”;二、输入数据元素an,建立结点并
;三、输入数据元素an-1,建立结点并
;ananan-1四、依次类推,直至输入a1为止。44for
(i=
n;i>
0;
--i)
{p=
(LinkList)
malloc
(sizeof
(LNode));scanf(&p->data);
//输入元素值p->next
=
L->next;
L->next
=
p;
//}}
//Crea
ist_L算法的时间复杂度为:
O(Listlength(L45))void
Crea ist_L(LinkList
&L,
int
n)
{//逆序输入n个数据元素,建立结点的单链表L
=
(LinkList)
malloc
(sizeof
(LNode));L->next
=
NULL;//先建立一个
结点的单链表46回顾
2.1
节中两个例子的算法,看一下当线性表分别以顺序存储结构和链表 结构实现时,它们的时间复杂度为多少?void
union(List
&La,
List
Lb)
{La_len=
ListLength(La); Lb_len
=ListLength(Lb);for
(i
=
1; i
<=
Lb_len; i++)
{Ge em(Lb,i,
e);if
(!LocateElem(La,
e,
equal(
))ListInsert(La,
++La_len,
e);}//for}//
union控制结构:for
循环基本操作:Ge em,
LocateElem
和
ListInsert当以链式映像实现抽象数据类型线性表时为:O(ListLength(La)×ListLength(Lb))例2-1算法时间复杂度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))
{Ge em(La,
i,
ai);
Ge em(Lb,
j,
bj);if
(ai
<=
bj)
{ListInsert(Lc,
++k,
ai); ++i;
}else
{
ListInsert(Lc,
++k,
bj); ++j;
}}
…
…例2-2分析比较书P31
算法2.12,书P26算法2.7和书P21
算法2.248静态链表的概念用一维数组来实现线性链表,这种用一维数组表示的线性链表,称为静态链表。静态特点:体现在表的容量是一定的。(数组的大小)链表特点:与删除同前面所述的动态链表方法相同静态链表的类型定义#define
MAXSIZE
1000
//链表的最大长度struct
Component
{data;cur;ElemTypeint}
;Component
VList[MAXSIZE];游标cursor静态链表49SLinkList类型的数组变量是结构数组,每一数组分量包括两个域:data:用于cur:用于线性表元素;直接后继元素在数组中的位置静态链表图示h=5静态链表与线性链表的区别?线性链表图示h=1020地址a4-1a30a18a220101011012210143101641018510206数组10227下标10248102691028101030a40a31010a11026a2101450例:
设 和删除只在表的头上进行h=7(5,7,2,3)(x,5,7,2,3)012345678910793-15123h=0012345678910x7793-15123表中加入x在VList中找空位置i(比如0)VList[i].data=x;VList[i].cur=h;h=i;静态链表的操作51最后一个结点的指针域的指针又指回第一个结点的链表a1a2…...an和单链表的差别仅在于,判别链表中最后一个结点的条件不再是“后继是否为空”,而是“后继是否为头结点”。522.3.2
循环链表53typedefstruct
DuLNode
{ElemType
data;//数据域struct
DuLNode*prior;//指向前驱的指针域struct
DuLNode
*next;//指向后继的指针域}
DuLNode,
*DuLinkList;2.3.3
双向链表“查询”和单链表相同。“
”和“删除”时需要同时修改两个方向上的指针。双向链表的操作特点:54ai-1aiep->next
=
s;s->next->prior
=
s;s->prior
=
p;pss->next
=
p->next;ai-1ai55ai-1删除aiai+1pp->next
=p->next->next;p->next->prior
=
p;ai-156作业2.3试写出逆转线性单链表的算法。(用C++语言)已知线性表中的元素非递减有序排列,并以 结点的单链表作
结构。
试写一高效的算法,删除表中所有值相同的多余元素(即使得操作后的线性表中的所有元素的值均不相同),同时被删结点空间,并分析算法的时间复杂度。(用C++语言)57第二章线性表2.4
一元多项式的表示及相加5859一元多项式的表示n
...
p
xnpn
(x)
p0
p
x
p
x21
2在计算机中,可以用一个线性表来表示:P
=(p0,
p1,
…,pn)但是对于形如S(x)
=
1
+
3x10000
–
2x20000但的多项式,上述表示方法是否合适?一元多项式60一元稀疏多项式一般情况下的一元稀疏多项式可写成Pn(x)
=
p1xe1
+
p2xe2
+
┄
+pmxem其中:pi
是指数为ei
的项的非零系数,0≤e1
<e2
<
┄
<
em
=
n可以下列线性表表示:((p1,
e1),
(p2,
e2),
┄,
(pm,em)
)61例如:P999(x)
=
7x3
-2x12
-
8x999可用线性表(
(7,
3),
(-2,
12),
(-8,
999)
)表示62抽象数据类型一元多项式的定义ADT
Polynomial
{数据对象:D={
ai
|
ai
∈TermSet,
i=1,2,...,m,
m≥0TermSet
中的每个元素包含一个表示系数的实数和表示指数的整数}数据关系:R1={
<ai-1
,ai
>|ai-1
,ai∈D,
i=2,...,n且ai-1中的指数值<ai中的指数值}63CreatPolyn
(
&P,
m
)操作结果:输入m项的系数和指数,建立一元多项式P。DestroyPolyn(&P)
初始条件:一元多项式P
已存在。操作结果:销毁一元多项式P。PrintPolyn
(
&P
)初始条件:一元多项式P
已存在。操作结果:打印输出一元多项式P。基本操作:64PolynLength(
P
)初始条件:一元多项式P
已存在。操作结果:返回一元多项式P
中的项数。AddPolyn
(
&Pa,
&Pb
)初始条件:一元多项式Pa
和Pb
已存在。操作结果:完成多项式相加运算,即:Pa=Pa+Pb,并销毁一元多项式Pb。SubtractPolyn
(
&Pa,
&Pb
)…
…}
ADT
Polynomial结构coefexpnnext结构:用线性链表表示。coef:系数,expn:指数,next:指针其中,头结点的expn为-1。例如:多项式
A
(x)=7
+3x
+9
x
8
+ 5x
17ha703198517∧-16566一元多项式的实现typedef
struct
{float
coef;int
expn;}
term,ElemType;//项的表示//系数//指数typedef
LinkList
polynomial;//用带表头结点的有序链表表示多项式结点的数据元素类型定义为:一个 结点的线性链表类型typedef
struct
LNode
{
//结点类型ElemTypestruct
LNodedata;*next;}
*Link,
*Position;typedef
struct{
//链表类型Link head,
tail;int
len;}
LinkList;//分别指向头结点和//最后一个结点的指针//指示链表长度书p37-3867结点的线性链表的基本操作书p37-38修改两个操作:Status
Ins (
LinkList
&L,
Link
h,
Link
s);//已知h指向线性表L中的一个结点,将s所指的结点Status
Del在h所指的结点之后(
LinkList
&L,
Link
h,
Link
&q);//已知h指向线性表L中的一个结点,删除h所指的结点之后的结点并以q返回68有序线性链表有序链表的基本操作与线性链表有两处不同:一、LocateElem(L,
e,&q,int(*compare)(ElemType,ElemType)
)初始条件:有序表L已存在。操作结果:若有序表L中存在元素e,则q指示
L中第一个值为e
的元素的位置,并返回函数值
TRUE;否则q指示第一个大于e
的元素的前驱的位置,并返回函数值FALSE。Compare是一个有序判定函数69(
12,
23,
34,
45,
56,
67,
78,
89,
98,
45
)例如:若
e
=
45,则q
指向若e=88,则q
指向表示值为
88
的元素应 在该指针所指结点之后。70二、OrderInsert(&L,
e,int(*compare)(ElemType,ElemType))初始条
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 物理往年会考题及答案
- 读《富足》读后感
- 《城南旧事》读后感800字作文
- 眼耳鼻咽喉科试题及答案
- 2025年深度解析Palantir报告
- 赞皇县2024-2025学年数学四下期末调研模拟试题含解析
- 华北水利水电大学《现代生物学仪器及应用》2023-2024学年第二学期期末试卷
- 2025年河北省容城博奥学校普通高中教育教学质量监测考试(1月)历史试题含解析
- 德州科技职业学院《计算物理》2023-2024学年第一学期期末试卷
- 广州番禺职业技术学院《微生物学Ⅰ》2023-2024学年第二学期期末试卷
- 2025年陕西省西安市不动产登记服务中心招聘25人历年高频重点提升(共500题)附带答案详解
- 2025年河北武安市委人才工作领导小组博硕引才58人历年高频重点提升(共500题)附带答案详解
- 2024年凉山交城建设有限责任公司招聘工作人员考试真题
- 麻醉、精神药品培训课件
- 道路救援设施投标管理策略
- 工程数学线性代数课后答案-同济第五版
- 中建室外管网专项施工方案
- 心血管内科医疗质量控制
- 抗美援朝资料
- 《课堂管理方法与技巧》课件
- 五年级语文下册 第三单元过关测评卷(部编版)
评论
0/150
提交评论