1 / 27

数据结构习题解答 (三)

数据结构习题解答 (三). helibao@mail.ustc.edu.cn 2011.12.30. 第三次作业 3.6 3.17 3.19 3.28 第六次作业 5.5 5.6 5.7 5.22 第九次作业 6.16 6.19 6.21 6.22 6.25 6.26 6.27 6.56 第十二次作业 7.11 7.13 7.42. 第三次作业. 3.6 试证明:若借助栈由输入序列 12…n 得到的输出序列为 p1p2…pn (它是输入序列的一个排列),则在输出序列中不可能出现这样的情形:存在 i<j<k 使 pj<pk<pi 。 解答: 反证法!

layne
Download Presentation

数据结构习题解答 (三)

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. 数据结构习题解答(三) helibao@mail.ustc.edu.cn 2011.12.30

  2. 第三次作业 • 3.6 3.17 3.19 3.28 • 第六次作业 • 5.5 5.6 5.7 5.22 • 第九次作业 • 6.16 6.19 6.21 6.22 6.25 6.26 6.27 6.56 • 第十二次作业 • 7.11 7.13 7.42

  3. 第三次作业 • 3.6 试证明:若借助栈由输入序列12…n得到的输出序列为p1p2…pn(它是输入序列的一个排列),则在输出序列中不可能出现这样的情形:存在i<j<k使pj<pk<pi。 • 解答:反证法! • 假设存在i<j<k使pj<pk<pi,则有: (1)pi>pj且i<j,pi和pj曾共存于栈中,且pi更靠近栈顶; (2)pi>pk且i<k,pi和pk曾共存于栈中,且pi更靠近栈顶; (3)由i<j<k可得,pi、pj、pk按序依次出栈。 综上,pi出栈时pj和pk尚在栈中,并且pj早于pk出栈,于是有:pj>pk。 这与题设pj<pk矛盾,证毕! 注!i<j说明pi早于pj出栈,而pi>pj说明pi晚于pj入栈。

  4. 第三次作业 • 3.17 试写出一个算法,识别一次读入一个以@为结束符的字符序列是否为形如‘序列1&序列2’模式的字符序列。其中序列1和序列2都不含字符‘&’,且序列2是序列1的逆序列。例如‘a+b&b+a’是属于该模式的字符序列,而‘1+3&3-1’则不是。 • 解答: • int IsReverse( ) //序列1和2为逆串返回1,否则返回0{   InitStack(s);   while((e=getchar())!=‘&’) { push(s,e);}    while((e=getchar())!='@')   {   if(StackEmpty(s)) { return 0;}      pop(s,c);     if(e!=c) { return 0;}   }if(!StackEmpty(s)) { return 0;} //如“aa+b&b+a”中序列1不是2的逆序 return 1;}

  5. 第三次作业 • 3.19 假设一个算术表达式中可以包含三种括号:圆括号‘(’和‘)’、方括 号‘[’和‘]’和花括号‘{’和‘}’,且这三种括号可按任意的次序嵌套使用(如: {[()[]]})。编写判别给定表达式所包含括号是否正确配对出现的算法 (已知表达式已存入数据元素为字符的顺序表中)。 • 解答: • Status AllBrackets_Test(char *str) //判别表达式中三种括号是否匹配{ InitStack(s);for(p=str;*p;p++){    if(*p==‘(’||*p==‘[’||*p==‘{’) push(s,*p);    else if(*p==‘)’||*p==‘]’||*p==‘}’)    {       if(StackEmpty(s)) return ERROR;       pop(s,c);       if(*p==‘)’&&c!=‘(’) return ERROR;       if(*p==‘]’&&c!=‘[’) return ERROR;       if(*p==‘}’&&c!=‘{’) return ERROR; //必须与当前栈顶括号匹配} }//for if(!StackEmpty(s)) return ERROR; //如“([]{}”不匹配 return OK; }//AllBrackets_Test

  6. 第三次作业 • 3.28 假设以带头结点的循环链表表示队列,并且只设一个指针指向队尾元素结点(注意不设头指针),试编写相应的队列初始化、入队列和出队列的算法。 • 解答: void InitCiQueue(CiQueue &Q) //初始化 { Q=(CiLNode*)malloc(sizeof(CiLNode)); Q->next=Q; }//InitCiQueue

  7. 第三次作业 • 3.28(续) • void EnCiQueue(CiQueue &Q,int x) //把元素x插入循环链表表示的队列Q,Q指向队尾元素,Q->next指向头结点,Q->next->next指向队头元素{  p=(CiLNode*)malloc(sizeof(CiLNode));  p->data=x;  p->next=Q->next; //直接把p加在Q的后面Q->next=p;  Q=p;  //修改尾指针} • Status DeCiQueue(CiQueue &Q,int x) //从循环链表表示的队列Q头部删除元素x{ if(Q==Q->next) return INFEASIBLE; //队列已空p=Q->next->next;  x=p->data;  Q->next->next=p->next;  free(p);  return OK;}//DeCiQueue

  8. 第六次作业 • 5.5 设有上三角阵(aij)nxn,将其上三角元素逐行存于数组B[m]中(m充分大),使得B[k]=aij且k=f1(i)+f2(j)+c。试推导出f1,f2和常数c(要求f1和f2中不含常数项)。 • 解答:上三角阵中有i ≤ j. aij之前有i行(0 ~ i-1) 第i行上aij之前元素个数为j-i(i ~ j-1).

  9. 第六次作业 • 5.6 设有三对角矩阵(aij)nxn,将其三条对角线上的元素存于数组B[3][n]中,使得元素B[u][v]=aij,试推导出从(i,j)到(u,v)的下标变换公式。 • 解答:下标从(0,0)开始 u=i-j+1 v=min{i, j} 备注:B[0][0…n-2] 和 B[2][0…n-2]存储两侧对角线元素 & B[1][0…n-1] 存储主对角线元素

  10. 第六次作业 • 5.7 设有三对角矩阵(aij)nxn,将其三条对角线上的元素存于数组B[3n-2]中,使得元素B[k]=aij,求: (1)用i,j表示k的下标变换公式; (2)用k表示i,j的下标变化公式; • 解答:下标从(0,0)开始 (1)i>0时,aij前有i行(0~i-1),其中第一行两个元素,其他行三个元素,共有元素数为:2+3(i-1) 第i行中,aij前有j-i个元素(i~j-1),所以: k=2+3(i-1)+(j-i)=2i+j-1 (i=0时等式也满足) (2)j-1≤i≤j+1 =>3j-2≤k+1≤3j+2 => j-2/3≤(k+1)/3 ≤j+2/3 => j= 于是,i=

  11. 第六次作业 • 5.22 假设系数矩阵A和B均以三元组顺序表作为存储结构。试写出满足以下的矩阵相加的算法:假设三元组顺序表A的空间足够大,将矩阵B加到矩阵A上,不增加A,B之外的附加空间,你的算法能否达到O(m+n)的时间复杂度,其中m和n分别为A,B矩阵中非零元的数目。 • 解答: void TSMatrix_Addto(TSMatrix &A,TSMatrix B)//将三元组矩阵B加到A上 {  for(i=0;i<A.tu;i++)  { //把A的所有元素都移到尾部以腾出位置 A.data[MAXSIZE-A.tu+i]=A.data[i]; }    pa=MAXSIZE-A.tu ;pb=0;pc=0; for(pb=0; pb<B.tu; pb++) { if (A.data[pa].i==B.data[pb].i){

  12. 第六次作业 • 5.22(续) if(A.data[pa].j==B.data[pb].j) { ne = A.data[pa].v + B.data[pb].v; if(ne) { A.data[pc].i = A.data[pa].i; A.data[pc].j = A.data[pa].j; A.data[pc].v = ne; pc++; } // end if(ne!=0) pa++; pb++; } //end if(…) else if(A.data[pa].j<B.data[pb].j){ A.data[pc].i = A.data[pa].i; A.data[pc].j = A.data[pa].j; A.data[pc].v = A.data[pa].v; pc++; pa++; } else {//A.data[pa].j>B.data[pb].j A.data[pc].i = B.data[pb].i; A.data[pc].j = B.data[pb].j; A.data[pc].v = B.data[pb].v; pc++; pb++; } } //end if(…)

  13. 第六次作业 • 5.22(续2) else if (A.data[pa].i<B.data[pb].i) { A.data[pc].i = A.data[pa].i; A.data[pc].j = A.data[pa].j; A.data[pc].v = A.data[pa].v; pc++; pa++; } else {//A.data[pa].i>B.data[pb].i A.data[pc].i = B.data[pb].i; A.data[pc].j = B.data[pb].j; A.data[pc].v = B.data[pb].v; pc++; pb++; } } //end for(…) for(i=A.tu;i<MAXSIZE;i++) { //清除原来的A中记录 A.data[i]={0,0,0}; } A.tu=pc; } //end TSMatrix_Addto()

  14. 第九次作业 • 6.16 将下列二叉链表改为先序线索链表(不画出树的形态)。 • 解答:

  15. 第九次作业 • 6.19 分别画出和下列树对应的二叉树。 • 解答:

  16. 第九次作业 • 6.21 画出和下列二叉树对应的森林。 • 解答:

  17. 第九次作业 • 6.22 对于6.19题中给出的各树分别求出以下遍历序列:(1)先根序列;(2)后根序列。 • 解答:遍历原树,而不是对应的二叉树! • (1) • (a) A (b) ABC (c) ABC • (d) ABCEIJFGKHD • (2) • (a) A (b) CBA (c) BCA • (d) BIJEFKGHCDA

  18. 第九次作业 • 6.23 画出和下列已知序列对应的树T: 树的先根次序访问序列为GFKDAIEBCHJ 树的后根次序访问序列为DIAEKFCJHBG。 • 解答:

  19. 第九次作业 • 6.26 假设用于通信的电文仅由8个字母组成,字母在电文中出现的频率分别为0.07,0.19,0.02,0.06, 0.32,0.03,0.21,0.10。试为这8个字母设计Huffman编码。使用0~7的二进制表示的形式是另一种编码方案。对于上述两种实例,比较两种方案的优缺点。 • 解答: 平均码长比为 2.61:3 Huffman编码较优

  20. 第九次作业 • 6.27 假设一颗二叉树的先序序列为EBADCFHGI KJ和中序序列为ABCDEFGHIJK。请画出该树。 解答:

  21. 第九次作业 • 6.56 试写出一个算法,在先序后继线索二叉树中,查找给定结点*p在先序序列中的后继(假设二叉树的根结点未知)。并讨论实现此算法对存储结构有何要求? • 解答: BTNode *PreOrder_Next(BTNode *p) //在先序后继线索二叉树中 //查找结点p的先序后继,并返回指针 {if(p->lchild) return p->lchild;//有左孩子,则左孩子即为后继 else return p->rchild; //无左孩子但有右孩子,则右孩子为 //后继,否则rchild指向的右线索即为后继 }//PreOrder_Next • 存储结构要求:只需要添加Rtag域,为1则rchild指向后继,否则指向右孩子。

  22. 第十二次作业 • 7.11 试利用Dijkstra算法求解题7.11图中从顶点a到其他各顶点间的最短路径,写出执行算法过程中各步的状态。 • 解答:

  23. 第十二次作业 • 7.13 试利用Floyd算法求解7.13图所示有向图中各对顶点之间的最短路径。 • 解答:根据PPT上算法迭代运算即可 初始值A(-1),P(-1) 四个顶点四次迭代,依次得到 A0,P0; A1,P1; A2,P2; A3,P3 详细过程略。。。

  24. 第十二次作业 • 7.42 以邻接表作存储结构实现求从源点到其余各顶点的最短路径的Dijkstra算法 • 解答:在PPT上算法的基础上修改! typedef int Distance[n]; typedef int Path[n] void Dijkstra ( ALGraph G, Distance D, Path P, int s ){ //0≤s ≤n-1,若<i,j>不是边,则G…… Boolean S[n];//S是红点集。S[i]为真表示i为红点,否则为白点 for ( i=0; i<n; i++) { //初始化 S[i]=FALSE; D[i]=INFINITY; for (p=G.vertices[s].firstarc; !p; p=p->nextarc) { D[p->adjvex] = *(p->info); //s为始点的边长,作为初始的估计距离 } if ( D[i]<Infinity ) P[i]=s; //<s,i>∊E, s是i的前驱(双亲) else P[i]=-1; // i无前驱,注意P[s]亦无前驱 } S[s]=TRUE; D[s]=0;//红点集仅有源点s

  25. 第十二次作业 • 7.42(续) for ( i=0; i<n-1; i++) { //向红点集S扩充n-1个红点 min=Infinity; for ( j=0; j<n; j++ ) //选估计距离最小的白点k(离s最近){ if ( !S[ j ] && D[ j ]<min ) { min=D[ j ]; k=j; } } if (min==Infinity) return; // 白点集为空或只剩下无最短路径的点 S[k]=TRUE; // k加入红点集 for (p=G.vertices[k].firstarc; !p; p=p->nextarc){ j= p->adjvex; if ( !S[ j ] && D[j]>D[k]+*(p->info) ) {//调整剩余白点的估计距离 D[j] = D[k]+*(p->info) ;//修改白点j的估计距离,使之离s更近 P[j] = k; // k是j的前驱 } }//endfor }

  26. Question?

  27. 祝大家考试顺利 谢谢!

More Related