版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
习题一1.简述下列概念:数据、数据元素、数据项、数据对象、数据结构、逻辑结构、存储结构、抽象数据类型。答案:数据:能被计算机处理的所有符号集合。数据元素:数据的基本处理单位。数据项:数据最小不可分割标识单位。数据对象:性质相同的数据元素集合。数据结构:数据间相互关系与组织方式。逻辑结构:数据元素抽象逻辑关系,与存储无关。存储结构:逻辑结构在内存的物理存储形式。抽象数据类型:数据定义+操作集合,封装实现、只看接口。2.试举一个数据结构的例子,叙述其逻辑结构和存储结构两个层次的含义及相互关系。答案:例如,学生线性表。把全班学生信息当作数据对象,单个学生为数据元素。逻辑结构为线性结构,学生前后依次排列,一对一前驱后继,连续有序。存储结构可以有两种:①顺序存储:连续内存空间,数组存放,地址相邻。②链式存储:内存分散,指针连接结点,地址不连续。逻辑结构和存储结构的关系:①逻辑结构是关系本质,抽象不变。②存储结构是落地实现,形式可变。③同一逻辑结构,可对应多种存储结构;存储结构决定存取效率。3.简述逻辑结构的四种基本关系并画出它们的关系图。答案:四种逻辑结构简述①集合结构。元素只同属一个集合,无前后、从属关系,仅共存。②线性结构。元素一对一,有唯一前驱后继,呈线性顺序。③树结构。元素一对多,分层从属,有父结点、子结点。④图结构。元素多对多,任意结点互相连通。四种逻辑结构关系简图①集合结构○○○互不相连②线性结构○→○→○→○③树结构④图结构4.存储结构有哪两种基本的存储方法实现?答案:①顺序存储。连续内存存放,相邻元素地址连续,依靠位置体现关系,如数组。②链式存储。内存分散不连续,结点存数据+指针,靠指针关联元素,如链表。5.选择题(1)在数据结构中,从逻辑上可以把数据结构分成(C)A.动态结构和静态结构B.紧凑结构和非紧凑结构C.线性结构和非线性结构D.内部结构和外部结构(2)与数据元素本身的形式、内容、相对位置、个数无关的是数据的(A)。A.存储结构B.存储实现C.逻辑结构D.运算实现(3)通常要求同一逻辑结构中的所有数据元素具有相同的特性,这意味着(B)。A.数据具有同一特点B.不仅数据元素所包含的数据项的个数要相同,而且对应数据项的类型要一致C.每个数据元素都一样D.数据元素所包含的数据项的个数要相等(4)以下说法正确的是(D)。A.数据元素是数据的最小单位B.数据项是数据的基本单位C.数据结构是带有结构的各数据项的集合D.一些表面上很不相同的数据可以有相同的逻辑结构(5)算法的时间复杂度取决于(A)。A.问题的规模B.待处理数据的初态C.计算机的配置D.A和B6.试分析下列各算法的时间复杂度。(1)x=90;y=lOO;while(y>O)if(x>lOO){x=x-lO;y--;}elsex++;答案:O(1)(2)for(i=O;i<n;i++)for(j=O;j<m;j++)a[i][j]=O;答案:O(n*m)(3)s=O;for(i=O;i<n;i++)for{j=O;j<n;j++)s+=B[i][j];sum=s;答案:O(n2)(4)i=l;while(i<=n)i=i*3;答案:O(logn)(5)x=O;for(i=l;i<n;i++)for(j=l;j<=n-i;j++)x++;答案:O(n2)(6)x=n;//n>ly=0while(x^(y+l)*(y+l))y++;答案:O(n)习题二1.选择题(1)顺序表中第一个元素的存储地址是100,每个元素的长度为2,则第5个元素的地址是(B)。A.110B.108C.100D.120(2)在含n个结点的顺序表中,算法的时间复杂度是0(1)的操作是(A)。A.访问第i个结点(1≤i≤n)和求第i个结点的直接前驱(1≤i≤n)B.在第i个结点后插入一个新结点(1≤i≤n)C.删除第1个结点(1≤i≤n)D.将n个结点从小到大排序(3)在一个有127个元素的顺序表中插入一个新元素并保持原来顺序不变,平均要移动的元素个数为(B)。A.8B.63.5C.63D.7(4)链接存储的存储结构所占存储空间(A)。A.分为两部分,一部分存放结点值,另一部分存放表示结点间关系的指针B.只有一部分,存放结点值C.只有一部分,存储表示结点间关系的指针D.分两部分,一部分存放结点值,另一部分存放结点所占单元数(5)线性表若采用链式存储结构,要求内存中可用存储单元的地址(D)。A.必须是连续的B.部分地址必须是连续的C.一定是不连续的D.连续或不连续都可以(6)线性表L在(B)情况下适用于使用链式结构实现。A.需经常修改L中的结点值B.需不断对L进行删除、插入C.L中含有大量的结点D.L中结点结构复杂(7)单链表的存储密度(C)。A.大于1B.等于1C.小于1D.不能确定(8)将两个各有n个元素的有序表归并成一个有序表,其最少的比较次数是(A)。A.nB.2n-1C.2nD.n-1(9)在一个长度为n的顺序表中,在第i个元素(l≤i≤n+1)之前插入一个新元素时需向后移动(B)个元素。A.n-iB.n-i+1C.n-i-1D.i(10)线性表L=(a1,a2,…,an),下列陈述正确的是(D)。A.每个元素都有一个直接前驱和一个直接后继B.线性表中至少有一个元素C.表中诸元素的排列必须是由小到大或由大到小D.除第一个和最后一个元素外,其余每个元素都有一个且仅有一个直接前驱和直接后继(11)创建一个包括n个结点的有序单链表的时间复杂度是(C)。A.O(1)B.O(n)C.O(n2)D.O(nlog2n)(12)以下陈述错误的是(D)。A.求表长、定位这两种运算在采用顺序存储结构时实现的效率不比采用链式存储结构时实现的效率低B.顺序存储的线性表可以随机存取C.由于顺序存储要求连续的存储区域,所以在存储管理上不够灵活D.线性表的链式存储结构优于顺序存储结构(13)在单链表中,要将s所指结点插入到p所指结点之后,其语句应为(D)。A.s->next=p+1;p->next=s;B.(*p).next=s;(*s).next=(*p).next;C.s->next=p->next;p->next=s->next;D.s->next=p->next;p->next=s;(14)在双向链表存储结构中,删除p所指结点时修改指针的操作为(A)。A.p->next->prior=p->prior;p->prior->next=p->next;B.p->next=p->next->next;p->next->prior=p;C.p->prior->next=p;p->prior=p->prior->prior;D.p->prior=p->next->next;p->next=p->prior->prior(15)在双向循环链表中,在p指针所指的结点后插入q所指向的新结点,其修改指针的操作是(C)。A.p->next=q;q->prior=p;p->next->prior=q;q->next=q;B.p->next=q;p->next->prior=q;q->prior=p;q->next=p->next;C.q->prior=p;q->next=p->next;p->next->prior=q;p->next=q;D.q->prior=p;q->next=p->next;p->next=q;p->next->prior=q;2.算法设计题(1)将两个递增的有序链表合并为一个递增的有序链表。要求结果链表仍使用原来两个链表、的存储空间,不另外占用其他的存储空间。表中不允许有重复的数据。答案:voidMerge_Increase(LinkList&La,LinkList&Lb,LinkList&Lc){//Lc直接使用La的头结点Lc=La;Node*pa=La->next,*pb=Lb->next,*pc=Lc;while(pa&&pb){if(pa->data<pb->data){pc->next=pa;pc=pa;pa=pa->next;}elseif(pa->data>pb->data){pc->next=pb;pc=pb;pb=pb->next;}else{//相等时删除一个pc->next=pa;pc=pa;pa=pa->next;Node*tmp=pb;pb=pb->next;free(tmp);}}pc->next=pa?pa:pb;free(Lb);//Lb头结点无用}(2)将两个非递减的有序链表合并为一个非递增的有序链表。要求结果链表仍使用原来两个链表的存储空间,不另外占用其他的存储空间。表中允许有重复的数据。答案:voidMerge_Decrease(LinkList&La,LinkList&Lb,LinkList&Lc){Lc=La;Node*pa=La->next,*pb=Lb->next;Lc->next=NULL;//新表为空,采用头插法实现逆序while(pa&&pb){if(pa->data<=pb->data){Node*tmp=pa->next;pa->next=Lc->next;Lc->next=pa;pa=tmp;}else{Node*tmp=pb->next;pb->next=Lc->next;Lc->next=pb;pb=tmp;}}while(pa){Node*tmp=pa->next;pa->next=Lc->next;Lc->next=pa;pa=tmp;}while(pb){Node*tmp=pb->next;pb->next=Lc->next;Lc->next=pb;pb=tmp;}free(Lb);}(3)已知两个链表A和B分别表示两个集合,其元素递增排列。请设计一个算法,用于求出A与B的交集,并存放在A链表中。答案:voidIntersection(LinkList&A,LinkListB){Node*pa=A->next,*pb=B->next,*pc=A;while(pa&&pb){if(pa->data<pb->data){Node*tmp=pa;pa=pa->next;free(tmp);}elseif(pa->data>pb->data){pb=pb->next;}else{pc->next=pa;pc=pa;pa=pa->next;pb=pb->next;}}//删除A中剩余结点while(pa){Node*tmp=pa;pa=pa->next;free(tmp);}pc->next=NULL;}(4)已知两个链表A和B分别表示两个集合,其元素递增排列。请设计算法求出两个集合A和B的差集(即仅由在A中出现而不在B中出现的元素所构成的集合),并以同样的形式存储,同时返回该集合的元素个数。答案:intDifference(LinkList&A,LinkListB){Node*pa=A->next,*pb=B->next,*pc=A;intcount=0;while(pa&&pb){if(pa->data<pb->data){pc->next=pa;pc=pa;pa=pa->next;count++;}elseif(pa->data>pb->data){pb=pb->next;}else{//相等,删除Node*tmp=pa;pa=pa->next;free(tmp);}}//剩余pa全部是差集部分while(pa){pc->next=pa;pc=pa;pa=pa->next;count++;}pc->next=NULL;returncount;}(5)设计算法将一个带头结点的单链表A分解为两个具有相同结构的链表B和C,其中B表的结点为A表中值小于零的结点,而C表的结点为A表中值大于零的结点(链表A中的元素为非零整数,要求B、C表利用A表的结点)。答案:voidSplitBySign(LinkListA,LinkList&B,LinkList&C){B=(LinkList)malloc(sizeof(Node));C=(LinkList)malloc(sizeof(Node));B->next=NULL;C->next=NULL;Node*pb=B,*pc=C;Node*p=A->next;while(p){Node*next=p->next;if(p->data<0){pb->next=p;pb=p;}elseif(p->data>0){pc->next=p;pc=p;}p=next;}pb->next=NULL;pc->next=NULL;free(A);//A原头结点可释放}(6)设计一个算法,通过一趟遍历确定长度为n的单链表中值最大的结点。答案:Node*FindMax(LinkListL){if(L->next==NULL)returnNULL;Node*p=L->next;Node*maxNode=p;while(p){if(p->data>maxNode->data)maxNode=p;p=p->next;}returnmaxNode;}(7)设计一个算法,将链表中所有结点的链接方向“原地”逆转,即要求仅利用原表的存储空间,换句话说,要求算法的空间复杂度为O(1)。答案:voidReverse(LinkList&L){Node*prev=NULL;Node*cur=L->next;Node*next;while(cur){next=cur->next;cur->next=prev;prev=cur;cur=next;}L->next=prev;}(8)设计一个算法,删除递增有序链表中值大于mink且小于maxk:的所有元素(mink和maxk是给定的两个参数,其值可以和表中的元素相同,也可以不同)。答案:voidDeleteRange(LinkListL,intmink,intmaxk){Node*p=L;while(p->next&&p->next->data<=mink)p=p->next;Node*q=p->next;while(q&&q->data<maxk){Node*tmp=q;q=q->next;free(tmp);}p->next=q;}(9)已知p指向双向循环链表中的一个结点,其结点结构为data、prior、next三个域,写出算法change(p),交换p所指向的结点及其前驱结点的顺序。答案:voidchange(Node*p){Node*prev=p->prior;if(prev==p)return;//只有一个结点//调整前后结点的链接prev->prior->next=p;p->prior=prev->prior;p->next->prior=prev;prev->next=p->next;prev->prior=p;p->next=prev;}(10)已知长度为n的线性表A采用顺序存储结构,请写一个时间复杂度为O(n)、空间复杂度为O(1)的算法,该算法可删除线性表中所有值为item的数据元素。答案:voidDeleteItem(intA[],int&n,intitem){intk=0;//新表长度for(inti=0;i<n;i++){if(A[i]!=item){A[k++]=A[i];}}n=k;}习题三1.选择题(1)若让元素1,2,3,4,5依次进栈,且进栈和出栈可以穿插进行,则出栈次序不可能出现(C)的情况。A.5,4,3,2,1B.2,1,5,4,3C.4,3,1,2,5D.2,3,5,4,1(2)若已知一个栈的入栈序列是1,2,3,…,n,其输出序列为p1,p2,…,pn,若p1=n,则pi为(C)。A.iB.n-iC.n-i+1D.不确定(3)已知栈的最大容量为4。若进栈序列为1,2,3,4,5,6,且进栈和出栈可以穿插进行,则可能出现的出栈序列为(C)。A.5,4,3,2,1,6 B.2,3,5,6,1,4C.3,2,5,4,1,6 D.1,4,6,5,2,3(4)设栈S的初始状态为空,若元素a、b、c、d、e、f依次进栈,得到的出栈序列是b、d、c、f、e、a,则栈S的容量至少是(B)。A.2B.3C.4D.6(5)若一个栈以向量V[l..n]存储,初始栈顶指针top设为n+1,则元素x进栈的正确操作是(C)。A.top++;V[top]=x;B.V[top]=x;top++C.top--;V[top]=x;D.V[top]=x;top--(6)判定一个顺序栈ST(最多元素为n)为栈满的条件是(D)。A.top!=0B.top==0C.top!=nD.top==n-1(7)向一个栈顶指针为hs的不带头结点的链栈中插入一个*s结点时,则执行(C)。A.hs->next=s;B.s->next=hs->next;hs->next=s;C.s->next=hs;hs=s;D.s->next=hs;hs=hs->next;(8)为解决计算机主机与打印机间速度不匹配问题,通常设一个打印数据缓冲区。主机将要输出的数据依次写入该缓冲区,而打印机则依次从该缓冲区中取出数据。该缓冲区的逻辑结构应该是(A)。A.队列B.栈C.线性表D.有序表(9)依次在初始为空的队列中插入元素a,b,c,d以后,紧接着做了两次删除操作,此时的队头元素是(C)。A.aB.bC.cD.d(10)在一个链队列中,front和rear分别为头指针和尾指针,则插入一个结点s的操作为(C)。A.front=front->nextB.s->next=rear;rear=sC.rear->next=s;rear=s;D.s->next=front;front=s;(11)数组Q[n]用来表示一个循环队列,f为当前队列头元素,r为队尾元素的位置,假定队列中元素的个数小于n,计算队列中元素个数的公式为(D)。A.r-fB.(n+f-r)%nC.n+r-fD.(n+r-f)%n(12)设计一个判别表达式中左、右括号是否配对出现的算法,采用(D)最佳。A.线性表的顺序存储结构B.队列C.线性表的链式存储结构D.栈(13)用链接方式存储的队列,在进行删除运算时(D)。A.仅修改头指针B.仅修改尾指针C.头、尾指针都要修改D.头、尾指针可能都要修改(14)循环队列存储在数组A[0..m]中,则入队时的操作为(D)。A.rear=rear+1B.rear=(rear-1)%(m-1)C.rear=(rear+l)%mD.rear=(rear+l)%(m+l)(15)栈和队列的共同点是(C)。A.都是先进先出B.都是先进后出C.只允许在端点处插入和删除元素D.没有共同点2.算法设计题(1)回文是指正读反读均相同的字符序列,如"abba"和"abdba"均是回文,但"good"不是回文。试写一个算法判定给定的字符序列是否为回文。(提示:将一半字符入栈)答案:#include<stdbool.h>#include<string.h>boolisPalindrome(charstr[]){intn=strlen(str);charstack[n/2+1];inttop=-1;//前一半入栈for(inti=0;i<n/2;i++){stack[++top]=str[i];}//奇数长度跳过中间intstart=(n%2==0)?n/2:n/2+1;//比较后一半for(inti=start;i<n;i++){if(stack[top--]!=str[i])returnfalse;}returntrue;}(2)假设以1和0分别表示入栈和出栈操作。栈的初态和终态均为空,入栈和出栈操作序列可表示为仅由I和O组成的序列,称可以操作的序列为合法序列,否则称为非法序列。①下面所示的序列中哪些是合法的?A.IOIIOIOOB.IOOIOIIOC.IIIOIOIOD.IIIOOIOO答案:A、D合法②通过对①的分析,写出一个算法,判定所给的操作序列是否合法。若合法,返回true,否则返回false(假定被判定的操作序列巳存入一维数组中)。答案:boolisValidSequence(charops[],intn){intstackSize=0;for(inti=0;i<n;i++){if(ops[i]=='I'){stackSize++;}elseif(ops[i]=='O'){if(stackSize==0)returnfalse;stackSize--;}}returnstackSize==0;}(3)假设以带头结点的循环链表表示队列,并且只设一个指针指向队尾元素结点(注意:不设头指针),试编写相应的置空队列、判断队列是否为空、入队和出队等算法。答案://结构定义:typedefstructNode{intdata;structNode*next;}Node,*Queue;//置空队列voidinitQueue(Queue*rear){*rear=(Node*)malloc(sizeof(Node));(*rear)->next=*rear;//循环指向自身}//判空boolisEmpty(Queuerear){returnrear->next==rear;}//入队(在队尾插入)voidenqueue(Queue*rear,intx){Node*s=(Node*)malloc(sizeof(Node));s->data=x;s->next=(*rear)->next;(*rear)->next=s;*rear=s;}//出队(删除头结点后的结点)booldequeue(Queue*rear,int*x){if((*rear)->next==*rear)returnfalse;//空Node*head=(*rear)->next;Node*p=head->next;//队头结点*x=p->data;head->next=p->next;if(p==*rear)*rear=head;//只剩一个结点free(p);returntrue;}(4)假设以数组Q[m]存放循环队列中的元素,同时设置一个标志tag,以tag=0和tag=1来区别在队头指针(front)和队尾指针(rear)相等时,队列状态为“空”还是“满"。试编写与此结构相应的插入(enqueue)和删除(dequeue)算法。答案://结构定义:#definem100typedefstruct{intQ[m];intfront,rear;inttag;//0:空,1:满(仅在front==rear时有效)}Queue;//初始化:voidinitQueue(Queue*q){q->front=q->rear=0;q->tag=0;}//判空:boolisEmpty(Queueq){returnq.front==q.rear&&q.tag==0;}//判满:boolisFull(Queueq){returnq.front==q.rear&&q.tag==1;}//入队:boolenqueue(Queue*q,intx){if(q->front==q->rear&&q->tag==1)returnfalse;//满q->Q[q->rear]=x;q->rear=(q->rear+1)%m;if(q->rear==q->front)q->tag=1;returntrue;}//出队:booldequeue(Queue*q,int*x){if(q->front==q->rear&&q->tag==0)returnfalse;//空*x=q->Q[q->front];q->front=(q->front+1)%m;q->tag=0;returntrue;}习题四1.选择题(1)串是一种特殊的线性表,其特殊性体现在(B)。A.可以顺序存储B.数据元素是单个字符C.可以链式存储D.数据元素可以是多个字符(2)下列关于串的的叙述中,不正确的是(B)。A.串是字符的有限序列B.空串是由空格构成的串C.模式匹配是串的一种重要运算D.串既可以采用顺序存储,也可以采用链式存储(3)串“ababaaababaa”的next数组为(C)。A.012345678999B.012121111212C.011234223456D.0123012322345(4)串“ababaabab”的nextval为(A)。A.010104101B.010102101C.010100011D.010101011(5)串的长度是指(B)。A.串中所含不同字母的个数B.串中所含字符的个数C.串中所含不同字符的个数D.串中所含非空格字符的个数(6)假设以行序为主序存储二维数组A=array[1..100,1..100],设每个数据元素占2个存储单元,基地址为10,则LOC[5,5]=(B)。A.808B.818C.1010D.1020(7)设有数组A[i,j],数组的每个元素长度为3字节,i的值为1〜8,j的值为1〜10,数组从内存首地址BA开始顺序存放,当用以列为主存放时,元素A[5,8]的存储首地址为(B)。A.BA+141B.BA+180C.BA+222D.BA+225(8)设有一个10阶的对称矩阵A,采用压缩存储方式,以行序为主存储,a11叫为第一元素,其存储地址为1,每个元素占一个地址空间,则a85的地址为(C)。A.13B.32C.33D.40(9)若对阶对称矩阵A以行序为主序方式将其下三角形的元素(包括主对角线上所有元素)依次存放于一维数组列B[1..(n(n+1))/2]中,则在B中确定aij(i<j)的位置k的关系为(B)。A.i×(i-1)/2+jB.j×(j-1)/2+iC.i×(i+1)/2+jD.j×(j+1)/2+i(10)二维数组A的每个元素是由10个字符组成的串,其行下标i=0,l,…,8,列下标j=l,2,…,10。若A按行先存储,元素A[8,5]的起始地址与当A按列先存储时的元素(B)的起始地址相同,设每个字符占一个字节。A.A[8,5]B.A[3,10]C.A[5,8]D.A[0,9](11)设二维数组A[1..m,1..n](即m行n列)按行存储在数组B[1..m×n]中,则二维数组元素A[i,j]在一维数组B中的下标为(A)。A.(i-1)×n+jB.(i-1)×n+j-1C.i×(j-1)D.j×m+i-1(12)数组A[0..4,-1..-3,5..7]中含有元素的个数为(B)。A.55B.45C.36D.162.应用题(1)已知模式串t=“abcaabbabcab”,写出用KMP算法求得的每个字符对应的next和nextval函数值。答案:next=[0,1,1,1,2,2,3,1,2,3,1,2]nextval=[0,1,1,0,2,1,3,0,1,1,0,1](2)设目标为t=“abcaabbabcabaacbacba”,模式为p=“abcabaa”。①计算模式p的nextval函数值;答案:nextval=[0,1,1,2,3,2,2]②画出利用KMP算法进行模式匹配时每一趟的匹配过程。答案:第一趟t:abcaabbabcabaacbacbap:abcabaaj:1234567i=1,j=1:t[1]=a,p[1]=a✅i=2,j=2i=2,j=2:t[2]=b,p[2]=b✅i=3,j=3i=3,j=3:t[3]=c,p[3]=c✅i=4,j=4i=4,j=4:t[4]=a,p[4]=a✅i=5,j=5i=5,j=5:t[5]=a,p[5]=b❌j=nextval[5]=3i=5,j=3:t[5]=a,p[3]=c❌j=nextval[3]=1i=5,j=1:t[5]=a,p[1]=a✅i=6,j=2i=6,j=2:t[6]=b,p[2]=b✅i=7,j=3i=7,j=3:t[7]=b,p[3]=c❌j=nextval[3]=1i=7,j=1:t[7]=b,p[1]=a❌j=nextval[1]=0→j=0⇒i++=8,j++=1第二趟i=8,j=1:t[8]=a,p[1]=a✅i=9,j=2i=9,j=2:t[9]=b,p[2]=b✅i=10,j=3i=10,j=3:t[10]=c,p[3]=c✅i=11,j=4i=11,j=4:t[11]=a,p[4]=a✅i=12,j=5i=12,j=5:t[12]=b,p[5]=b✅i=13,j=6i=13,j=6:t[13]=a,p[6]=a✅i=14,j=7i=14,j=7:t[14]=a,p[7]=a✅匹配成功,位置i=14,j=7,模式串起始于i-j+1=14-7+1=8匹配位置:t[8..14]=abcaaba?检查:t[8..14]=abcabaa✅(3)数组A中,每个元素A[i,j]的长度均为32个二进制位,行下标从-1〜9,列下标从1〜11,从首地址S开始连续存放在主存储器中,主存储器字长为16位。求:①存放该数组所需多少单元?②存放数组第4列所有元素至少需多少单元?③数组按行存放时,元素A[7,4]的起始地址是多少?④数组按列存放时,元素A[4,7]的起始地址是多少?答案:①总单元数:242②第4列单元数:22③行序A[7,4]地址:S+182④列序A[4,7]地址:S+1423.算法设计题(1)写一个算法统计在输入字符串中各个不同字符出现的频度并将结果存入文件(字符串中的合法字符为A〜Z这26个字母和0〜9这10个数字)。答案:#include<stdio.h>voidcountCharsToFile(constchar*str,constchar*filename){intcount[36]={0};//0~25:A-Z,26~35:0-9for(inti=0;str[i]!='\0';i++){charc=str[i];if(c>='A'&&c<='Z'){count[c-'A']++;}elseif(c>='0'&&c<='9'){count[26+(c-'0')]++;}}FILE*fp=fopen(filename,"w");if(!fp)return;for(inti=0;i<26;i++){if(count[i]>0)fprintf(fp,"%c:%d\n",'A'+i,count[i]);}for(inti=0;i<10;i++){if(count[26+i]>0)fprintf(fp,"%c:%d\n",'0'+i,count[26+i]);}fclose(fp);}(2)写一个递归算法来实现字符串逆序存储,要求不另设串存储空间。答案:#include<string.h>voidreverseRecur(char*s,intleft,intright){if(left>=right)return;chartemp=s[left];s[left]=s[right];s[right]=temp;reverseRecur(s,left+1,right-1);}voidreverseString(char*s){if(s)reverseRecur(s,0,strlen(s)-1);}(3)编写算法,实现下面函数的功能。函数voidinsert(char*s,char*t,intpos)将字符串t插入到字符串s中,插人位置为pos。假设分配给字符串s的空间足够让字符串r插入。(说明:不得使用任何库函数)答案:#include<string.h>voidinsert(char*s,constchar*t,intpos){intlen_s=strlen(s);intlen_t=strlen(t);//将s[pos..len_s-1]后移len_t位for(inti=len_s;i>=pos;i--){s[i+len_t]=s[i];}//插入tfor(inti=0;i<len_t;i++){s[pos+i]=t[i];}}(4)已知字符串S1中存放一段英文,写出算法format(sl,s2,s3,n),将其按给定的长度n格式化成两端对齐的字符串S2,其多余的字符送S3。答案:#include<string.h>#include<ctype.h>voidformat(constchar*s1,char*s2,char*s3,intn){intlen=strlen(s1);inti=0,s2_idx=0,s3_idx=0;while(i<len){//跳过前导空格while(i<len&&s1[i]=='')i++;if(i>=len)break;//收集一行单词intword_start[100],word_end[100],word_len[100];intwc=0;intline_len=0;while(i<len&&s1[i]!='\0'){intstart=i;while(i<len&&s1[i]!='')i++;intend=i-1;intwlen=end-start+1;if(wc>0&&line_len+1+wlen>n)break;//放不下下一个单词word_start[wc]=start;word_end[wc]=end;word_len[wc]=wlen;line_len+=(wc==0?wlen:1+wlen);wc++;//跳过中间空格(i现在指向空格或末尾)while(i<len&&s1[i]=='')i++;}if(wc==1){//只有一个单词:左对齐for(intk=word_start[0];k<=word_end[0];k++)s2[s2_idx++]=s1[k];for(intk=word_len[0];k<n;k++)//补空格s2[s2_idx++]='';}else{//多个单词:均匀插空格inttotal_spaces=n-line_len;//需要多插入的空格数intbase_spaces=total_spaces/(wc-1);intextra=total_spaces%(wc-1);for(intw=0;w<wc;w++){for(intk=word_start[w];k<=word_end[w];k++)s2[s2_idx++]=s1[k];if(w<wc-1){intspaces=1+base_spaces+(w<extra?1:0);for(intk=0;k<spaces;k++)s2[s2_idx++]='';}}}s2[s2_idx++]='\n';}s2[s2_idx]='\0';//剩余部分放入s3while(i<len)s3[s3_idx++]=s1[i++];s3[s3_idx]='\0';}习题五1.选择题(1)把一棵树转换为二叉树后,这棵二叉树的形态是(A)。A.唯一的B.有多种C.有多种,但根结点都没有左孩子D.有多种,但根结点都没有右孩子(2)由3个结点可以构造出多少种不同的二叉树(D)。A.2B.3C.4D.5(3)一棵完全二叉树上有1001个结点,其叶子结点的个数是(D)。A.250B.254C.500D.501(4)一个具有1025个结点的二叉树的高h为(D)。A.10B.11C.10至1025之间D.10至1024之间(5)利用二叉链表存储树,则根结点的右指针(C)。A.指向最左孩子B.指向最右孩子C.为空D.非空(6)对二叉树的结点从1开始进行连续编号,要求每个结点的编号大于其左、右孩子的编号,同一结点的左右孩子中,其左孩子的编号小于其右孩子的编号,可采用(C)遍历实现编号。A.先序B.中序C.后序D.从根开始按层次(7)在一棵度为4的树T中,若有20个度为4的结点,10个度为3的结点,1个度为2的结点,10个度为1的结点,则树T的叶结点个数是(B)。A.41B.82C.113D.122(8)在下列存储形式中,(D)不是树的存储形式?A.双亲表示法B.孩子链表表示法C.孩子兄弟表示法D.顺序存储表示法(9)一棵非空的二叉树的先序遍历序列与后序遍历序列正好相反,则该二叉树一定满足(C)。A.所有的结点均无左孩子B.所有的结点均无右孩子C.只有一个叶子结点D.是任意一棵二叉树(10)设哈夫曼树中有199个结点,则该哈夫曼树中有(B)个叶子结点。A.99B.100C.98D.1012.应用题(1)试找出满足下列条件的二叉树。①先序序列与后序序列相同。②中序序列与后序序列相同。③先序序列与中序序列相同。④中序序列与层次遍历序列相同。答案:①单节点②左斜单链(仅有左分支)③右斜单链(仅有右分支)④右斜单链(仅有右分支)(2)设一棵二叉树的先序序列:ABDFCEGH,中序序列:BFDAGEHC。①画出这棵二叉树。②画出这棵二叉树的后序线索树。③将这棵二叉树转换成对应的树(或森林)。答案:①②③(3)假设用于通信的电文仅由8个字母组成,字母在电文中出现的频率分别为0.07,0.19,0.02,0.06,0.32,0.03,0.21,0.10。①试为这8个字母设计哈夫曼编码。②试设计另一种由二进制表示的等长编码方案。③对于上述实例,比较两种方案的优缺点。答案:①a:1111b:1110c:1101d:1100e:101f:100g:01h:00②a:000,b:001,c:010,d:011,e:100,f:101,g:110,h:111③哈夫曼编码优点:平均码长最短,利于数据压缩。缺点:解码需知道树结构,编解码较复杂,可能遇到错误传播(单个比特错影响一串)。等长编码优点:简单固定长度,解码快,容错易(错一个比特只影响一个字符的译码)。缺点:平均码长较长,压缩率差。(4)已知下列字符A、B、C、D、E、F、G的权值分别为3、12、7、4、2、8,11,试填写出其对应哈夫曼树存储结构的初态和终态。答案:(初态)结点weightparentlchildrchild13000212000370004400052000680007110008~130000答案:(终态)结点weightparentlchildrchild1(A)30002(B)120003(C)70004(D)40005(E)20006(F)80007(G)110008595199114810151236112013971227132101347011123.算法设计题以二叉链表作为二叉树的存储结构,编写以下算法:(1)统计二叉树的叶结点个数。(2)判别两棵树是否相等。(3)交换二叉树每个结点的左孩子和右孩子。(4)设计二叉树的双序遍历算法(双序遍历是指对于二叉树的每一个结点来说,先访问这个结点,再按双序遍历它的左子树,然后再一次访问这个结点,接下来按双序遍历它的右子树)。(5)计算二叉树最大的宽度(二叉树的最大宽度是指二叉树所有层中结点个数的最大值)□(6)用按层次顺序遍历二叉树的方法,统计树中度为1的结点数目。(7)求任意二叉树中第一条最长的路径长度,并输出此路径上各结点的值。(8)输出二叉树中从每个叶子结点到根结点的路径。答案:假定二叉树结点定义为:typedefstructBiTNode{chardata;structBiTNode*lchild,*rchild;}BiTNode,*BiTree;(1)统计叶结点个数intcountLeaves(BiTreeT){if(T==NULL)return0;if(T->lchild==NULL&&T->rchild==NULL)return1;returncountLeaves(T->lchild)+countLeaves(T->rchild);}(2)判别两棵树是否相等intisEqual(BiTreeT1,BiTreeT2){if(T1==NULL&&T2==NULL)return1;if(T1==NULL||T2==NULL)return0;if(T1->data!=T2->data)return0;returnisEqual(T1->lchild,T2->lchild)&&isEqual(T1->rchild,T2->rchild);}(3)交换每个结点的左右孩子voidswapChildren(BiTreeT){if(T==NULL)return;BiTNode*temp=T->lchild;T->lchild=T->rchild;T->rchild=temp;swapChildren(T->lchild);swapChildren(T->rchild);}(4)双序遍历(访问结点两次:中左右中右)voiddoubleOrder(BiTreeT){if(T==NULL)return;printf("%c",T->data);//第一次访问doubleOrder(T->lchild);printf("%c",T->data);//第二次访问doubleOrder(T->rchild);}(5)计算二叉树最大宽度#include<stdlib.h>#defineMAXSIZE100intmaxWidth(BiTreeT){if(T==NULL)return0;BiTreequeue[MAXSIZE];intfront=0,rear=0;queue[rear++]=T;intmax=0;while(front<rear){intlevelSize=rear-front;if(levelSize>max)max=levelSize;for(inti=0;i<levelSize;i++){BiTreep=queue[front++];if(p->lchild)queue[rear++]=p->lchild;if(p->rchild)queue[rear++]=p->rchild;}}returnmax;}(6)统计度为1的结点数目intcountDegree1(BiTreeT){if(T==NULL)return0;intcnt=0;BiTreequeue[MAXSIZE];intfront=0,rear=0;queue[rear++]=T;while(front<rear){BiTreep=queue[front++];intdegree=(p->lchild!=NULL)+(p->rchild!=NULL);if(degree==1)cnt++;if(p->lchild)queue[rear++]=p->lchild;if(p->rchild)queue[rear++]=p->rchild;}returncnt;}(7)求最长路径长度并输出路径上的结点值intheight(BiTreeT){if(T==NULL)return0;intleft=height(T->lchild);intright=height(T->rchild);return(left>right?left:right)+1;}voidprintPath(BiTreeT,char*path,intdepth){if(T==NULL)return;path[depth]=T->data;if(T->lchild==NULL&&T->rchild==NULL){for(inti=0;i<=depth;i++)printf("%c",path[i]);printf("\n");return;}printPath(T->lchild,path,depth+1);printPath(T->rchild,path,depth+1);}voidlongestRootToLeaf(BiTreeT){inth=height(T);char*path=(char*)malloc(h*sizeof(char));printPath(T,path,0);free(path);}(8)输出每个叶子到根的路径voidprintPathToRoot(BiTreeT,char*path,intdepth){if(T==NULL)return;path[depth]=T->data;if(T->lchild==NULL&&T->rchild==NULL){for(inti=depth;i>=0;i--)printf("%c",path[i]);printf("\n");return;}printPathToRoot(T->lchild,path,depth+1);printPathToRoot(T->rchild,path,depth+1);}voidallLeafToRootPaths(BiTreeT){charpath[100];printPathToRoot(T,path,0);}习题六1.选择题(1)在一个无向图中,所有顶点的度数之和等于图的边数的(C)倍。A.1/2B.1C.2D.4(2).在一个有向图中,所有顶点的入度之和等于所有顶点的出度之和的(B)倍。A.1/2B.1C.2D.4(3).具有w个顶点的有向图最多有(B)条边。A.nB.n(n-1)C.n(n-1)D.n2(4).G是一个非连通无向图,共有28条边,则该图至少有(C)个顶点。A.7B.8C.9D.10(5).若从无向图的任意一个顶点出发进行一次深度优先搜索可以访问图中所有的顶点,则该图一定是(B)图。A.非连通B.连通C.强连通D.有向(6).下面(A)适合构造一个稠密图G的最小生成树。A.Prim算法B.Kruskal算法C.Floyd算法D.Dykstra算法(7).用邻接表表示图进行广度优先遍历时,通常可借助(B)来实现算法。A.栈B.队列C.树D.图(8).用邻接表表示图进行深度优先遍历时,通常可借助(A)来实现算法。A.栈B.队列C.树D.图2应用题(1)已知图6.31所示的有向图,请给出:①每个顶点的入度和出度;②邻接矩阵;③邻接表;④逆邻接表。图6.31有向图图6.32无向网答案:①顶点入度出度130222312413521623答案:②123456100000021001003010001400101151000006110010答案:③1:2:1,43:2,64:3,5,65:16:1,5,2答案:④1:2,5,62:3,63:44:25:4,66:3,42.已知如图6.32所示的无向网,请给出:①邻接矩阵;②邻接表;③最小生成树。答案:①abcdefgha04300000b40559000c35050005d05507654e09070300f00063020g00050206h00540060答案:②a:b,cb:a,c,d,ec:a,b,d,hd:c,b,e,f,g,he:b,d,ff:d,e,
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 独立研究学者绩效评估表
- 企业数据仓库建设方案与实施手册
- 市场营销经理市场调研策略指南
- 年度销售目标达成情况的通报函件7篇范文
- 医疗保健专业人员服务质量KPI绩效考核表
- 关于通知调整供应商地址事宜的函(5篇范文)
- 餐饮业厨师技艺评估绩效评定表
- 会议议程制定与执行标准方案
- 台风来袭企业应对策略预案
- 学会感恩从小做起:感恩教育课件小学主题班会课件
- 2026年湖南省中考语文试题【含答案】
- 2024-2025学年高一下学期7月期末人教版地理试题(必修一+必修二)(原卷版)
- 2026年注册信贷分析师(CCRA)-通关题库附参考答案详解(精练)
- 部编版1-6年级课内古诗及释义
- 教师如何上好一节课培训
- 领导干部报告个人有关事项培训
- 小学语文阅读理解与思维可视化训练课题报告教学研究课题报告001
- 2026年传媒行业招聘考试核心知识点配套练习题含答案
- 女性就业创业培训课件
- 日文客服招聘笔试题目及答案
- 2025年通风管道专业清洗合同协议
评论
0/150
提交评论