数据结构C语言版习题解答.docx
- 文档编号:10152603
- 上传时间:2023-02-08
- 格式:DOCX
- 页数:31
- 大小:225.07KB
数据结构C语言版习题解答.docx
《数据结构C语言版习题解答.docx》由会员分享,可在线阅读,更多相关《数据结构C语言版习题解答.docx(31页珍藏版)》请在冰豆网上搜索。
数据结构C语言版习题解答
1.3设n是正整数。
试写出下列程序段中用记号“△”标注的语句的频度:
(2)i=1;k=0;
do{
△k+=10*i;
i++;
}while(i<=n-1)
当n=1时,执行1;
当n>=2时,执行n-1次;
(3)i=1;k=0;
do{
△k+=10*i;i++;
}while(i==n);
当n=2时,执行2次;
当n!
=2时,执行1次;
(4)i=1;j=0;
while(i+j≤n){
△if(i } 执行n次; (5)x=n;y=0;//n是不小于1的常数 while(x>=(y+1)*(y+1)){ △y++; } 执行 向下取整) (6)x=91;y=100; while(y>0) △if(x>100){x-=10;y--;} elsex++; } If语句执行100次 (7)for(i=0;i for(j=i;j for(k=j;k △x+=2; 过程: 第二章 2.3已知顺序表La中数据元素按非递减有序排列。 试写一个算法,将元素x插到La的合适位置上,保持该表的有序性。 思路: 先判断线性表的存储空间是否满,若满返回Error;否则从后向前先移动数据,找到合适的位置插入。 StatusInsert_SqList(SqList&La,intx)//把x插入递增有序表La中 { if(La.length==La.listsize)returnERROR; for(i=La.length-1;La.elem[i]>x&&i>=0;i--) La.elem[i+1]=La.elem[i]; La.elem[i+1]=x; La.length++; returnOK; }//Insert_SqList 2.5试写一个算法,实现顺序表的就地逆置,即在原表的存储空间将线性表(a1,a2,...,an-1,an)逆置为(an,an-1,...,a2,a1) //思路就是两个指示变量i,j同时分别从顺序表的开始和结尾处相向改变 voidreverse(SqList&A)//顺序表的就地逆置 { ElemTypep; for(i=1,j=A.length;i { //A.elem[i]<->A.elem[j]; p=A.elem[i]; A.elem[i[=A.elem[j]; A.elem[j]=p; } }//reverse 2.7已知线性表L采用顺序存储结构存放,对两种不同情况分别写出算法,删除L中多余的元素,使得L中没有重复元素: (1)L中数据元素无序排列; (2)L中数据元素非递减有序排列。 voidDelete_SameElem(SqLink&L,intL.length){ //层循环移动参数,中层循环寻找相同元,外层循环遍历整个表 inti=0;intj=i+1;intlength=L.length; while(i for(j=i+1;j if(L.Elem[j]==L.Elem[i]){// for(k=j;k L.Elem[k]=L.Elem[k+1]; length--; j--;//移动元素后,由于少了一个元素,因此要减1 } }//endif If(L.Elem[j]>L.Elem[i])break;//第二小问添加此句 }//endfor }//endwhile }//endfunctoion 2.8已知线性表L采用链式结构存放。 对两种不同情况分别写出算法,删除L中值相同的多余元素,使得L中没有重复元素: (1)L中数据元素无序排列; (2)L中数据元素非递减有序排列。 (1)L中数据元素无序排列; 思路: 由于是无序排列,需要线性表中每个元素都要相互进行比较。 StatusListDelete(Linklist&L)//L是带头结点的线性表 { ElemType*p,*q; p==L->next;q=p->next;//设定p变化较慢,q变化较快 while(p->next){ while(q){ if(p->data! =q->data) q=q->next; else{ q=q->next; p->next=q; }//else }//while p=p->next;q=p->next;//开始后一结点的寻找 returnOK; }//ListDelete (2)L中数据元素非递减有序排列。 思路: 由于是有序的,遍历一次线性表就行了 StatusListDelete(LinkList&L) { ElemType*p,*q; p=L->next;q=p->next; while(p->next) { if(p->data! =q->data){ p=p->next;//和第一问不同地方 q=p->next; }//if else{ while(p->data==q->data) q=q->next;//多个连续的重复值 }//else p->next=q;p=q;q=p->next;//删除值重复的结点,并修改相应的指针 returnOK; }//ListDelete 2.9设有两个非递减有序的单链表A,B。 请写出算法,将A和B就地归并成一个按元素值非递增有序的单链表。 //将合并逆置后的结果放在C表中,并删除B表 StatusListMergeOppose_L(LinkList&A,LinkList&B,LinkList&C) { LinkListpa,pb,qa,qb; pa=A; pb=B; qa=pa;//保存pa的前驱指针 qb=pb;//保存pb的前驱指针 pa=pa->next; pb=pb->next; A->next=NULL; C=A; while(pa&&pb){ if(pa->data qa=pa; pa=pa->next; qa->next=A->next;//将当前最小结点插入A表表头 A->next=qa; } else{ qb=pb; pb=pb->next; qb->next=A->next;//将当前最小结点插入A表表头 A->next=qb; } } while(pa){ qa=pa; pa=pa->next; qa->next=A->next; A->next=qa; } while(pb){ qb=pb; pb=pb->next; qb->next=A->next; A->next=qb; } pb=B; free(pb); returnOK; } 2.13设以带头结点的双向循环链表表示的线性表L=(a1,a2,a3,...,an)。 试写一时间复杂度为O(n)的算法,将L改造为L=(a1,a3,...,an,...,a4,a2)。 voidReform(DuLinkedList&L)//按1,3,5,...4,2的顺序重排双向循环链表L中的所有结点 { p=L.next; while(p->next! =L&&p->next->next! =L) { p->next=p->next->next; p=p->next; }//p指向最后一个奇数结点 if(p->next==L)//结点个数是奇数,使最后一个奇数结点next指向最后一个偶数结点 p->next=L->pre->pre; else//结点个数是偶数,使最后一个奇数结点next指向最后一个偶数结点 p->next=L->pre; p=p->next;//此时p指向最后一个偶数结点 while(p->pre->pre! =L) { p->next=p->pre->pre; p=p->next; } p->next=L;//最后一个结点next指向头结点 //调整了next链的结构,此时pre链仍为原状 //调整pre链的结构 for(p=L;p->next! =L;p=p->next)p->next->pre=p; L->pre=p;//头结点的pre指向a2结点 }//Reform 第三章栈和队列 3.6试写一个算法,识别依次读入的一个以@为结束符的字符序列是否为形如“序列1&序列2”模式的字符序列。 其中,序列1和序列2中都不包含字符‘&’,且序列2是序列1的逆序。 例如,“a+b&b+a”是属于该模式的字符序列,而“1+3&3-1”则不是。 算法: intSeqReverse()//判断输入的字符串中'&'前和'&'后部分是否为逆串,是则返回1,否则返回0 { InitStack(s); while((e=getchar())! ='&') { if(e==’@’) return0;//不允许在’&’之前出现’@’ push(s,e); }//序列1输入完毕 while((e=getchar())! ='@') { if(StackEmpty(s)) return0; pop(s,c); if(e! =c) return0; } if(! StackEmpty(s)) return0;//序列1元素还有剩余 return1; }//IsReverse 3.7假设一个算术表达式中可以包含三种符号: 圆括号“(”和“)”、方括号“[”和“]”、花括号“{”和“}”,且这三种括号可按任意次序嵌套使用。 编写判别给定表达式中所含的括号是否正确配对的算法(已知表达式已存入数据元素为字符的顺序表中)。 算法: StatusBracketTest(char*str)//判别表达式中三种括号是否匹配 { InitStack(s); for(p=str;*p;p++) { if(*p=='('||*p=='['||*p=='{') push(s,*p); else if(*p==')'||*p==']'||*p=='}') { if(StackEmpty(s)) returnERROR; pop(s,c); if(*p==')'&&c! ='(')returnERROR; if(*p==']'&&c! ='[')returnERROR; if(*p=='}'&&c! ='{')returnERROR;//必须与当前栈顶括号匹配 }//if }//for if(! StackEmpty(s))returnERROR;//进栈的符号还有剩余,Error returnOK; }//BracketTest 3.8设表达式由单字母变量、双目运算符和圆括号组成(如: “(a*(b+c)-d)/e)”。 试写一个算法,将一个书写正确的表达式转换为逆波兰式。 思路: 1.遇到数字直接发送2.遇到’(’直接入栈3.遇到’)’则将栈元素发送直至遇到’(’4.栈空则直接入栈5.栈非空时若优先级大于栈则入栈,否则栈元素出栈 intRankOfOperator(charc){ switch(c){ case'#': return-1; case'(': return0; case'+': case'-': return1; case'*': case'/': case')': return2; } } intPrecede(charc,charch){ returnRankOfOperator(c)>RankOfOperator(ch); } voidExpressionTOPolandStyle(charsuffix[],char*exp){ Stacks;InitStack(s,100);inti=0;charc; while(*exp){ if(isdigital(*exp)) suffix[i++]=*exp; else{ switch(*exp){ case'(': push(s,'('); case')': while((c=pops(s))! ='(') suffix[i++]=c; break; default: if(IsEmpty(s)) push(s,*exp); else{ suffix[i++]=pop(s); exp--; //与后面的exp++相抵消,使得栈优先级大于等于栈外的都出栈 } }//endswitch }//endelse exp++; }//endwhile while(! IsEmpty(s))suffix[i++]=pop(s);suffix[i]=0; } 3.10假设以带头结点的单循环链表表示队列,只设一个尾指针指向队尾元素,不设头指针。 试编写相应的队列初始化、入队和出队算法(在出队算法中要传回队头元素的值) 要点: 定义好数据类型,带头结点的单循环链表,只有尾指针,注意删除元素时只有一个元素的特殊性 typedefintDataType structNode{ DataTypedata; Node*next; }; structCycleListQueue{ Node*tail; }; voidInitCycleListQueue(CycleListQueue&L){ L.tail=newNode; L.tail->next=L.tail; } voidEnterQueue(CycleListQueue&L,DataTypevalue){ Node*p=newNode; p->data=value; p->next=L.tail->next; L.tail->next=p; L.tail=p; } voidDeparQueue(CycleListQueue&L,DataType&d){ if(L.tail->next! =L.tail->next->next){ Node*p=L.tail->next->next; L.tail->next->next=p->next; d=p->data; if(p==L.tail)L.tail=p->next; deletep; returnd; } } 3.11假设将循环队列定义为: 以rear和length分别指示队尾元素和队列长度。 试给出此循环队列的队满条件,并写出相应的入队和出队算法(在出队算法中要传递回队头元素的值)。 此循环队列的队满条件: Q.length==MAXQSIZE; 入队算法: StatusEnCyQueue(CyQueue&Q,intx)//带length域的循环队列入队算法 { if(Q.length==MAXSIZE)returnOVERFLOW; Q.rear=(Q.rear+1)%MAXSIZE; Q.base[Q.rear]=x;//rear指向队尾元素 Q.length++; returnOK; }//EnCyQueue 出队算法: StatusDeCyQueue(CyQueue&Q,int&x)//带length域的循环队列出队算法,用x返回队头元素的值 { if(Q.length==0)returnError;//空队列,错误 head=(Q.rear-Q.length+1)%MAXSIZE;//head指向队头 x=Q.base[head]; Q.length--; returnOK; }//DeCyQueue 3.12试写一个算法: 判别读入的一个以‘@’为结束符的字符序列是否是“回文”(所谓“回文”是指正读和反读都相同的字符序列,如“xxyzyxx”是回文,而“abcab”则不是回文)。 StatusTest()//判别输入的字符串是否回文序列,是则返回1,否则返回0 { InitStack(S); InitQueue(Q); while((c=getchar())! ='@') { Push(S,c); EnQueue(Q,c);//同时使用栈和队列两种结构 } while(! StackEmpty(S)) { Pop(S,a); DeQueue(Q,b); if(a! =b)returnERROR; } returnOK; }//Test 第五章多维数组 5.4设有一个准对角矩阵 按以下方式存于一维数组B[4m]中: 0 1 2 3 4 5 6 k 4m-2 4m-1 a11 a12 a21 a22 a33 a34 a43 ... aij ... a2m-1,2m a2m,2m 写出由一对下标(i,j)求k的转换公式。 因为i行前有2(i-1)个元素。 现考虑i行情况,当j是奇数,i行有1个元素,k=2(i-1)+1-1=2(i-1);否则i行有2个元素,k=2(i-1)+2-1=2i-1。 故: k= 或若i为奇数,k=2(i-1)+j-i=i+j-2;当i为偶数时,k=2i-(i-j)-1=i+j-1 k= 5.5已知稀疏矩阵A4×5如下: (1)用三元组表作为存储结构,绘出相应的三元组表示意图; (2)用十字链表作为存储结构,绘出相应的十字链表示意图。 (1)三元组表: i j v 1 2 1 1 5 5 2 1 2 2 2 3 2 4 6 4 2 4 4 5 7 (2)十字链表 第六章数和二叉树 6.5已知一棵度为k的树中有n1个度为1的结点,n2个度为2的结点,...,nk个度为k的结点,问该树中有多少个叶子结点? 设叶子结点有x个,则树的结点总数为n1+n2+…nk+x; 同时除了根结点外,每个结点都指向一个结点,所有从这个角度考虑树的结点总数为: n1+2•n2+…k•nk+1; n1+n2+…nk+x=n1+2•n2+…k•nk+1,可得x= 6.8已知一棵树如图6-1所示,画出与该树对应的二叉树,并写出该树的先根遍历序列和后根遍历序列。 先根遍历: ABCEIJFGKHD 后根遍历: BIJEFKGHCDA 对应的二叉树: 6.9将如图6-2所示的森林转化为对应的二叉树。 K 图6-2 A C D E B F G H J I L M N O 树对应的二叉树 森林对应的二叉树: 6.11已知某二叉树的中序序列为DCBGEAHFIJK,后序序列为DCEGBFHKJIA。 请画出该二叉树。 6.14假设某个电文由(a,b,c,d,e,f,g,h)8个字母组成,每个字母在电文中出现的次数分别为(7,19,2,6,32,3,21,10),试解答下列问题: (1)画出出huffman树; 1000 2c 3f 5 11 G 28 7a 17 32e 60 6d 19b 21g 40 10h (2)写出每个字母的huffman编码; a: 1010b: 00c: 10000d: 1001e: 11f: 10001g: 01h: 1011 (3)在对该电文进行最优二进制编码处理后,电文的二进制位数。 4*7+2*19+5*2+4*6+2*32+5*3+2*21+4*10=261 6.17写出按层次遍历二叉树的算法。 思路: 用队列存储结构,并用递归方法 StatusLevelOrderTraverse(BitTreeT,Status(*Visit)(TElemTypee)//层序遍历二叉树 { InitQueue(Q);//初始化队列 if(! T)returnError;//空树,直接返回 EnQueue(Q,T);//根结点入队 BiTNode*p; while(! QueueEmpty(Q)) { DeQueue(Q,p); Visit(p->data); if(p->lchild)EnQueue(Q,p->lchild); if(p->rchild)EnQueue(Q,p->rchild); }//while returnOk; }//LevelOrderTraverse 6.19写出判断两棵给定二叉树是否相似的算法。 (注: 两棵二叉树B1和B2相似是指: B1和B2皆空,或者皆不空且B1的左、右子树和B2的左、右子树分别相似。 ) 思路: 采用递归进行比较判断 boolBiTreeSimilar(BiTreeT1,BiTreeT2) { if(T1==Null&&T2==Null) return1; elseif(T1==Null||T2==Null) return0; else return(BiTreeSilimar(T1->lchild,T2->lchild)&&BiTreeSimilar(T1->rchild,T2->rchild)); } 6.21写出统计树中叶子结点个数的算法,树用孩子兄弟链表表示。 思路: 在孩子兄弟链表中,若结点的firstchild为Null,则为叶子结点;采用递归方法。 intCountLeaves(TreeT,int&num)//num传递的初值为0 { if(T->nextsibling! =Null) num+=CountLeaves(T->nextsibling); if(T->firstchild! =Null) num+=CountLeaves(T->firstchild); else num+=1;//firstchild域为空,则为叶子结点 returnnum; } 图7-1 V5 V4 V2 V3 V1 V6 第七章图 7.1已知有向图如图7-1所示, 请给出该图的 (1)邻接矩阵示意图 (2)邻接表示意图 (3)逆邻接表 (4)所有强连通分量
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 数据结构 语言版 习题 解答