1、习题一 一、选择题 1B 2C 3B 4D 5C 6D 7A 8C 二、填空题 1数据元素 数据元素间关系 2. 数据的组织形式,即数据元素之间逻辑关系的总体 3有穷性 确定性 可行性 4算法的时间复杂度和空间复杂度 5集合 线性结构 树形结构 图状结构或网状结构 三、简述题 1解答: 四种表示方法。 顺序存储方式。数据元素顺序存放,每个存储结点只含一个元素。存储位置反映数据 元素间的逻辑关系。存储密度大,但有些操作(如插入、删除)效率较差。 链式存储方式。每个存储结点除包含数据元素信息外还包含一组(至少一个)指针。 指针反映数据元素间的逻辑关系。这种方式不要求存储空间连续,便于动态操作(如插
2、入、 删除等) ,但存储空间开销大(用于指针) ,另外不能折半查找等。 索引存储方式。除数据元素存储在一地址连续的内存空间外,尚需建立一个索引表, 索引表中索引指示存储结点的存储位置(下标)或存储区间端点(下标) ,兼有静态和动态 特性。 散列存储方式。通过散列函数和解决冲突的方法,将关键字散列在连续的有限的地址 空间内, 并将散列函数的值解释成关键字所在元素的存储地址, 这种存储方式称为散列存储。 其特点是存取速度快,只能按关键字随机存取,不能顺序存取,也不能折半存取。 2解答: 数据类型是程序设计语言中的一个概念,它是一个值的集合和操作的集合。如 C 语言 中的整型、实型、字符型等,如整数
3、的取值范围与具体机器和编译系统有关,其操作有加、 减、乘、除、求余等。实际上数据类型是厂家提供给用户的已实现了的数据结构。 “抽象数 据类型(ADT) ”指一个数学模型及定义在该模型上的一组操作。 “抽象”的意义在于数据 类型的数学抽象特性。抽象数据类型的定义仅取决于它的逻辑特性,而与其在计算机内部如 何表示和实现无关。无论其内部结构如何变化,只要它的数学特性不变就不影响它的外部使 用。抽象数据类型和数据类型实质上是一个概念。此外,抽象数据类型的范围更广,它已不 再局限于机器已定义和实现的数据类型, 还包括用户在设计软件系统时自行定义的数据类型。 使用抽象数据类型定义的软件模块含定义、 表示和
4、实现三部分, 封装在一起, 对用户透明 (提 供接口) , 而不必了解实现细节。 抽象数据类型的出现使程序设计不再是 “艺术” , 而是向 “科 学”迈进了一步。 3解答: 评价好的算法有四个方面。 一是算法的正确性; 二是算法的易读性; 三是算法的健壮性; 四是算法的时空效率(运行) 。 4解答: 逻辑结构、存储结构、操作(运算) 。 5解答: 通常考虑算法所需要的存储空间量和算法所需要的时间量。后者又涉及到四方面:程序 运行时所需输入的数据总量,对源程序进行编译所需时间,计算机执行每条指令所需时间和 程序中指令重复执行的次数。 6解答: 栈和队列的逻辑结构相同,其存储表示也可相同(顺序存储
5、和链式存储) ,但由于其运 算集合不同而成为不同的数据结构。 7解答: 线性表中的插入、删除操作,在顺序存储方式下平均移动近一半的元素,时间复杂度为 O(n);而在链式存储方式下,插入和删除时间复杂度都是 O(1)。 8解答: 对算法 A1 和A2 的时间复杂度 T1 和 T2 取对数,得 nlog22和2log2n。显然,算法A2 好 于A1。 9解答: 语句执行的次数为 n-2 次,T(n)= O(n)。 语句执行的次数为 n-1 次,T(n)= O(n)。 语句执行的次数为 n次,T(n)= O(n)。 语句执行的次数为 n 1/2 次,T(n)= O(n 1/2 )。 语句执行的次数为
6、(n(n-1)(n-2)/6 次,T(n)= O(n 3 )。 习题二 一、选择题 1C 2C 3A 4C 5B 6D 7A 8A 9B 10 A 二、填空题 1. 不管单链表是否为空表,头指针均不空,并使得对单链表的操作在各种情况下统一 2. 4 2 3. 随机 随机存取 4. O(n) O(n) 5. 相同 6. O(1) O(n) 7. 不同 8. 物理存储位置 链指针 9. O(1) O(n) 10.L-next=L if(!L.elem) return false; / 存储分配失败 L.listsize+=L.incrementsize; / 当前存储容量增加 for(i=L.le
7、ngth-1;i=0i-) L.elemi+1=L.elemi; L.elemi+1=x; L.length+; return true; 2算法描述如下: void Converse_Sq(SqList ElemType x; mid=L.length/2; for(i=0;imid;i+) x=L.elemi; L.elemi=L.elemL.length-1-i; L.elemL.length-1-i=x; 3算法描述如下: void Converse2_Sq(ElemType a,int low, int high) int n,i; ElemType x; n=(high-low+1
8、)/2; for(i=0;in;i+) x=alow+i; alow+i=ahigh-i; ahigh-i=x; void Exchange_Sq(ElemType a,int m,int n) Converse2_Sq(a,0,m+n-1); Converse2_Sq(a,0,n-1); Converse2_Sq(a,n,n+m-1); 4算法描述如下: void Delete_Sq(SqList for(i=0;i=si-) if(L.elemi=0) for(k=i;knext; head-next=NULL; while(p) q=p; p=p-next; q-next=head-ne
9、xt; head-next=q; 6算法描述如下: void LinListSort(LinkList p=head-next; head-next=NULL; while(p) curr=head-next; pre=head; while(curr curr=curr-next; q=p; p=p-next; q-next=pre-next; pre-next=q; 7算法描述如下: bool NListInsert_L( LinkList int j; p=head; j=1; while(p-next j+; / 寻找第 i-1 个结点,并让 p 指向此结点 if(j!=i-1 / i
10、 的位置不合理 if(s=(LNode *)malloc(sizeof(LNode)=NULL) exit(1); / 存储分配失败 s-data=e; if(i=1) / 插入在表头 s-next=head; head=s; else s-next=p-next; p-next=s; / 插入新结点 return true; bool NListDelete_L( LinkList int j; p=head; j=1; while(p-next j+; / 寻找第 i-1 个结点,并让 p 指向此结点 if(j!=i-1 / i 的位置不合理 if(i=1) / 删除表头结点 q=p; h
11、ead=head-next; else q=p-next; / q 指向其后继 p-next=q-next; / 删除q 所指结点 e=q-data; free(q); return true; 8算法描述如下: typedef struct DuNode ElemType data; struct DuNode *prior; struct DuNode *next; DuLNode,*DuLinkList; int ListLength_DuL(DuLinkList int num=0; while(p!=L) num+; p=p-next; return num; bool ListGe
12、t_DuL(DuLinkList int j; p=L-next; j=1; while(p-next!=L j+; / 寻找第i个结点,并让p 指向此结点 if(j!=i) return false; / i 的位置不合理 e=p-data; / 被取元素的值赋给 e return true; 9算法描述如下: bool IsSubSet(LinkList La, LinkList Lb) bool ok1,ok2; LinkList p1,p2; ok1=true; p1=La-next; while(ok1 p2=Lb-next; while(!ok2 else p2=p2-next;
13、ok1=ok2; p1=p1-next; return ok1; 10算法描述如下: void merge_L(LinkList La, LinkList Lb, LinkList Lc=La; pa=La-next; Lc-next=NULL; pb=Lb-next; free(Lb); while(pa pa=pa-next; qa-next=Lc-next; Lc-next=qa; else if(pa-datapb-data) qb=pb; pb=pb-next; qb-next=Lc-next; Lc-next=qb; else qa=pa; qb=pb; pa=pa-next; p
14、b=pb-next; qa-next=Lc-next; Lc-next=qa; free(qb); while(pa) qa=pa; pa=pa-next; qa-next=Lc-next; Lc-next=qa; while(pb) qb=pb; pb=pb-next; qb-next=Lc-next; Lc-next=qb; 11算法描述如下: void Interaction(LinkList ha,LinkList hb,LinkList LinListSort(ha); LinListSort(hb); /调用第6题的排序函数 pa=ha-next; pb=hb-next; hc=(
15、LinkList)malloc(sizeof(LNode); hc-next=NULL; while(pa else if(pa-datapb-data) pb=pb-next; else pc=(LinkList)malloc(sizeof(LNode); pc-data=pa-data; pc-next=hc-next; hc-next=pc; pa=pa-next; pb=pb-next; 12算法描述如下: void Decompose(LinkList L,LinkList p=L; ha=(LNode *)malloc(sizeof(LNode); hb=(LNode *)mall
16、oc(sizeof(LNode); hc=(LNode *)malloc(sizeof(LNode); ha-next=ha; hb-next=hb; hc-next=hc; while(p) if(Adata q-next=ha-next; ha-next=q; else if(0data q-next=hb-next; hb-next=q; else q=p; p=p-next; q-next=hc-next; hc-next=q; 13算法描述如下: void Delete_L(LinkList L) / 删除带头结点的单链表 L 中值相同的多余结点 LinkList p,q,s; p=
17、L-next; while(p-next while(q-next) if(p-data=q-next-data) s=q-next; q-next=s-next; free(s); else q=q-next; p=p-next; 14算法描述如下: int CountNode(LinkList head,ElemType x) int sum=0; LinkList p=head-next; while(p) if(p-data=x) sum+; p=p-next; return sum; 15算法描述如下: void RetNode(LinkList L, LinkList p=L-ne
18、xt; pa=La=(LNode *)malloc(sizeof(LNode); pb=Lb=(LNode *)malloc(sizeof(LNode); while(p) if(p-data%2) pa-next=p; p=p-next; pa=pa-next; else pb-next=p; p=p-next; pb=pb-next; pa-next=NULL; pb-next=NULL; 习题三 一、选择题 1B 2B 3B 4D 5C 6A 7D 8D 9D 10C 二、填空题 1. SXSSXSXX 2. 18 3. (m+1)%n 4. 只允许在表的一端进行元素的插入而在另一端进行
19、元素的删除 5. top1+1=top2 三、算法设计题 说明:以下解答中有关顺序栈的习题要包含头文件:SqStack.h,有关顺序循环队列的 习题要包含头文件:SqQueue.h,有关单链表的习题要包含头文件:LinkList.h。 1算法描述如下: bool ExpIsCorrect(char exp,int n) SqStack S; int i; char x; InitStack_Sq(S); for(i=0;in;i+) if(expi=(|expi=|expi=) Push_Sq(S,expi); else if(expi=) else if(expi=) return fals
20、e; else if(expi= else if(expi= return false; else if(expi= else if(expi= return false; else if(expi=)|expi=|expi=) return false; if(!StackEmpty_Sq(S) cout“左括号多于右括号!“endl; return false; else cout“括号匹配成功!“endl; return true; 2算法描述如下: void LQInitiate(LinkList Rear-next=Rear; bool LQAppend(LinkList if(!(
21、p=(LNode *)malloc(sizeof(LNode) return false; p-data=x; p-next=Rear-next; Rear-next=p; Rear=p; return true; bool LQDelete(LinkList Rear,ElemType front=Rear-next; if(front-next=front) coutnext; d=p-data; front-next=p-next; free(p); return true; 3算法描述如下: void Output() int x; SqStack S; InitStack_Sq(S)
22、; cinx; while(x!=0) Push_Sq(S,x); cinx; while(!StackEmpty_Sq(S) Pop_Sq(S,x); coutx“ “; coutendl; DestroyStack_Sq(S); / 撤销顺序栈 4算法描述如下: # define MAX 20 typedef struct ElemType vMAX; int front,rear,top; QueueStack; void InitQS(QueueStack QS.top=MAX; bool Estack(QueueStack else QS.v-QS.top=e; return tru
23、e; bool Equeue(QueueStack else QS.v+QS.rear=e; return true; 5说明:为简单起见,解答中队列采用静态顺序结构。 算法描述如下: # define QueueSize 100 typedef struct int front; int rear; int tag; ElemType queueQueueSize; CirQueue_1; void InitQueue(CirQueue_1 Q.tag=0; bool EnQueue(CirQueue_1 return false; Q.tag=1; Q.queueQ.rear=e; Q.r
24、ear=(Q.rear+1)%QueueSize; return true; bool DeQueue(CirQueue_1 return false; e=Q.queueQ.front; Q.tag=0; Q.front=(Q.front+1)%QueueSize; return true; 6算法描述如下: # define QueueSize 100 typedef struct int front; int rear; int count; ElemType queueQueueSize; CirQueue_2; void InitQueue(CirQueue_2 Q.count=0;
25、 bool EnQueue(CirQueue_2 return false; Q.count+; Q.queueQ.rear=e; Q.rear=(Q.rear+1)%QueueSize; return true; bool DeQueue(CirQueue_2 return false; e=Q.queueQ.front; Q.count-; Q.front=(Q.front+1)%QueueSize; return true; 7算法描述如下: 队满条件:Q.length=QueueSize # define QueueSize 100 typedef struct int length;
26、 int rear; ElemType queueQueueSize; CirQueue_3; void InitQueue_3(CirQueue_3 Q.length=0; bool EnQueue_3(CirQueue_3 return false; Q.queueQ.rear=e; Q.rear=(Q.rear+1)%QueueSize; Q.length+; return true; bool DeQueue_3(CirQueue_3 return false; int tmpfront; tmpfront=(QueueSize+Q.rear-Q.length)%QueueSize;
27、Q.length-; e=Q.queuetmpfront; return true; 8算法描述如下: bool IsHuiWen(char *str) SqQueue Q; SqStack S; char x,y; int i,length=strlen(str); InitQueue_Sq(Q); InitStack_Sq(S); for(i=0;in; cout“请输入“n“个 10 以内的整数:“; for(i=0;ia; for(j=0;jdata=x; q-next=p; q=p; q-next=NULL; void Print(LinkList head) LinkList p=
28、head-next; while(p) coutdata; p=p-next; coutendl; 10题目分析栈的特点是后进先出,队列的特点是先进先出。所以,用两个栈 S1 和 S2 模拟一个队列时,S1 作输入栈,逐个元素进栈,以此模拟队列元素的入队。当需要出队 时,将栈 S1退栈并逐个进栈 S2 中,S1 中最先入栈的元素,在 S2 中处于栈顶。S2 退栈,相 当于队列的出队,实现了先进先出。显然,只有栈 S2 为空且 S1 也为空,才算是队列空。 算法描述如下: typedef struct ElemType stackMaxStackSize; int top; SqStack; b
29、ool EnQueue(SqStack return false; if(S1.top=MaxStackSize Push(S2,x); Push(S1,x); return true; /x 入栈,实现了队列元素的入队 bool DeQueue(SqStack return true; else /处理 S2 空栈 if(StackEmpty(S1) cout“队列空!“endl; return false; /若输入栈也为空,则判定队空 else /先将栈S1 倒入 S2 中,再作出队操作 while(!StackEmpty(S1) Pop(S1,x); Push(S2,x); Pop(S
30、2,x); /S2 退栈相当于队列出队 return true; bool QueueEmpty(SqStack S1,SqStack S2) /本算法判用栈 S1和 S2 模拟的队列是否为空 if(StackEmpty(S1) else return false ; /队列非空 算法讨论算法中假定栈 S1 和栈 S2 容量相同。出队从栈 S2 出,当 S2 为空时,若 S1 不空,则将 S1 倒入S2 再出栈。入队在 S1,当 S1满后,若 S2空,则将 S1倒入 S2,之后再 入队。因此队列的容量为两栈容量之和。元素从栈 S1 倒入 S2,必须在 S2 空的情况下才能 进行,即在要求出队操
31、作时,若 S2空,则不论 S1 元素多少(只要不空) ,就要全部倒入 S2 中。 习题四 一、选择题 1B 2B 3C 4D 5D 二、填空题 1. 顺序存储方式 链接存储方式 2. 两个串的长度相等且对应位置的字符相同 3. 零个字符的串 零 4. 由一个或多个空格字符组成的串 其包含的空格个数 5. 字符 6. 任意个连续的字符组成的子序列 7. 串的整体或串的某一部分子串 串复制 取子串 插入子串 删除子串等 三、算法设计题 说明:以下解答中有关动态顺序串的习题要包含头文件:DSqString.h,有关单链结构 的习题要包含头文件: SLinkString.h, 有关顺序循环队列的习题要
32、包含头文件: SqQueue.h, 有关单链表的习题要包含头文件:LinkList.h。 1本题的算法思想是:从头到尾扫描 S 串,对于值为 ch1 的元素直接替换成 ch2 即可。 其算法描述如下: void Trans_Sq(DSqString for(i=0;iS.length;i+) if(S.stri=ch1)S.stri=ch2; 2算法描述如下: void Delall_Sq(DSqString k=S.length; while(inext) if(p-next-str=ch) q=p-next; p-next=q-next; free(q); else p=p-next; 4
33、算法描述如下: bool Equalsubstr(DSqString S,DSqString head=0; /head 指向当前发现的最长等值子串的串头 max=1; /max 记录子串的长度 for(i=0,j=1;imax) /发现新的最长等值子串,更新 head和 max head=i; max=count; if(max1) if(!(sub.str=(char *)malloc(i*sizeof(char) / 给串 sub 申请空间 return false; for(k=0;kS.length|jS.length|i=j) return false; disc=j-i-1; i
34、f(T.lengthdisc) if(!(S.str=(char )realloc(S.str,(S.length+T.length-disc)*sizeof(char) return false; for(k=S.length-1;k=j;k-) S.strk+T.length-disc=S.strk; for(k=0;knext k+; if(k!=i) return false; k=0; while(q-next k+; if(k!=j) return false; r=T-next; while(r-next) / r 指向串T 的表尾 r=r-next; h=p-next; p-n
35、ext=T-next; / 删除第 i 到第 j 个结点,并插入串 T free(T); r-next=q; while(h!=q h=h-next; free(r); return true; 7算法描述如下: bool pattern_index(DSqString S,DSqString T,int / i 和 j 分别扫描主串 S 和子串 T while(iS.length j+; else / 主串指针回溯重新开始下一次匹配 i=i-j+1; j=0; if(j=T.length) pos=i-T.length; return true; else return false; / I
36、ndex_Sq 8算法描述如下: int Substr_count(DSqString substr,DSqString str) int i=0,j,k,count=0; for(i=0;inext; while(p) if(p-str=x) p-str=y; p=p-next; 10算法描述如下: bool Found(SLinkString head,char x) / 若x在链表 head中,返回 true;否则返回 false while(head-next if(head-next) return true; else return false; bool FindFirst(SL
37、inkString S,SLinkString T,char if(!S-next) coutnext; while(Found(T,p-str) p=p-next; ch=p-str; 11.本题采用动态顺序结构存储从键盘输入的字符串。 算法描述如下: void Count(DSqString S) int i,j,num36; for(i=0;i=0 numi+; else if(A=S.strj numi+; for(i=0;i10;i+) printf(“数字%d 的个数=%dn“,i,numi); for(i=10;i36;i+) printf(“字母字符%c 的个数=%dn“,i+
38、55,numi); 12算法描述如下: 块链结构的定义如下: # define Number 80 / 可由用户定义的结点大小 # include “stdlib.h“ typedef struct Chunk char strNumber; / 一个结点存放 Number 个字符 struct Chunk *next; Chunk; / 结点类型定义 typedef struct BLhead Chunk *head,*tail; / 串的头尾指针 int length; / 串的当前长度 BLhead,*BLinkString; bool SubStr_BL(BLinkString S,
39、BLinkString int j,n,m,w,l,u; n=S-length; p=S-head; if(pos=0 sub=(BLhead *)malloc(sizeof(BLhead); /创建子串头结点 sub-length=len; sub-head=(Chunk *)malloc(sizeof(Chunk); /创建子串的第一个结点 q=sub-head; w=1; /指向子串中的当前结点 u=m; /指向主串中的当前结点 l=pos; /指向主串中的当前位置 for(j=0;j=Number *w) /所取字符的个数超过一个结点中的最大字符数 w+; /子串结点数加 1 q-ne
40、xt=(Chunk *)malloc(sizeof(Chunk); /创建新结点 q=q-next; /指向子串中下一个结点 if(l=Number *u) /主串中的字符的个数超过一个结点中的最大字符数 u+; /主串结点数加 1 p=p-next; /指向主串中下一个结点 q-strj%Number=p-strl%Number; /给子串中的相应结点赋值 l+; /指向主串中的下一个字符 return true; else return false; 13算法描述如下: void DSqstrSort(DSqString for(i=0; iS.strj) t=S.stri; S.stri
41、=S.strj; S.strj=t; bool Replacestr_Sq(DSqString S,DSqString T,DSqString if(!S.length|!T.length) coutT.strj) j+; else V.strk=S.stri; i+;j+;k+; V.length=k; return true; 14算法描述如下: void Delsubstr_Sq(DSqString while(Index_Sq(S,T,pos) / 判断T 是否是 S 的子串 StrDelete_Sq(S,pos,T.length); / 删除子串T 15. 本题要求字符串 S1 拆分
42、成字符串 S2 和字符串 S3,要求字符串 S2“按给定长度 n 格式化成两端对齐的字符串” ,即长度为 n 且首尾字符不得为空格字符。算法从左到右扫 描字符串 S1,找到第一个非空格字符,计数到 n,第 n 个拷入字符串 S2的字符不得为空 格,然后将余下字符复制到字符串 S3 中。 算法描述如下: bool format(DSqString S1,DSqString if(!(S2.str=(char *)malloc(n*sizeof(char) / 给串S2 申请空间 return false; while(iS1.length if(i=S1.length) cout“字符串 S1
43、为空串或空格串“endl; return false; while(iS1.length i+; j+; k+; if(i=S1.length) cout“字符串 S1 没有“n“个有效字符“endl; return false; if(S2.str-j= ) /若最后一个字符为空格,则需向后找到第一个非空格字符 i-; /i 后退 while(S1.stri= if(i=S1.length) cout“S1 串没有“n“个两端对齐的字符串“endl; return false; S2.strj=S1.stri; /字符串 S2 最后一个非空字符 i+; S2.length=n; j=0; /将 S1 串其余部分送字符串 S3。 if(!(S3.str=(char *)malloc(S1.length-i)*sizeof(char) / 给串S2申请空间 return false; while (iS1.length) S3.strj+=S1.stri+; S3.length=j; return true;