数据结构各章习题及答案.docx
《数据结构各章习题及答案.docx》由会员分享,可在线阅读,更多相关《数据结构各章习题及答案.docx(91页珍藏版)》请在冰豆网上搜索。
数据结构各章习题及答案
数据结构习题及解答
第1章概述
【例1-1】分析以下程序段的时间复杂度。
for(i=0;ifor(j=0;jA[i][j]=0;解:该程序段的时间复杂度为O(m*n)。【例1-2】分析以下程序段的时间复杂度。i=s=0;①while(s{i++;②s+=i;③}解:语句①为赋值语句,其执行次数为1次,所以其时间复杂度为O(1)。语句②和语句③构成while循环语句的循环体,它们的执行次数由循环控制条件中s与n的值确定。假定循环重复执行x次后结束,则语句②和语句③各重复执行了x次。其时间复杂度按线性累加规则为O(x)。此时s与n满足关系式:s≥n,而s=1+2+3+…+x。所以有:1+2+3+…+x≥n,可以推出:x=x与n之间满足x=f(),所以循环体的时间复杂度为O(),语句①与循环体由线性累加规则得到该程序段的时间复杂度为O()。【例1-3】分析以下程序段的时间复杂度。i=1;①while(i<=n)i=2*i;②解:其中语句①的执行次数是1,设语句②的执行次数为f(n),则有:。得:T(n)=O()【例1-4】有如下递归函数fact(n),分析其时间复杂度。fact(intn){if(n<=1) return(1); ①elsereturn(n*fact(n-1)); ②}解:设fact(n)的运行时间函数是T(n)。该函数中语句①的运行时间是O(1),语句②的运行时间是T(n-1)+O(1),其中O(1)为常量运行时间。由此可得fact(n)的时间复杂度为O(n)。习题1一、单项选择题1.数据结构是指(1.A)。A.数据元素的组织形式B.数据类型C.数据存储结构D.数据定义2.数据在计算机存储器内表示时,物理地址与逻辑地址不相同的,称之为(2.C)。A.存储结构B.逻辑结构C.链式存储结构D.顺序存储结构3.树形结构是数据元素之间存在一种(3.D)。A.一对一关系B.多对多关系C.多对一关系D.一对多关系4.设语句x++的时间是单位时间,则以下语句的时间复杂度为(4.B)。for(i=1;i<=n;i++)for(j=i;j<=n;j++)x++;A.O(1)B.O()C.O(n)D.O()5.算法分析的目的是(5.C、),算法分析的两个主要方面是(A)。(1)A.找出数据结构的合理性B.研究算法中的输入和输出关系C.分析算法的效率以求改进D.分析算法的易懂性和文档性(2)A.空间复杂度和时间复杂度B.正确性和简明性C.可读性和文档性D.数据复杂性和程序复杂性6.计算机算法指的是(6.C、),它具备输入,输出和(B)等五个特性。(1)A.计算方法B.排序方法C.解决问题的有限运算序列D.调度方法(2)A.可行性,可移植性和可扩充性B.可行性,确定性和有穷性C.确定性,有穷性和稳定性D.易读性,稳定性和安全性7.数据在计算机内有链式和顺序两种存储方式,在存储空间使用的灵活性上,链式存储比顺序存储要(7.B)。A.低B.高C.相同D.不好说8.数据结构作为一门独立的课程出现是在(8.D)年。A.1946B.1953C.1964D.19689.数据结构只是研究数据的逻辑结构和物理结构,这种观点(9.B)。A.正确B.错误C.前半句对,后半句错D.前半句错,后半句对10.计算机内部数据处理的基本单位是(10.B)。A.数据B.数据元素C.数据项D.数据库二、填空题1.数据结构按逻辑结构可分为两大类,分别是______________和_________________。1.线性结构,非线性结构2.数据的逻辑结构有四种基本形态,分别是________________、__________________、__________________和__________________。2.集合,线性,树,图3.线性结构反映结点间的逻辑关系是__________________的,非线性结构反映结点间的逻辑关系是__________________的。3.一对一,一对多或多对多4.一个算法的效率可分为__________________效率和__________________效率。4.时间,空间5.在树型结构中,树根结点没有__________________结点,其余每个结点的有且只有__________________个前趋驱结点;叶子结点没有__________________结点;其余每个结点的后续结点可以__________________。5.前趋,一,后继,多 6.在图型结构中,每个结点的前趋结点数和后续结点数可以__________________。6.有多个7.线性结构中元素之间存在__________________关系;树型结构中元素之间存在__________________关系;图型结构中元素之间存在__________________关系。7.一对一,一对多,多对多8.下面程序段的时间复杂度是__________________。8.O()for(i=0;ifor(j=0;jA[i][j]=0;9.下面程序段的时间复杂度是__________________。9.O()i=s=0;while(s{i++;s+=i;}10.下面程序段的时间复杂度是__________________。10.O()s=0;for(i=0;ifor(j=0;js+=B[i][j];sum=s;11.下面程序段的时间复杂度是__________________。11.O(logn)i=1;while(i<=n)i=i*3;12.衡量算法正确性的标准通常是__________________________。12.程序对于精心设计的典型合法数据输入能得出符合要求的结果。13.算法时间复杂度的分析通常有两种方法,即___________和___________的方法,通常我们对算法求时间复杂度时,采用后一种方法。13.事后统计,事前估计三、求下列程序段的时间复杂度。1.x=0;for(i=1;ifor(j=i+1;j<=n;j++)x++;1.O()2.x=0;for(i=1;ifor(j=1;j<=n-i;j++)x++;2.O()3.inti,j,k;for(i=0;ifor(j=0;j<=n;j++){c[i][j]=0;for(k=0;kc[i][j]=a[i][k]*b[k][j]}3.O(n)4.i=n-1;while((i>=0)&&A[i]!=k))j--;return(i);4.O(n)5.fact(n){if(n<=1)return(1);elsereturn(n*fact(n-1));}5.O(n)第2章线性表【例2-1】试编写出将两个顺序存储的有序表A和B合成一个有序表C的算法。解:假设A、B和C的类型为下述SqList类型:#definemaxlen1000typedefintelemtypetypedefstruct{elemtypeelem[maxlen];intlen;}SqList;设A和B的数据元素均为整数且为升序排列,设A的长度为m,B的长度为n,则合并后C的长度为m+n。合并时进行A、B元素的比较,将较小的链入C中,算法描述如下:intmerge(SqList*A,SqList*B,SqList*C)//将两个有序表A和B合成一个有序表C{intm,n,i,j,k;m=(*A).len;n=(*B).len;if(m+n>maxlen-1){printf("overflow");exit(0);}i=0;j=0;//i和j分别作为扫描顺序表A和B的指针k=0;//k指示顺序表C中当前位置while((i<=m)&&(j<=n))if((*A).elem[i]<=(*B).elem[j]){(*C).elem[k]=(*A)elem[i];i++;k++;}else{(*C).elem[k]=(*B)elem[j];j++;k++;}while(i<=m)//表B已结束,表A没有结束,链入表A的剩余部分{(*C).elem[k]=(*A).elem[i];i++;k++;}while(j<=m)//表A已结束,表B没有结束,链入表B的剩余部分{(*C).elem[k]=(*B).elem[j];i++;k++;}return(1);}【例2-2】写一算法实现单链表的逆置。解:假设单链表的表头指针用head表示,其类型为下面定义的LinkList,并且单链表不带头结点。逆置后原来的最后一个结点成为第一个结点,于是从第一个结点开始逐个修改每个结点的指针域进行逆置,且刚被逆置的结点总是新链表的第一个结点,故令head指向它(如图2-1所示)。typedefstructNode{elemtypedata;structNode*next;}LinkList; 具体算法描述如下:voidcontray(LinkList*head){//将head单链表中所有结点按相反次序链接LinkList*p,*q;p=head;//p指向未被逆序的第一个结点,初始时指向原表头结点head=NULL;while(p!=NULL){q=p;//q指向将被逆序链接的结点p=p->next;q->next=head;head=q;}}【例2-3】假设有一个循环链表的长度大于1,且表中既无头结点也无头指针,已知p为指向链表中某结点的指针,设计在链表中删除p所指结点的前趋结点的算法。解:可引入一个指针q,当q->next=p时,说明此时q所指的结点为p所指结点的前趋结点,从而可得算法如下:voiddelete(LinkList*p){//在链表中删除p所指结点的前趋结点LinkList*q,*t;q=p;while(q->next->next!=p)//q->next不是p的前趋结点q=q->next;t=q->next;//t指向要删除结点q->next=p;//删除t结点free(t);}【例2-4】试设计实现删除单链表中值相同的多余结点的算法。解:该例可以这样考虑,先取开始结点的值,将它与其后的所有结点值一一比
for(j=0;jA[i][j]=0;解:该程序段的时间复杂度为O(m*n)。【例1-2】分析以下程序段的时间复杂度。i=s=0;①while(s{i++;②s+=i;③}解:语句①为赋值语句,其执行次数为1次,所以其时间复杂度为O(1)。语句②和语句③构成while循环语句的循环体,它们的执行次数由循环控制条件中s与n的值确定。假定循环重复执行x次后结束,则语句②和语句③各重复执行了x次。其时间复杂度按线性累加规则为O(x)。此时s与n满足关系式:s≥n,而s=1+2+3+…+x。所以有:1+2+3+…+x≥n,可以推出:x=x与n之间满足x=f(),所以循环体的时间复杂度为O(),语句①与循环体由线性累加规则得到该程序段的时间复杂度为O()。【例1-3】分析以下程序段的时间复杂度。i=1;①while(i<=n)i=2*i;②解:其中语句①的执行次数是1,设语句②的执行次数为f(n),则有:。得:T(n)=O()【例1-4】有如下递归函数fact(n),分析其时间复杂度。fact(intn){if(n<=1) return(1); ①elsereturn(n*fact(n-1)); ②}解:设fact(n)的运行时间函数是T(n)。该函数中语句①的运行时间是O(1),语句②的运行时间是T(n-1)+O(1),其中O(1)为常量运行时间。由此可得fact(n)的时间复杂度为O(n)。习题1一、单项选择题1.数据结构是指(1.A)。A.数据元素的组织形式B.数据类型C.数据存储结构D.数据定义2.数据在计算机存储器内表示时,物理地址与逻辑地址不相同的,称之为(2.C)。A.存储结构B.逻辑结构C.链式存储结构D.顺序存储结构3.树形结构是数据元素之间存在一种(3.D)。A.一对一关系B.多对多关系C.多对一关系D.一对多关系4.设语句x++的时间是单位时间,则以下语句的时间复杂度为(4.B)。for(i=1;i<=n;i++)for(j=i;j<=n;j++)x++;A.O(1)B.O()C.O(n)D.O()5.算法分析的目的是(5.C、),算法分析的两个主要方面是(A)。(1)A.找出数据结构的合理性B.研究算法中的输入和输出关系C.分析算法的效率以求改进D.分析算法的易懂性和文档性(2)A.空间复杂度和时间复杂度B.正确性和简明性C.可读性和文档性D.数据复杂性和程序复杂性6.计算机算法指的是(6.C、),它具备输入,输出和(B)等五个特性。(1)A.计算方法B.排序方法C.解决问题的有限运算序列D.调度方法(2)A.可行性,可移植性和可扩充性B.可行性,确定性和有穷性C.确定性,有穷性和稳定性D.易读性,稳定性和安全性7.数据在计算机内有链式和顺序两种存储方式,在存储空间使用的灵活性上,链式存储比顺序存储要(7.B)。A.低B.高C.相同D.不好说8.数据结构作为一门独立的课程出现是在(8.D)年。A.1946B.1953C.1964D.19689.数据结构只是研究数据的逻辑结构和物理结构,这种观点(9.B)。A.正确B.错误C.前半句对,后半句错D.前半句错,后半句对10.计算机内部数据处理的基本单位是(10.B)。A.数据B.数据元素C.数据项D.数据库二、填空题1.数据结构按逻辑结构可分为两大类,分别是______________和_________________。1.线性结构,非线性结构2.数据的逻辑结构有四种基本形态,分别是________________、__________________、__________________和__________________。2.集合,线性,树,图3.线性结构反映结点间的逻辑关系是__________________的,非线性结构反映结点间的逻辑关系是__________________的。3.一对一,一对多或多对多4.一个算法的效率可分为__________________效率和__________________效率。4.时间,空间5.在树型结构中,树根结点没有__________________结点,其余每个结点的有且只有__________________个前趋驱结点;叶子结点没有__________________结点;其余每个结点的后续结点可以__________________。5.前趋,一,后继,多 6.在图型结构中,每个结点的前趋结点数和后续结点数可以__________________。6.有多个7.线性结构中元素之间存在__________________关系;树型结构中元素之间存在__________________关系;图型结构中元素之间存在__________________关系。7.一对一,一对多,多对多8.下面程序段的时间复杂度是__________________。8.O()for(i=0;ifor(j=0;jA[i][j]=0;9.下面程序段的时间复杂度是__________________。9.O()i=s=0;while(s{i++;s+=i;}10.下面程序段的时间复杂度是__________________。10.O()s=0;for(i=0;ifor(j=0;js+=B[i][j];sum=s;11.下面程序段的时间复杂度是__________________。11.O(logn)i=1;while(i<=n)i=i*3;12.衡量算法正确性的标准通常是__________________________。12.程序对于精心设计的典型合法数据输入能得出符合要求的结果。13.算法时间复杂度的分析通常有两种方法,即___________和___________的方法,通常我们对算法求时间复杂度时,采用后一种方法。13.事后统计,事前估计三、求下列程序段的时间复杂度。1.x=0;for(i=1;ifor(j=i+1;j<=n;j++)x++;1.O()2.x=0;for(i=1;ifor(j=1;j<=n-i;j++)x++;2.O()3.inti,j,k;for(i=0;ifor(j=0;j<=n;j++){c[i][j]=0;for(k=0;kc[i][j]=a[i][k]*b[k][j]}3.O(n)4.i=n-1;while((i>=0)&&A[i]!=k))j--;return(i);4.O(n)5.fact(n){if(n<=1)return(1);elsereturn(n*fact(n-1));}5.O(n)第2章线性表【例2-1】试编写出将两个顺序存储的有序表A和B合成一个有序表C的算法。解:假设A、B和C的类型为下述SqList类型:#definemaxlen1000typedefintelemtypetypedefstruct{elemtypeelem[maxlen];intlen;}SqList;设A和B的数据元素均为整数且为升序排列,设A的长度为m,B的长度为n,则合并后C的长度为m+n。合并时进行A、B元素的比较,将较小的链入C中,算法描述如下:intmerge(SqList*A,SqList*B,SqList*C)//将两个有序表A和B合成一个有序表C{intm,n,i,j,k;m=(*A).len;n=(*B).len;if(m+n>maxlen-1){printf("overflow");exit(0);}i=0;j=0;//i和j分别作为扫描顺序表A和B的指针k=0;//k指示顺序表C中当前位置while((i<=m)&&(j<=n))if((*A).elem[i]<=(*B).elem[j]){(*C).elem[k]=(*A)elem[i];i++;k++;}else{(*C).elem[k]=(*B)elem[j];j++;k++;}while(i<=m)//表B已结束,表A没有结束,链入表A的剩余部分{(*C).elem[k]=(*A).elem[i];i++;k++;}while(j<=m)//表A已结束,表B没有结束,链入表B的剩余部分{(*C).elem[k]=(*B).elem[j];i++;k++;}return(1);}【例2-2】写一算法实现单链表的逆置。解:假设单链表的表头指针用head表示,其类型为下面定义的LinkList,并且单链表不带头结点。逆置后原来的最后一个结点成为第一个结点,于是从第一个结点开始逐个修改每个结点的指针域进行逆置,且刚被逆置的结点总是新链表的第一个结点,故令head指向它(如图2-1所示)。typedefstructNode{elemtypedata;structNode*next;}LinkList; 具体算法描述如下:voidcontray(LinkList*head){//将head单链表中所有结点按相反次序链接LinkList*p,*q;p=head;//p指向未被逆序的第一个结点,初始时指向原表头结点head=NULL;while(p!=NULL){q=p;//q指向将被逆序链接的结点p=p->next;q->next=head;head=q;}}【例2-3】假设有一个循环链表的长度大于1,且表中既无头结点也无头指针,已知p为指向链表中某结点的指针,设计在链表中删除p所指结点的前趋结点的算法。解:可引入一个指针q,当q->next=p时,说明此时q所指的结点为p所指结点的前趋结点,从而可得算法如下:voiddelete(LinkList*p){//在链表中删除p所指结点的前趋结点LinkList*q,*t;q=p;while(q->next->next!=p)//q->next不是p的前趋结点q=q->next;t=q->next;//t指向要删除结点q->next=p;//删除t结点free(t);}【例2-4】试设计实现删除单链表中值相同的多余结点的算法。解:该例可以这样考虑,先取开始结点的值,将它与其后的所有结点值一一比
A[i][j]=0;
解:
该程序段的时间复杂度为O(m*n)。
【例1-2】分析以下程序段的时间复杂度。
i=s=0;①
while(s{i++;②s+=i;③}解:语句①为赋值语句,其执行次数为1次,所以其时间复杂度为O(1)。语句②和语句③构成while循环语句的循环体,它们的执行次数由循环控制条件中s与n的值确定。假定循环重复执行x次后结束,则语句②和语句③各重复执行了x次。其时间复杂度按线性累加规则为O(x)。此时s与n满足关系式:s≥n,而s=1+2+3+…+x。所以有:1+2+3+…+x≥n,可以推出:x=x与n之间满足x=f(),所以循环体的时间复杂度为O(),语句①与循环体由线性累加规则得到该程序段的时间复杂度为O()。【例1-3】分析以下程序段的时间复杂度。i=1;①while(i<=n)i=2*i;②解:其中语句①的执行次数是1,设语句②的执行次数为f(n),则有:。得:T(n)=O()【例1-4】有如下递归函数fact(n),分析其时间复杂度。fact(intn){if(n<=1) return(1); ①elsereturn(n*fact(n-1)); ②}解:设fact(n)的运行时间函数是T(n)。该函数中语句①的运行时间是O(1),语句②的运行时间是T(n-1)+O(1),其中O(1)为常量运行时间。由此可得fact(n)的时间复杂度为O(n)。习题1一、单项选择题1.数据结构是指(1.A)。A.数据元素的组织形式B.数据类型C.数据存储结构D.数据定义2.数据在计算机存储器内表示时,物理地址与逻辑地址不相同的,称之为(2.C)。A.存储结构B.逻辑结构C.链式存储结构D.顺序存储结构3.树形结构是数据元素之间存在一种(3.D)。A.一对一关系B.多对多关系C.多对一关系D.一对多关系4.设语句x++的时间是单位时间,则以下语句的时间复杂度为(4.B)。for(i=1;i<=n;i++)for(j=i;j<=n;j++)x++;A.O(1)B.O()C.O(n)D.O()5.算法分析的目的是(5.C、),算法分析的两个主要方面是(A)。(1)A.找出数据结构的合理性B.研究算法中的输入和输出关系C.分析算法的效率以求改进D.分析算法的易懂性和文档性(2)A.空间复杂度和时间复杂度B.正确性和简明性C.可读性和文档性D.数据复杂性和程序复杂性6.计算机算法指的是(6.C、),它具备输入,输出和(B)等五个特性。(1)A.计算方法B.排序方法C.解决问题的有限运算序列D.调度方法(2)A.可行性,可移植性和可扩充性B.可行性,确定性和有穷性C.确定性,有穷性和稳定性D.易读性,稳定性和安全性7.数据在计算机内有链式和顺序两种存储方式,在存储空间使用的灵活性上,链式存储比顺序存储要(7.B)。A.低B.高C.相同D.不好说8.数据结构作为一门独立的课程出现是在(8.D)年。A.1946B.1953C.1964D.19689.数据结构只是研究数据的逻辑结构和物理结构,这种观点(9.B)。A.正确B.错误C.前半句对,后半句错D.前半句错,后半句对10.计算机内部数据处理的基本单位是(10.B)。A.数据B.数据元素C.数据项D.数据库二、填空题1.数据结构按逻辑结构可分为两大类,分别是______________和_________________。1.线性结构,非线性结构2.数据的逻辑结构有四种基本形态,分别是________________、__________________、__________________和__________________。2.集合,线性,树,图3.线性结构反映结点间的逻辑关系是__________________的,非线性结构反映结点间的逻辑关系是__________________的。3.一对一,一对多或多对多4.一个算法的效率可分为__________________效率和__________________效率。4.时间,空间5.在树型结构中,树根结点没有__________________结点,其余每个结点的有且只有__________________个前趋驱结点;叶子结点没有__________________结点;其余每个结点的后续结点可以__________________。5.前趋,一,后继,多 6.在图型结构中,每个结点的前趋结点数和后续结点数可以__________________。6.有多个7.线性结构中元素之间存在__________________关系;树型结构中元素之间存在__________________关系;图型结构中元素之间存在__________________关系。7.一对一,一对多,多对多8.下面程序段的时间复杂度是__________________。8.O()for(i=0;ifor(j=0;jA[i][j]=0;9.下面程序段的时间复杂度是__________________。9.O()i=s=0;while(s{i++;s+=i;}10.下面程序段的时间复杂度是__________________。10.O()s=0;for(i=0;ifor(j=0;js+=B[i][j];sum=s;11.下面程序段的时间复杂度是__________________。11.O(logn)i=1;while(i<=n)i=i*3;12.衡量算法正确性的标准通常是__________________________。12.程序对于精心设计的典型合法数据输入能得出符合要求的结果。13.算法时间复杂度的分析通常有两种方法,即___________和___________的方法,通常我们对算法求时间复杂度时,采用后一种方法。13.事后统计,事前估计三、求下列程序段的时间复杂度。1.x=0;for(i=1;ifor(j=i+1;j<=n;j++)x++;1.O()2.x=0;for(i=1;ifor(j=1;j<=n-i;j++)x++;2.O()3.inti,j,k;for(i=0;ifor(j=0;j<=n;j++){c[i][j]=0;for(k=0;kc[i][j]=a[i][k]*b[k][j]}3.O(n)4.i=n-1;while((i>=0)&&A[i]!=k))j--;return(i);4.O(n)5.fact(n){if(n<=1)return(1);elsereturn(n*fact(n-1));}5.O(n)第2章线性表【例2-1】试编写出将两个顺序存储的有序表A和B合成一个有序表C的算法。解:假设A、B和C的类型为下述SqList类型:#definemaxlen1000typedefintelemtypetypedefstruct{elemtypeelem[maxlen];intlen;}SqList;设A和B的数据元素均为整数且为升序排列,设A的长度为m,B的长度为n,则合并后C的长度为m+n。合并时进行A、B元素的比较,将较小的链入C中,算法描述如下:intmerge(SqList*A,SqList*B,SqList*C)//将两个有序表A和B合成一个有序表C{intm,n,i,j,k;m=(*A).len;n=(*B).len;if(m+n>maxlen-1){printf("overflow");exit(0);}i=0;j=0;//i和j分别作为扫描顺序表A和B的指针k=0;//k指示顺序表C中当前位置while((i<=m)&&(j<=n))if((*A).elem[i]<=(*B).elem[j]){(*C).elem[k]=(*A)elem[i];i++;k++;}else{(*C).elem[k]=(*B)elem[j];j++;k++;}while(i<=m)//表B已结束,表A没有结束,链入表A的剩余部分{(*C).elem[k]=(*A).elem[i];i++;k++;}while(j<=m)//表A已结束,表B没有结束,链入表B的剩余部分{(*C).elem[k]=(*B).elem[j];i++;k++;}return(1);}【例2-2】写一算法实现单链表的逆置。解:假设单链表的表头指针用head表示,其类型为下面定义的LinkList,并且单链表不带头结点。逆置后原来的最后一个结点成为第一个结点,于是从第一个结点开始逐个修改每个结点的指针域进行逆置,且刚被逆置的结点总是新链表的第一个结点,故令head指向它(如图2-1所示)。typedefstructNode{elemtypedata;structNode*next;}LinkList; 具体算法描述如下:voidcontray(LinkList*head){//将head单链表中所有结点按相反次序链接LinkList*p,*q;p=head;//p指向未被逆序的第一个结点,初始时指向原表头结点head=NULL;while(p!=NULL){q=p;//q指向将被逆序链接的结点p=p->next;q->next=head;head=q;}}【例2-3】假设有一个循环链表的长度大于1,且表中既无头结点也无头指针,已知p为指向链表中某结点的指针,设计在链表中删除p所指结点的前趋结点的算法。解:可引入一个指针q,当q->next=p时,说明此时q所指的结点为p所指结点的前趋结点,从而可得算法如下:voiddelete(LinkList*p){//在链表中删除p所指结点的前趋结点LinkList*q,*t;q=p;while(q->next->next!=p)//q->next不是p的前趋结点q=q->next;t=q->next;//t指向要删除结点q->next=p;//删除t结点free(t);}【例2-4】试设计实现删除单链表中值相同的多余结点的算法。解:该例可以这样考虑,先取开始结点的值,将它与其后的所有结点值一一比
{i++;②
s+=i;③
}
语句①为赋值语句,其执行次数为1次,所以其时间复杂度为O
(1)。
语句②和语句③构成while循环语句的循环体,它们的执行次数由循环控制条件中s与n的值确定。
假定循环重复执行x次后结束,则语句②和语句③各重复执行了x次。
其时间复杂度按线性累加规则为O(x)。
此时s与n满足关系式:
s≥n,而s=1+2+3+…+x。
所以有:
1+2+3+…+x≥n,可以推出:
x=
x与n之间满足x=f(
),所以循环体的时间复杂度为O(
),语句①与循环体由线性累加规则得到该程序段的时间复杂度为O(
)。
【例1-3】分析以下程序段的时间复杂度。
i=1;①
while(i<=n)
i=2*i;②
其中语句①的执行次数是1,设语句②的执行次数为f(n),则有:
。
得:
T(n)=O(
)
【例1-4】有如下递归函数fact(n),分析其时间复杂度。
fact(intn)
{if(n<=1)
return
(1); ①
else
return(n*fact(n-1)); ②
设fact(n)的运行时间函数是T(n)。
该函数中语句①的运行时间是O
(1),语句②的运行时间是T(n-1)+O
(1),其中O
(1)为常量运行时间。
由此可得fact(n)的时间复杂度为O(n)。
习题1
一、单项选择题
1.数据结构是指(1.A)。
A.数据元素的组织形式B.数据类型
C.数据存储结构D.数据定义
2.数据在计算机存储器内表示时,物理地址与逻辑地址不相同的,称之为(2.C)。
A.存储结构B.逻辑结构
C.链式存储结构D.顺序存储结构
3.树形结构是数据元素之间存在一种(3.D)。
A.一对一关系B.多对多关系
C.多对一关系D.一对多关系
4.设语句x++的时间是单位时间,则以下语句的时间复杂度为(4.B)。
for(i=1;i<=n;i++)
for(j=i;j<=n;j++)
x++;
A.O
(1)B.O(
)C.O(n)D.O(
5.算法分析的目的是(5.C、),算法分析的两个主要方面是(A)。
(1)A.找出数据结构的合理性B.研究算法中的输入和输出关系
C.分析算法的效率以求改进D.分析算法的易懂性和文档性
(2)A.空间复杂度和时间复杂度B.正确性和简明性
C.可读性和文档性D.数据复杂性和程序复杂性
6.计算机算法指的是(6.C、),它具备输入,输出和(B)等五个特性。
(1)A.计算方法B.排序方法
C.解决问题的有限运算序列D.调度方法
(2)A.可行性,可移植性和可扩充性B.可行性,确定性和有穷性
C.确定性,有穷性和稳定性D.易读性,稳定性和安全性
7.数据在计算机内有链式和顺序两种存储方式,在存储空间使用的灵活性上,链式存储比顺序存储要(7.B)。
A.低B.高C.相同D.不好说
8.数据结构作为一门独立的课程出现是在(8.D)年。
A.1946B.1953C.1964D.1968
9.数据结构只是研究数据的逻辑结构和物理结构,这种观点(9.B)。
A.正确B.错误
C.前半句对,后半句错D.前半句错,后半句对
10.计算机内部数据处理的基本单位是(10.B)。
A.数据B.数据元素C.数据项D.数据库
二、填空题
1.数据结构按逻辑结构可分为两大类,分别是______________和_________________。
1.线性结构,非线性结构
2.数据的逻辑结构有四种基本形态,分别是________________、__________________、__________________和__________________。
2.集合,线性,树,图
3.线性结构反映结点间的逻辑关系是__________________的,非线性结构反映结点间的逻辑关系是__________________的。
3.一对一,一对多或多对多
4.一个算法的效率可分为__________________效率和__________________效率。
4.时间,空间
5.在树型结构中,树根结点没有__________________结点,其余每个结点的有且只有__________________个前趋驱结点;叶子结点没有__________________结点;其余每个结点的后续结点可以__________________。
5.前趋,一,后继,多
6.在图型结构中,每个结点的前趋结点数和后续结点数可以__________________。
6.有多个
7.线性结构中元素之间存在__________________关系;树型结构中元素之间存在__________________关系;图型结构中元素之间存在__________________关系。
7.一对一,一对多,多对多
8.下面程序段的时间复杂度是__________________。
8.O(
for(i=0;ifor(j=0;jA[i][j]=0;9.下面程序段的时间复杂度是__________________。9.O()i=s=0;while(s{i++;s+=i;}10.下面程序段的时间复杂度是__________________。10.O()s=0;for(i=0;ifor(j=0;js+=B[i][j];sum=s;11.下面程序段的时间复杂度是__________________。11.O(logn)i=1;while(i<=n)i=i*3;12.衡量算法正确性的标准通常是__________________________。12.程序对于精心设计的典型合法数据输入能得出符合要求的结果。13.算法时间复杂度的分析通常有两种方法,即___________和___________的方法,通常我们对算法求时间复杂度时,采用后一种方法。13.事后统计,事前估计三、求下列程序段的时间复杂度。1.x=0;for(i=1;ifor(j=i+1;j<=n;j++)x++;1.O()2.x=0;for(i=1;ifor(j=1;j<=n-i;j++)x++;2.O()3.inti,j,k;for(i=0;ifor(j=0;j<=n;j++){c[i][j]=0;for(k=0;kc[i][j]=a[i][k]*b[k][j]}3.O(n)4.i=n-1;while((i>=0)&&A[i]!=k))j--;return(i);4.O(n)5.fact(n){if(n<=1)return(1);elsereturn(n*fact(n-1));}5.O(n)第2章线性表【例2-1】试编写出将两个顺序存储的有序表A和B合成一个有序表C的算法。解:假设A、B和C的类型为下述SqList类型:#definemaxlen1000typedefintelemtypetypedefstruct{elemtypeelem[maxlen];intlen;}SqList;设A和B的数据元素均为整数且为升序排列,设A的长度为m,B的长度为n,则合并后C的长度为m+n。合并时进行A、B元素的比较,将较小的链入C中,算法描述如下:intmerge(SqList*A,SqList*B,SqList*C)//将两个有序表A和B合成一个有序表C{intm,n,i,j,k;m=(*A).len;n=(*B).len;if(m+n>maxlen-1){printf("overflow");exit(0);}i=0;j=0;//i和j分别作为扫描顺序表A和B的指针k=0;//k指示顺序表C中当前位置while((i<=m)&&(j<=n))if((*A).elem[i]<=(*B).elem[j]){(*C).elem[k]=(*A)elem[i];i++;k++;}else{(*C).elem[k]=(*B)elem[j];j++;k++;}while(i<=m)//表B已结束,表A没有结束,链入表A的剩余部分{(*C).elem[k]=(*A).elem[i];i++;k++;}while(j<=m)//表A已结束,表B没有结束,链入表B的剩余部分{(*C).elem[k]=(*B).elem[j];i++;k++;}return(1);}【例2-2】写一算法实现单链表的逆置。解:假设单链表的表头指针用head表示,其类型为下面定义的LinkList,并且单链表不带头结点。逆置后原来的最后一个结点成为第一个结点,于是从第一个结点开始逐个修改每个结点的指针域进行逆置,且刚被逆置的结点总是新链表的第一个结点,故令head指向它(如图2-1所示)。typedefstructNode{elemtypedata;structNode*next;}LinkList; 具体算法描述如下:voidcontray(LinkList*head){//将head单链表中所有结点按相反次序链接LinkList*p,*q;p=head;//p指向未被逆序的第一个结点,初始时指向原表头结点head=NULL;while(p!=NULL){q=p;//q指向将被逆序链接的结点p=p->next;q->next=head;head=q;}}【例2-3】假设有一个循环链表的长度大于1,且表中既无头结点也无头指针,已知p为指向链表中某结点的指针,设计在链表中删除p所指结点的前趋结点的算法。解:可引入一个指针q,当q->next=p时,说明此时q所指的结点为p所指结点的前趋结点,从而可得算法如下:voiddelete(LinkList*p){//在链表中删除p所指结点的前趋结点LinkList*q,*t;q=p;while(q->next->next!=p)//q->next不是p的前趋结点q=q->next;t=q->next;//t指向要删除结点q->next=p;//删除t结点free(t);}【例2-4】试设计实现删除单链表中值相同的多余结点的算法。解:该例可以这样考虑,先取开始结点的值,将它与其后的所有结点值一一比
for(j=0;jA[i][j]=0;9.下面程序段的时间复杂度是__________________。9.O()i=s=0;while(s{i++;s+=i;}10.下面程序段的时间复杂度是__________________。10.O()s=0;for(i=0;ifor(j=0;js+=B[i][j];sum=s;11.下面程序段的时间复杂度是__________________。11.O(logn)i=1;while(i<=n)i=i*3;12.衡量算法正确性的标准通常是__________________________。12.程序对于精心设计的典型合法数据输入能得出符合要求的结果。13.算法时间复杂度的分析通常有两种方法,即___________和___________的方法,通常我们对算法求时间复杂度时,采用后一种方法。13.事后统计,事前估计三、求下列程序段的时间复杂度。1.x=0;for(i=1;ifor(j=i+1;j<=n;j++)x++;1.O()2.x=0;for(i=1;ifor(j=1;j<=n-i;j++)x++;2.O()3.inti,j,k;for(i=0;ifor(j=0;j<=n;j++){c[i][j]=0;for(k=0;kc[i][j]=a[i][k]*b[k][j]}3.O(n)4.i=n-1;while((i>=0)&&A[i]!=k))j--;return(i);4.O(n)5.fact(n){if(n<=1)return(1);elsereturn(n*fact(n-1));}5.O(n)第2章线性表【例2-1】试编写出将两个顺序存储的有序表A和B合成一个有序表C的算法。解:假设A、B和C的类型为下述SqList类型:#definemaxlen1000typedefintelemtypetypedefstruct{elemtypeelem[maxlen];intlen;}SqList;设A和B的数据元素均为整数且为升序排列,设A的长度为m,B的长度为n,则合并后C的长度为m+n。合并时进行A、B元素的比较,将较小的链入C中,算法描述如下:intmerge(SqList*A,SqList*B,SqList*C)//将两个有序表A和B合成一个有序表C{intm,n,i,j,k;m=(*A).len;n=(*B).len;if(m+n>maxlen-1){printf("overflow");exit(0);}i=0;j=0;//i和j分别作为扫描顺序表A和B的指针k=0;//k指示顺序表C中当前位置while((i<=m)&&(j<=n))if((*A).elem[i]<=(*B).elem[j]){(*C).elem[k]=(*A)elem[i];i++;k++;}else{(*C).elem[k]=(*B)elem[j];j++;k++;}while(i<=m)//表B已结束,表A没有结束,链入表A的剩余部分{(*C).elem[k]=(*A).elem[i];i++;k++;}while(j<=m)//表A已结束,表B没有结束,链入表B的剩余部分{(*C).elem[k]=(*B).elem[j];i++;k++;}return(1);}【例2-2】写一算法实现单链表的逆置。解:假设单链表的表头指针用head表示,其类型为下面定义的LinkList,并且单链表不带头结点。逆置后原来的最后一个结点成为第一个结点,于是从第一个结点开始逐个修改每个结点的指针域进行逆置,且刚被逆置的结点总是新链表的第一个结点,故令head指向它(如图2-1所示)。typedefstructNode{elemtypedata;structNode*next;}LinkList; 具体算法描述如下:voidcontray(LinkList*head){//将head单链表中所有结点按相反次序链接LinkList*p,*q;p=head;//p指向未被逆序的第一个结点,初始时指向原表头结点head=NULL;while(p!=NULL){q=p;//q指向将被逆序链接的结点p=p->next;q->next=head;head=q;}}【例2-3】假设有一个循环链表的长度大于1,且表中既无头结点也无头指针,已知p为指向链表中某结点的指针,设计在链表中删除p所指结点的前趋结点的算法。解:可引入一个指针q,当q->next=p时,说明此时q所指的结点为p所指结点的前趋结点,从而可得算法如下:voiddelete(LinkList*p){//在链表中删除p所指结点的前趋结点LinkList*q,*t;q=p;while(q->next->next!=p)//q->next不是p的前趋结点q=q->next;t=q->next;//t指向要删除结点q->next=p;//删除t结点free(t);}【例2-4】试设计实现删除单链表中值相同的多余结点的算法。解:该例可以这样考虑,先取开始结点的值,将它与其后的所有结点值一一比
9.下面程序段的时间复杂度是__________________。
9.O(
i=s=0;
while(s{i++;s+=i;}10.下面程序段的时间复杂度是__________________。10.O()s=0;for(i=0;ifor(j=0;js+=B[i][j];sum=s;11.下面程序段的时间复杂度是__________________。11.O(logn)i=1;while(i<=n)i=i*3;12.衡量算法正确性的标准通常是__________________________。12.程序对于精心设计的典型合法数据输入能得出符合要求的结果。13.算法时间复杂度的分析通常有两种方法,即___________和___________的方法,通常我们对算法求时间复杂度时,采用后一种方法。13.事后统计,事前估计三、求下列程序段的时间复杂度。1.x=0;for(i=1;ifor(j=i+1;j<=n;j++)x++;1.O()2.x=0;for(i=1;ifor(j=1;j<=n-i;j++)x++;2.O()3.inti,j,k;for(i=0;ifor(j=0;j<=n;j++){c[i][j]=0;for(k=0;kc[i][j]=a[i][k]*b[k][j]}3.O(n)4.i=n-1;while((i>=0)&&A[i]!=k))j--;return(i);4.O(n)5.fact(n){if(n<=1)return(1);elsereturn(n*fact(n-1));}5.O(n)第2章线性表【例2-1】试编写出将两个顺序存储的有序表A和B合成一个有序表C的算法。解:假设A、B和C的类型为下述SqList类型:#definemaxlen1000typedefintelemtypetypedefstruct{elemtypeelem[maxlen];intlen;}SqList;设A和B的数据元素均为整数且为升序排列,设A的长度为m,B的长度为n,则合并后C的长度为m+n。合并时进行A、B元素的比较,将较小的链入C中,算法描述如下:intmerge(SqList*A,SqList*B,SqList*C)//将两个有序表A和B合成一个有序表C{intm,n,i,j,k;m=(*A).len;n=(*B).len;if(m+n>maxlen-1){printf("overflow");exit(0);}i=0;j=0;//i和j分别作为扫描顺序表A和B的指针k=0;//k指示顺序表C中当前位置while((i<=m)&&(j<=n))if((*A).elem[i]<=(*B).elem[j]){(*C).elem[k]=(*A)elem[i];i++;k++;}else{(*C).elem[k]=(*B)elem[j];j++;k++;}while(i<=m)//表B已结束,表A没有结束,链入表A的剩余部分{(*C).elem[k]=(*A).elem[i];i++;k++;}while(j<=m)//表A已结束,表B没有结束,链入表B的剩余部分{(*C).elem[k]=(*B).elem[j];i++;k++;}return(1);}【例2-2】写一算法实现单链表的逆置。解:假设单链表的表头指针用head表示,其类型为下面定义的LinkList,并且单链表不带头结点。逆置后原来的最后一个结点成为第一个结点,于是从第一个结点开始逐个修改每个结点的指针域进行逆置,且刚被逆置的结点总是新链表的第一个结点,故令head指向它(如图2-1所示)。typedefstructNode{elemtypedata;structNode*next;}LinkList; 具体算法描述如下:voidcontray(LinkList*head){//将head单链表中所有结点按相反次序链接LinkList*p,*q;p=head;//p指向未被逆序的第一个结点,初始时指向原表头结点head=NULL;while(p!=NULL){q=p;//q指向将被逆序链接的结点p=p->next;q->next=head;head=q;}}【例2-3】假设有一个循环链表的长度大于1,且表中既无头结点也无头指针,已知p为指向链表中某结点的指针,设计在链表中删除p所指结点的前趋结点的算法。解:可引入一个指针q,当q->next=p时,说明此时q所指的结点为p所指结点的前趋结点,从而可得算法如下:voiddelete(LinkList*p){//在链表中删除p所指结点的前趋结点LinkList*q,*t;q=p;while(q->next->next!=p)//q->next不是p的前趋结点q=q->next;t=q->next;//t指向要删除结点q->next=p;//删除t结点free(t);}【例2-4】试设计实现删除单链表中值相同的多余结点的算法。解:该例可以这样考虑,先取开始结点的值,将它与其后的所有结点值一一比
{i++;
s+=i;
10.下面程序段的时间复杂度是__________________。
10.O(
s=0;
for(i=0;ifor(j=0;js+=B[i][j];sum=s;11.下面程序段的时间复杂度是__________________。11.O(logn)i=1;while(i<=n)i=i*3;12.衡量算法正确性的标准通常是__________________________。12.程序对于精心设计的典型合法数据输入能得出符合要求的结果。13.算法时间复杂度的分析通常有两种方法,即___________和___________的方法,通常我们对算法求时间复杂度时,采用后一种方法。13.事后统计,事前估计三、求下列程序段的时间复杂度。1.x=0;for(i=1;ifor(j=i+1;j<=n;j++)x++;1.O()2.x=0;for(i=1;ifor(j=1;j<=n-i;j++)x++;2.O()3.inti,j,k;for(i=0;ifor(j=0;j<=n;j++){c[i][j]=0;for(k=0;kc[i][j]=a[i][k]*b[k][j]}3.O(n)4.i=n-1;while((i>=0)&&A[i]!=k))j--;return(i);4.O(n)5.fact(n){if(n<=1)return(1);elsereturn(n*fact(n-1));}5.O(n)第2章线性表【例2-1】试编写出将两个顺序存储的有序表A和B合成一个有序表C的算法。解:假设A、B和C的类型为下述SqList类型:#definemaxlen1000typedefintelemtypetypedefstruct{elemtypeelem[maxlen];intlen;}SqList;设A和B的数据元素均为整数且为升序排列,设A的长度为m,B的长度为n,则合并后C的长度为m+n。合并时进行A、B元素的比较,将较小的链入C中,算法描述如下:intmerge(SqList*A,SqList*B,SqList*C)//将两个有序表A和B合成一个有序表C{intm,n,i,j,k;m=(*A).len;n=(*B).len;if(m+n>maxlen-1){printf("overflow");exit(0);}i=0;j=0;//i和j分别作为扫描顺序表A和B的指针k=0;//k指示顺序表C中当前位置while((i<=m)&&(j<=n))if((*A).elem[i]<=(*B).elem[j]){(*C).elem[k]=(*A)elem[i];i++;k++;}else{(*C).elem[k]=(*B)elem[j];j++;k++;}while(i<=m)//表B已结束,表A没有结束,链入表A的剩余部分{(*C).elem[k]=(*A).elem[i];i++;k++;}while(j<=m)//表A已结束,表B没有结束,链入表B的剩余部分{(*C).elem[k]=(*B).elem[j];i++;k++;}return(1);}【例2-2】写一算法实现单链表的逆置。解:假设单链表的表头指针用head表示,其类型为下面定义的LinkList,并且单链表不带头结点。逆置后原来的最后一个结点成为第一个结点,于是从第一个结点开始逐个修改每个结点的指针域进行逆置,且刚被逆置的结点总是新链表的第一个结点,故令head指向它(如图2-1所示)。typedefstructNode{elemtypedata;structNode*next;}LinkList; 具体算法描述如下:voidcontray(LinkList*head){//将head单链表中所有结点按相反次序链接LinkList*p,*q;p=head;//p指向未被逆序的第一个结点,初始时指向原表头结点head=NULL;while(p!=NULL){q=p;//q指向将被逆序链接的结点p=p->next;q->next=head;head=q;}}【例2-3】假设有一个循环链表的长度大于1,且表中既无头结点也无头指针,已知p为指向链表中某结点的指针,设计在链表中删除p所指结点的前趋结点的算法。解:可引入一个指针q,当q->next=p时,说明此时q所指的结点为p所指结点的前趋结点,从而可得算法如下:voiddelete(LinkList*p){//在链表中删除p所指结点的前趋结点LinkList*q,*t;q=p;while(q->next->next!=p)//q->next不是p的前趋结点q=q->next;t=q->next;//t指向要删除结点q->next=p;//删除t结点free(t);}【例2-4】试设计实现删除单链表中值相同的多余结点的算法。解:该例可以这样考虑,先取开始结点的值,将它与其后的所有结点值一一比
for(j=0;js+=B[i][j];sum=s;11.下面程序段的时间复杂度是__________________。11.O(logn)i=1;while(i<=n)i=i*3;12.衡量算法正确性的标准通常是__________________________。12.程序对于精心设计的典型合法数据输入能得出符合要求的结果。13.算法时间复杂度的分析通常有两种方法,即___________和___________的方法,通常我们对算法求时间复杂度时,采用后一种方法。13.事后统计,事前估计三、求下列程序段的时间复杂度。1.x=0;for(i=1;ifor(j=i+1;j<=n;j++)x++;1.O()2.x=0;for(i=1;ifor(j=1;j<=n-i;j++)x++;2.O()3.inti,j,k;for(i=0;ifor(j=0;j<=n;j++){c[i][j]=0;for(k=0;kc[i][j]=a[i][k]*b[k][j]}3.O(n)4.i=n-1;while((i>=0)&&A[i]!=k))j--;return(i);4.O(n)5.fact(n){if(n<=1)return(1);elsereturn(n*fact(n-1));}5.O(n)第2章线性表【例2-1】试编写出将两个顺序存储的有序表A和B合成一个有序表C的算法。解:假设A、B和C的类型为下述SqList类型:#definemaxlen1000typedefintelemtypetypedefstruct{elemtypeelem[maxlen];intlen;}SqList;设A和B的数据元素均为整数且为升序排列,设A的长度为m,B的长度为n,则合并后C的长度为m+n。合并时进行A、B元素的比较,将较小的链入C中,算法描述如下:intmerge(SqList*A,SqList*B,SqList*C)//将两个有序表A和B合成一个有序表C{intm,n,i,j,k;m=(*A).len;n=(*B).len;if(m+n>maxlen-1){printf("overflow");exit(0);}i=0;j=0;//i和j分别作为扫描顺序表A和B的指针k=0;//k指示顺序表C中当前位置while((i<=m)&&(j<=n))if((*A).elem[i]<=(*B).elem[j]){(*C).elem[k]=(*A)elem[i];i++;k++;}else{(*C).elem[k]=(*B)elem[j];j++;k++;}while(i<=m)//表B已结束,表A没有结束,链入表A的剩余部分{(*C).elem[k]=(*A).elem[i];i++;k++;}while(j<=m)//表A已结束,表B没有结束,链入表B的剩余部分{(*C).elem[k]=(*B).elem[j];i++;k++;}return(1);}【例2-2】写一算法实现单链表的逆置。解:假设单链表的表头指针用head表示,其类型为下面定义的LinkList,并且单链表不带头结点。逆置后原来的最后一个结点成为第一个结点,于是从第一个结点开始逐个修改每个结点的指针域进行逆置,且刚被逆置的结点总是新链表的第一个结点,故令head指向它(如图2-1所示)。typedefstructNode{elemtypedata;structNode*next;}LinkList; 具体算法描述如下:voidcontray(LinkList*head){//将head单链表中所有结点按相反次序链接LinkList*p,*q;p=head;//p指向未被逆序的第一个结点,初始时指向原表头结点head=NULL;while(p!=NULL){q=p;//q指向将被逆序链接的结点p=p->next;q->next=head;head=q;}}【例2-3】假设有一个循环链表的长度大于1,且表中既无头结点也无头指针,已知p为指向链表中某结点的指针,设计在链表中删除p所指结点的前趋结点的算法。解:可引入一个指针q,当q->next=p时,说明此时q所指的结点为p所指结点的前趋结点,从而可得算法如下:voiddelete(LinkList*p){//在链表中删除p所指结点的前趋结点LinkList*q,*t;q=p;while(q->next->next!=p)//q->next不是p的前趋结点q=q->next;t=q->next;//t指向要删除结点q->next=p;//删除t结点free(t);}【例2-4】试设计实现删除单链表中值相同的多余结点的算法。解:该例可以这样考虑,先取开始结点的值,将它与其后的所有结点值一一比
s+=B[i][j];
sum=s;
11.下面程序段的时间复杂度是__________________。
11.O(log
n)
i=1;
i=i*3;
12.衡量算法正确性的标准通常是__________________________。
12.程序对于精心设计的典型合法数据输入能得出符合要求的结果。
13.算法时间复杂度的分析通常有两种方法,即___________和___________的方法,通常我们对算法求时间复杂度时,采用后一种方法。
13.事后统计,事前估计
三、求下列程序段的时间复杂度。
1.x=0;
for(i=1;ifor(j=i+1;j<=n;j++)x++;1.O()2.x=0;for(i=1;ifor(j=1;j<=n-i;j++)x++;2.O()3.inti,j,k;for(i=0;ifor(j=0;j<=n;j++){c[i][j]=0;for(k=0;kc[i][j]=a[i][k]*b[k][j]}3.O(n)4.i=n-1;while((i>=0)&&A[i]!=k))j--;return(i);4.O(n)5.fact(n){if(n<=1)return(1);elsereturn(n*fact(n-1));}5.O(n)第2章线性表【例2-1】试编写出将两个顺序存储的有序表A和B合成一个有序表C的算法。解:假设A、B和C的类型为下述SqList类型:#definemaxlen1000typedefintelemtypetypedefstruct{elemtypeelem[maxlen];intlen;}SqList;设A和B的数据元素均为整数且为升序排列,设A的长度为m,B的长度为n,则合并后C的长度为m+n。合并时进行A、B元素的比较,将较小的链入C中,算法描述如下:intmerge(SqList*A,SqList*B,SqList*C)//将两个有序表A和B合成一个有序表C{intm,n,i,j,k;m=(*A).len;n=(*B).len;if(m+n>maxlen-1){printf("overflow");exit(0);}i=0;j=0;//i和j分别作为扫描顺序表A和B的指针k=0;//k指示顺序表C中当前位置while((i<=m)&&(j<=n))if((*A).elem[i]<=(*B).elem[j]){(*C).elem[k]=(*A)elem[i];i++;k++;}else{(*C).elem[k]=(*B)elem[j];j++;k++;}while(i<=m)//表B已结束,表A没有结束,链入表A的剩余部分{(*C).elem[k]=(*A).elem[i];i++;k++;}while(j<=m)//表A已结束,表B没有结束,链入表B的剩余部分{(*C).elem[k]=(*B).elem[j];i++;k++;}return(1);}【例2-2】写一算法实现单链表的逆置。解:假设单链表的表头指针用head表示,其类型为下面定义的LinkList,并且单链表不带头结点。逆置后原来的最后一个结点成为第一个结点,于是从第一个结点开始逐个修改每个结点的指针域进行逆置,且刚被逆置的结点总是新链表的第一个结点,故令head指向它(如图2-1所示)。typedefstructNode{elemtypedata;structNode*next;}LinkList; 具体算法描述如下:voidcontray(LinkList*head){//将head单链表中所有结点按相反次序链接LinkList*p,*q;p=head;//p指向未被逆序的第一个结点,初始时指向原表头结点head=NULL;while(p!=NULL){q=p;//q指向将被逆序链接的结点p=p->next;q->next=head;head=q;}}【例2-3】假设有一个循环链表的长度大于1,且表中既无头结点也无头指针,已知p为指向链表中某结点的指针,设计在链表中删除p所指结点的前趋结点的算法。解:可引入一个指针q,当q->next=p时,说明此时q所指的结点为p所指结点的前趋结点,从而可得算法如下:voiddelete(LinkList*p){//在链表中删除p所指结点的前趋结点LinkList*q,*t;q=p;while(q->next->next!=p)//q->next不是p的前趋结点q=q->next;t=q->next;//t指向要删除结点q->next=p;//删除t结点free(t);}【例2-4】试设计实现删除单链表中值相同的多余结点的算法。解:该例可以这样考虑,先取开始结点的值,将它与其后的所有结点值一一比
for(j=i+1;j<=n;j++)
1.O(
2.x=0;
for(i=1;ifor(j=1;j<=n-i;j++)x++;2.O()3.inti,j,k;for(i=0;ifor(j=0;j<=n;j++){c[i][j]=0;for(k=0;kc[i][j]=a[i][k]*b[k][j]}3.O(n)4.i=n-1;while((i>=0)&&A[i]!=k))j--;return(i);4.O(n)5.fact(n){if(n<=1)return(1);elsereturn(n*fact(n-1));}5.O(n)第2章线性表【例2-1】试编写出将两个顺序存储的有序表A和B合成一个有序表C的算法。解:假设A、B和C的类型为下述SqList类型:#definemaxlen1000typedefintelemtypetypedefstruct{elemtypeelem[maxlen];intlen;}SqList;设A和B的数据元素均为整数且为升序排列,设A的长度为m,B的长度为n,则合并后C的长度为m+n。合并时进行A、B元素的比较,将较小的链入C中,算法描述如下:intmerge(SqList*A,SqList*B,SqList*C)//将两个有序表A和B合成一个有序表C{intm,n,i,j,k;m=(*A).len;n=(*B).len;if(m+n>maxlen-1){printf("overflow");exit(0);}i=0;j=0;//i和j分别作为扫描顺序表A和B的指针k=0;//k指示顺序表C中当前位置while((i<=m)&&(j<=n))if((*A).elem[i]<=(*B).elem[j]){(*C).elem[k]=(*A)elem[i];i++;k++;}else{(*C).elem[k]=(*B)elem[j];j++;k++;}while(i<=m)//表B已结束,表A没有结束,链入表A的剩余部分{(*C).elem[k]=(*A).elem[i];i++;k++;}while(j<=m)//表A已结束,表B没有结束,链入表B的剩余部分{(*C).elem[k]=(*B).elem[j];i++;k++;}return(1);}【例2-2】写一算法实现单链表的逆置。解:假设单链表的表头指针用head表示,其类型为下面定义的LinkList,并且单链表不带头结点。逆置后原来的最后一个结点成为第一个结点,于是从第一个结点开始逐个修改每个结点的指针域进行逆置,且刚被逆置的结点总是新链表的第一个结点,故令head指向它(如图2-1所示)。typedefstructNode{elemtypedata;structNode*next;}LinkList; 具体算法描述如下:voidcontray(LinkList*head){//将head单链表中所有结点按相反次序链接LinkList*p,*q;p=head;//p指向未被逆序的第一个结点,初始时指向原表头结点head=NULL;while(p!=NULL){q=p;//q指向将被逆序链接的结点p=p->next;q->next=head;head=q;}}【例2-3】假设有一个循环链表的长度大于1,且表中既无头结点也无头指针,已知p为指向链表中某结点的指针,设计在链表中删除p所指结点的前趋结点的算法。解:可引入一个指针q,当q->next=p时,说明此时q所指的结点为p所指结点的前趋结点,从而可得算法如下:voiddelete(LinkList*p){//在链表中删除p所指结点的前趋结点LinkList*q,*t;q=p;while(q->next->next!=p)//q->next不是p的前趋结点q=q->next;t=q->next;//t指向要删除结点q->next=p;//删除t结点free(t);}【例2-4】试设计实现删除单链表中值相同的多余结点的算法。解:该例可以这样考虑,先取开始结点的值,将它与其后的所有结点值一一比
for(j=1;j<=n-i;j++)
2.O(
3.inti,j,k;
for(i=0;ifor(j=0;j<=n;j++){c[i][j]=0;for(k=0;kc[i][j]=a[i][k]*b[k][j]}3.O(n)4.i=n-1;while((i>=0)&&A[i]!=k))j--;return(i);4.O(n)5.fact(n){if(n<=1)return(1);elsereturn(n*fact(n-1));}5.O(n)第2章线性表【例2-1】试编写出将两个顺序存储的有序表A和B合成一个有序表C的算法。解:假设A、B和C的类型为下述SqList类型:#definemaxlen1000typedefintelemtypetypedefstruct{elemtypeelem[maxlen];intlen;}SqList;设A和B的数据元素均为整数且为升序排列,设A的长度为m,B的长度为n,则合并后C的长度为m+n。合并时进行A、B元素的比较,将较小的链入C中,算法描述如下:intmerge(SqList*A,SqList*B,SqList*C)//将两个有序表A和B合成一个有序表C{intm,n,i,j,k;m=(*A).len;n=(*B).len;if(m+n>maxlen-1){printf("overflow");exit(0);}i=0;j=0;//i和j分别作为扫描顺序表A和B的指针k=0;//k指示顺序表C中当前位置while((i<=m)&&(j<=n))if((*A).elem[i]<=(*B).elem[j]){(*C).elem[k]=(*A)elem[i];i++;k++;}else{(*C).elem[k]=(*B)elem[j];j++;k++;}while(i<=m)//表B已结束,表A没有结束,链入表A的剩余部分{(*C).elem[k]=(*A).elem[i];i++;k++;}while(j<=m)//表A已结束,表B没有结束,链入表B的剩余部分{(*C).elem[k]=(*B).elem[j];i++;k++;}return(1);}【例2-2】写一算法实现单链表的逆置。解:假设单链表的表头指针用head表示,其类型为下面定义的LinkList,并且单链表不带头结点。逆置后原来的最后一个结点成为第一个结点,于是从第一个结点开始逐个修改每个结点的指针域进行逆置,且刚被逆置的结点总是新链表的第一个结点,故令head指向它(如图2-1所示)。typedefstructNode{elemtypedata;structNode*next;}LinkList; 具体算法描述如下:voidcontray(LinkList*head){//将head单链表中所有结点按相反次序链接LinkList*p,*q;p=head;//p指向未被逆序的第一个结点,初始时指向原表头结点head=NULL;while(p!=NULL){q=p;//q指向将被逆序链接的结点p=p->next;q->next=head;head=q;}}【例2-3】假设有一个循环链表的长度大于1,且表中既无头结点也无头指针,已知p为指向链表中某结点的指针,设计在链表中删除p所指结点的前趋结点的算法。解:可引入一个指针q,当q->next=p时,说明此时q所指的结点为p所指结点的前趋结点,从而可得算法如下:voiddelete(LinkList*p){//在链表中删除p所指结点的前趋结点LinkList*q,*t;q=p;while(q->next->next!=p)//q->next不是p的前趋结点q=q->next;t=q->next;//t指向要删除结点q->next=p;//删除t结点free(t);}【例2-4】试设计实现删除单链表中值相同的多余结点的算法。解:该例可以这样考虑,先取开始结点的值,将它与其后的所有结点值一一比
for(j=0;j<=n;j++)
{c[i][j]=0;
for(k=0;kc[i][j]=a[i][k]*b[k][j]}3.O(n)4.i=n-1;while((i>=0)&&A[i]!=k))j--;return(i);4.O(n)5.fact(n){if(n<=1)return(1);elsereturn(n*fact(n-1));}5.O(n)第2章线性表【例2-1】试编写出将两个顺序存储的有序表A和B合成一个有序表C的算法。解:假设A、B和C的类型为下述SqList类型:#definemaxlen1000typedefintelemtypetypedefstruct{elemtypeelem[maxlen];intlen;}SqList;设A和B的数据元素均为整数且为升序排列,设A的长度为m,B的长度为n,则合并后C的长度为m+n。合并时进行A、B元素的比较,将较小的链入C中,算法描述如下:intmerge(SqList*A,SqList*B,SqList*C)//将两个有序表A和B合成一个有序表C{intm,n,i,j,k;m=(*A).len;n=(*B).len;if(m+n>maxlen-1){printf("overflow");exit(0);}i=0;j=0;//i和j分别作为扫描顺序表A和B的指针k=0;//k指示顺序表C中当前位置while((i<=m)&&(j<=n))if((*A).elem[i]<=(*B).elem[j]){(*C).elem[k]=(*A)elem[i];i++;k++;}else{(*C).elem[k]=(*B)elem[j];j++;k++;}while(i<=m)//表B已结束,表A没有结束,链入表A的剩余部分{(*C).elem[k]=(*A).elem[i];i++;k++;}while(j<=m)//表A已结束,表B没有结束,链入表B的剩余部分{(*C).elem[k]=(*B).elem[j];i++;k++;}return(1);}【例2-2】写一算法实现单链表的逆置。解:假设单链表的表头指针用head表示,其类型为下面定义的LinkList,并且单链表不带头结点。逆置后原来的最后一个结点成为第一个结点,于是从第一个结点开始逐个修改每个结点的指针域进行逆置,且刚被逆置的结点总是新链表的第一个结点,故令head指向它(如图2-1所示)。typedefstructNode{elemtypedata;structNode*next;}LinkList; 具体算法描述如下:voidcontray(LinkList*head){//将head单链表中所有结点按相反次序链接LinkList*p,*q;p=head;//p指向未被逆序的第一个结点,初始时指向原表头结点head=NULL;while(p!=NULL){q=p;//q指向将被逆序链接的结点p=p->next;q->next=head;head=q;}}【例2-3】假设有一个循环链表的长度大于1,且表中既无头结点也无头指针,已知p为指向链表中某结点的指针,设计在链表中删除p所指结点的前趋结点的算法。解:可引入一个指针q,当q->next=p时,说明此时q所指的结点为p所指结点的前趋结点,从而可得算法如下:voiddelete(LinkList*p){//在链表中删除p所指结点的前趋结点LinkList*q,*t;q=p;while(q->next->next!=p)//q->next不是p的前趋结点q=q->next;t=q->next;//t指向要删除结点q->next=p;//删除t结点free(t);}【例2-4】试设计实现删除单链表中值相同的多余结点的算法。解:该例可以这样考虑,先取开始结点的值,将它与其后的所有结点值一一比
c[i][j]=a[i][k]*b[k][j]
3.O(n
4.i=n-1;
while((i>=0)&&A[i]!
=k))
j--;
return(i);
4.O(n)
5.fact(n)
(1);
return(n*fact(n-1));
5.O(n)
第2章线性表
【例2-1】试编写出将两个顺序存储的有序表A和B合成一个有序表C的算法。
假设A、B和C的类型为下述SqList类型:
#definemaxlen1000
typedefintelemtype
typedefstruct
{elemtypeelem[maxlen];
intlen;
}SqList;
设A和B的数据元素均为整数且为升序排列,设A的长度为m,B的长度为n,则合并后C的长度为m+n。
合并时进行A、B元素的比较,将较小的链入C中,算法描述如下:
intmerge(SqList*A,SqList*B,SqList*C)//将两个有序表A和B合成一个有序表C
{intm,n,i,j,k;
m=(*A).len;n=(*B).len;
if(m+n>maxlen-1)
{printf("overflow");
exit(0);
i=0;j=0;//i和j分别作为扫描顺序表A和B的指针
k=0;//k指示顺序表C中当前位置
while((i<=m)&&(j<=n))
if((*A).elem[i]<=(*B).elem[j])
{(*C).elem[k]=(*A)elem[i];
i++;k++;
{(*C).elem[k]=(*B)elem[j];
j++;k++;
while(i<=m)//表B已结束,表A没有结束,链入表A的剩余部分
{(*C).elem[k]=(*A).elem[i];
while(j<=m)//表A已结束,表B没有结束,链入表B的剩余部分
{(*C).elem[k]=(*B).elem[j];
【例2-2】写一算法实现单链表的逆置。
假设单链表的表头指针用head表示,其类型为下面定义的LinkList,并且单链表不带头结点。
逆置后原来的最后一个结点成为第一个结点,于是从第一个结点开始逐个修改每个结点的指针域进行逆置,且刚被逆置的结点总是新链表的第一个结点,故令head指向它(如图2-1所示)。
typedefstructNode
{elemtypedata;
structNode*next;
}LinkList;
具体算法描述如下:
voidcontray(LinkList*head)
{//将head单链表中所有结点按相反次序链接
LinkList*p,*q;
p=head;//p指向未被逆序的第一个结点,初始时指向原表头结点
head=NULL;
while(p!
=NULL)
{q=p;//q指向将被逆序链接的结点
p=p->next;
q->next=head;
head=q;
【例2-3】假设有一个循环链表的长度大于1,且表中既无头结点也无头指针,已知p为指向链表中某结点的指针,设计在链表中删除p所指结点的前趋结点的算法。
可引入一个指针q,当q->next=p时,说明此时q所指的结点为p所指结点的前趋结点,从而可得算法如下:
voiddelete(LinkList*p)
{//在链表中删除p所指结点的前趋结点
LinkList*q,*t;
q=p;
while(q->next->next!
=p)//q->next不是p的前趋结点
q=q->next;
t=q->next;//t指向要删除结点
q->next=p;//删除t结点
free(t);
}
【例2-4】试设计实现删除单链表中值相同的多余结点的算法。
该例可以这样考虑,先取开始结点的值,将它与其后的所有结点值一一比
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1