数据结构习题答案.docx

上传人:b****6 文档编号:4105938 上传时间:2022-11-27 格式:DOCX 页数:27 大小:666.30KB
下载 相关 举报
数据结构习题答案.docx_第1页
第1页 / 共27页
数据结构习题答案.docx_第2页
第2页 / 共27页
数据结构习题答案.docx_第3页
第3页 / 共27页
数据结构习题答案.docx_第4页
第4页 / 共27页
数据结构习题答案.docx_第5页
第5页 / 共27页
点击查看更多>>
下载资源
资源描述

数据结构习题答案.docx

《数据结构习题答案.docx》由会员分享,可在线阅读,更多相关《数据结构习题答案.docx(27页珍藏版)》请在冰豆网上搜索。

数据结构习题答案.docx

数据结构习题答案

计算机科学与工程学院

二OO五年三月

目录

第一章绪论3

第二章线性表5

第三章栈和队列9

第三章串10

第五章数组与广义表12

第六章树和二叉树14

第七章图18

第八章查找22

第九章内部排序24

第一章绪论

1.2.3综合题14、

设n为正整数。

试确定下列各程序段中前置以记号@的语句的频度:

(1)i=1;k=0;

While(i<=n-1){

@k+=10*I;

i++;

}

答:

n-1

(2)i=1;k=0;

do{

@k+=10*I;

i++;

}while(I<=n-1);

答:

n-1

(3)i=1;k=0;

While(i<=n-1){

i++;

@k+=10*i;

}

答:

n-1

(4)k=0;

for(i=1;i<=n;i++){

for(j=i;j<=n;j++)

@k++;

}

答:

(n+1)*n/2

(5)for(i=1;i<=n;i++){

for(j=i;j<=n;j++){

for(k=1;k<=j;k++)

@x+=delta;

}

答:

1/6*n*(n+1)*(n+2)

(6)i=1;j=0;

While(i+j<=n){

@if(i>j)j++;

elsei++;

}

答:

n

(7)x=n;y=o;

while(x>=(y+1)*(y+1)){

@y++;

}

答:

⎣√n⎦

(8)x=91;y=100;

while(y>0){

@if(x>100){x-=10;y--;}

elsex++;

}

答:

1100

 

1.2.3综合题20、

voidprint_descending(intx,inty,intz)//按从大到小顺序输出三个数

{

scanf("%d,%d,%d",&x,&y,&z);

if(xy;//<->为表示交换的双目运算符,以下同

if(yz;

if(xy;//冒泡排序

printf("%d%d%d",x,y,z);

}//print_descending

 

1.2.3综合题22

试编写算法,计算i!

.2i的值并存入数组a[0…arrsize-1]的第i-1个分量中(I=1,2,….,n)。

假设计算机中允许的整数最大值为maxint,则当n>arrsize或对某个k(1≤k≤n)使k!

.2k>maxint时,应按出错处理,注意选择你认为较好的出错处理方法。

解:

Statusalgo119(inta[ARRSIZE])//求i!

*2^i序列的值且不超过maxint

{

  last=1;

  for(i=1;i<=ARRSIZE;i++)

  {

a[i-1]=last*2*i;

  if((a[i-1]/last)!

=(2*i))reurnOVERFLOW;

  last=a[i-1];

  returnOK;

  }

}//algo119

分析:

当某一项的结果超过了maxint时,它除以前面一项的商会发生异常.

第二章线性表

作业:

2.2.2综合题3、

编写一个函数将一个向量A(有n个元素且任何元素均不为0)分拆成两个向量,使A中大于0的元素存放在B中,小于0的元素存放在C中。

解:

本题的算法思想是:

依次遍历A的元素,比较当前的元素值,大于0者赋给B(假设有p个元素),小于0者赋给C(假设有q个元素)。

实现本题功能的函数如下:

voidret(vectorA,intn,vectorB,int*p,vectorC,int*q)

{inti;

*p=0;*q=0;

for(i=0;i<=n-1;i++)

{if(A[i]>0)

{(*p)++;

B[*p]=A[i];

}

if(A[i]<0)

{(*q)++;

C[*q]=A[i];

}

}

}

2.2.2综合题5、

编写一个函数从一给定的向量A中删除元素值在x到y(x≤y)之间的所有元素,要求以较高的效率来实现。

解:

本题的算法思想是:

从0开始扫描向量A,以k记录下元素值在x到y之间的元素个数,对于不满足该条件的元素,前移k个位置。

最后返回向量的新长度,这种算法比每删除一个元素后立即移动其后元素效率要高一些。

实现本题功能的过程如下:

intdel(A,n,x,y)

vectorA;

intn;

ElemTypex,y;

{inti=0,k=0;

while(i

{if(A[i]>=x&&A[i]<=y)k++;

elseA[i-k]=A[i];/*前移k个位置*/

i++;

}

return(n-k);

}

 

2.2.2综合题8、

有两个向量A(有m个元素)和B(有n个元素),其元素均以从小到大的升序排列,编写一个函数将它们合并成一个向量C,要求C的元素也是以从小到大的升序排列。

解:

本题的算法思想是:

依次扫描通过A和B的元素,比较当前的元素的值,将较小值的元素赋给C,如此直到一个向量扫描完毕,然后将未完的一个向量的余下所有元素赋给C即可。

实现本题功能的函数如下:

intlink(vectora,intm,vectorb,intn,vectorc)

{inti=0,j=0,l,k=0;

while(i

{if(a[i]

elseif(a[i]>b[j])c[k++]=b[j++];

else

{/*相等者只保存一个*/

c[k++]=b[j++];

i++;

}

}

if(i==m)/*b未完时,当余下的元素赋给c*/

for(l=j;l

c[k++]=b[l];

if(j==n)/*a未完时,当余下的元素赋给c*/for(l=i;i

c[k++]=a[l];

returnk;/*返回c的长度*/

}

2.2.2综合题9、

有一个单链表(不同结点的数据域值可能相同),其头指针为head,编写一个函数计算数据域为x的结点个数。

解:

本题是遍历通过该链表的每个结点,每遇到一个结点,结点个数加1,结点个数存储在变量n中。

实现本题功能的函数如下:

intcount(head,x)

node*head;

ElemTypex;

{

node*p;

intn=0;

p=head;

while(p!

=NULL)

{

if(p->data==x)n++;

p=p->next;

}

return(n);

}

2.2.2综合题11、

有一个单链表L(至少有1个结点),其头结点指针为head,编写一个函数将L逆置,即最后一个结点变成第一个结点,原来倒数第二个结点变成第二个结点,如此等等。

解:

本题采用的算法是:

从头到尾扫描单链表L,将第一个结点的next域置为NULL,

将第二个结点的next域指向第一个结点,将第三个结点的next域指向第二个结点,如此等等,直到最后一个结点,便用head指向它,这样达到了本题的要求。

实现本题功能的函数如下:

voidinvert(head)

node*head;

{

node*p,*q,*r;

p=head;

q=p->next;

while(q!

=NULL)/*当L没有后续结点时终止*/

{r=q->next;

q->next=p;

p=q;

q=r;

}head->next=NULL;

head=p;/*p指向L的最后一个结点,现改为头结点*/

}

2.2.2综合题16、

有一个有序单链表(从小到大排列),表头指针为head,编写一个函数向该单链表中插入一个元素为x的结点,使插入后该链表仍然有序。

解:

本题算法的思想是先建立一个待插入的结点,然后依次与链表中的各结点的数据域比较大小,找到插入该结点的位置,最后插入该结点。

实现本题功能的函数如下:

node*insertorder(head,x)

node*head;ElemTypex;

{

node*s,*p,*q;

s=(node*)malloc(sizeof(node));/*建立一个待插入的结点*/

s->data=x;

s->next=NULL;

if(head==NULL||xdata)/*若单链表为空或x小于第一个结点的date域*/

{

s->next=head;/*则把s结点插入到表头后面*/

head=s;

}

else

{q=head;/*为s结点寻找插入位置,p指向待比较的结点,q指向p的前驱结点*/

p=q->next;

while(p!

=NULL&&x>p->data)/*若x小于p所指结点的data域值*/

if(x>p->data)/*则退出while循环*/

{

q=p;

p=p->next;

}

s->next=p;/*将s结点插入到q和p之间*/

q->next=s;

}

return(head);

}

2.2.2综合题23、

假设在长度大于1的循环单链表中,既无头结点也无头指针,p为指向该链表中某个结点的指针,编写一个函数删除该结点的前驱结点。

解:

本题利用循环单链表的特点,通过p指针可循环找到其前驱结点q及q的前驱结点r,然后将其删除。

实现本题功能的函数如下:

node*del(p)

node*p;

{

node*q,*r;

q=p;/*查找p结点的前驱结点,用q指针指向*/

while(q->next!

=p)q=q->next;

r=q;/*查找q结点的前驱结点,用r指针指向*/

while(r->next!

=q)r=r->next;

r->next=p;/*删除q所指的结点*/

free(q);

return(p);

}

2.2.2综合题41

试写一算法在带头结点的单链表结构上的实现线性表操作LOCATE(L,X)。

LNode*Locate(LinkListL,intx)//链表上的元素查找,返回指针

{

  for(p=l->next;p&&p->data!

=x;p=p->next);

  returnp;

}//Locate

第三章栈和队列

3.2.2综合习题13、

如果用一个循环数组qu[0,m0-1]表示队列时,该队列只有一个头指针front,不设队尾指针rear,而改置计数器count用以记录队列中结点的个数。

(1)编写实现队列的五个基本运算;

(2)队列中能容纳元素的最多个数还是m0-1吗?

解:

(1)依题意,有如下条件:

队列为空:

count==0,front==1

队列为满:

count==m0

队列尾的第一个元素位置==(front+count)%m0

队列首的第一个元素位置==(front+1)%m0

队列类型定义如下:

typedefintqu[m0];

由此得到如下对应上述基本运算的5个函数如下:

/*m0定义为全局变量*/

voidmakenull(front,count)/*使队列q为空*/

intfront,count;

{front=1;count=0;}

intempty(count)/*判定队列q是否为空*/

intcount;

{if(count==0)return

(1);elsereturn(0);}

voidpop(q,front,count,x)/*取队列头元素给x*/

quq;

intfront,count;

ElemType*x;

{

if(count==0)printf("队列下溢出\n");

else

{front=(front+1)%m0;*x=q[front];}

}

voidenqueue(q,x,front,count)/*将元素x入队列*/

quq;

intfront,count;

ElemTypex;

{intplace;

if(count==m0)printf("队列上溢出\n");

else

{count++;e=(front+count)%m0;q[place]=x;}

}

voiddequeue(q,front,count)/*删除队列头元素*/

quq;

intfront,count;

{

if(count==0)printf("队列下溢出\n");

else

{front=(front+1)%m0;count--;}

}

(2)队列中可容纳的最多元素个数为m0个。

3.2.2综合习题31

假设称正读和反读都相同的字符序列为“回文”,例如,‘abba’和‘abcba’是回文,‘bcde’和‘ababa’则不是回文,试写一个算法判别读入的一个以‘@’为结束符的字符序列是否是“回文”。

intPalindrome_Test()//判别输入的字符串是否回文序列,是则返回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;

}//Palindrome_Test

第三章串

4.2.3综合习题2、

若x和y是两个采用顺序结构存储的串,编写一个比较两个串是否相等的函数。

解:

两个串相等表示对应的字符必须都相同,所以扫描两串,逐一比较相应位置的字符,若相同继续比较直到全部比较完毕,如果都相同则表示两串相等,否则表示两串不相等,由此得到如下函数:

intsame(x,y)

orderstring*x,*y;

{

inti=0,tag=1;

if(x->len!

=y->len)

return(0);

else

{

while(ilen&&tag)

{

if(x->vec[i]!

=y->vec[i])tag=0;

i++;

}

return(tag);

}

}

4.2.3综合习题4、

采用顺序结构存储串s,编写一个函数删除s中第i个字符开始的j个字符。

解:

本题的算法思想是:

先判定s串中要删除的内容是否存在,若存在则将第i+j-1之后的字符前移j个位置。

其函数如下:

orderstring*delij(s,i,j)

orderstring*s;

inti,j;

{

inth;

if(i+jlen)

{

for(h=i;h

s->vec[h]=s->vec[h+j];

s->len-=j;

return(s);

}

elseprintf("无法进行删除操作\n");

}

4.2.3综合习题24、

编写算法,求串s所含不同字符的总数和每种字符的个数。

typedefstruct{

                charch;

                intnum;

              }mytype;

voidStrAnalyze(StringtypeS)//统计串S中字符的种类和个数

{

  mytypeT[MAXSIZE];//用结构数组T存储统计结果

  for(i=1;i<=S[0];i++)

  {

    c=S[i];j=0;

    while(T[j].ch&&T[j].ch!

=c)j++;//查找当前字符c是否已记录过

    if(T[j].ch)T[j].num++;

    elseT[j]={c,1};

  }//for

  for(j=0;T[j].ch;j++)

    printf("%c:

  %d\n",T[j].ch,T[j].num);

}//StrAnalyze

4.2.3综合习题30

试写一算法,在串的堆存储结构上实现基本操作Concat(&T,s1.s2).

voidHString_Concat(HStrings1,HStrings2,HString&t)//将堆结构表示的串s1和s2连接为新串t

{

  if(t.ch)free(t.ch);

  t.ch=malloc((s1.length+s2.length)*sizeof(char));

  for(i=1;i<=s1.length;i++)t.ch[i-1]=s1.ch[i-1];

  for(j=1;j<=s2.length;j++,i++)t.ch[i-1]=s2.ch[j-1];

  t.length=s1.length+s2.length;

}//HString_Concat

第五章数组与广义表

5.2.3综合习题9、

假设稀疏矩阵A和B(具有相同的大小m×n)都采用三元组表示,编写一个函数计算C=A+B,要求C也采用三元组表示。

解:

本题采用的算法思想是:

依次扫描A和B的行号和列号,若A的当前项的行号等于B的当前项的行号,则比较其列号,将较小列的项存入C中,如果列号也相等,则将对应的元素值相加后存入C中;若A的当前项的行号小于B的当前项的行号,则将A的项存入C中;若A的当前项的行号大于B的当前项的行号,则将B的项存入C中。

这样产生了C,因此,实现本题功能的函数如下:

voidmatadd(A,B,C)

smatrikA,B,C;

{

inti=1,j=1,k=1;

while(i<=A[0][2]&&j<=B[0][2])

/*若A的当前项的行号等于B的当前项的行号,则比较其列号,将较小列的项*/

/*存入C中,如果列号也相等,则将对应的元素值相加后存入C中*/

if(A[i][0]==B[j][0])

if(A[i][1]

{

C[k][0]=A[i][0];

C[k][1]=A[i][1];

C[k][2]=A[i][2];

k++;

i++;

}

elseif(A[i][1]>B[j][1])

{

C[k][0]=B[j][0];

C[k][1]=B[j][1];

C[k][2]=B[j][2];

k++;

j++;

}

else

{

C[k][0]=B[j][0];

C[k][1]=B[j][1];

C[k][2]=A[i][2]+B[j][2];

if(C[k][2]!

=0)k++;

i++;

j++;

}

elseif(A[i][0]

/*若A的当前项的行号小于B的当前项的行号,则将A的项存入C中*/

{

C[k][0]=A[i][0];

C[k][1]=A[i][1];

C[k][2]=A[i][2];

k++;

i++;

}

else/*若A的当前项的行号大于B的当前项的行号,则将B的项存入C中*/

{

C[k][0]=B[j][0];

C[k][1]=B[j][1];

C[k][2]=B[j][2];

k++;

j++;

}

C[0][0]=A[0][0];/*产生第0行的结果*/

C[0][1]=A[0][1];

C[0][2]=k-1;

}

5.2.3综合习题26

试设计一个算法,将数组An中的元素A[0]至A[n-1]循环右移k位,并要求只用一个元素大小的附加存储,元素移动或交换次数为O(n)。

voidRSh(intA[n],intk)//把数组A的元素循环右移k位,只用一个辅助存储空间

{

  for(i=1;i<=k;i++)

    if(n%i==0&&k%i==0)p=i;//求n和k的最大公约数p

  for(i=0;i

  {

    j=i;l=(i+k)%n;temp=A[i];

    while(l!

=i)

    {

      A[j]=temp;

      temp=A[l];

      A[l]=A[j];

      j=l;l=(j+k)%n;

    }//循环右移一步

    A[i]=temp;

  }//for

}//RSh

分析:

要把A的元素循环右移k位,则A[0]移至A[k],A[k]移至A[2k]......直到最终回到A[0].然而这并没有全部解决问题,因为有可能有的元素在此过程中始终没有被访问过,而是被跳了过去.分析可知,当n和k的最大公约数为p时,只要分别以A[0],A[1],...A[p-1]为起点执行上述算法,就可以保证每一个元素都被且仅被右移一次,从而满足题目要求.也就是说,A的所有元素分别处在p个"循环链"上面.举例如下:

n=15,k=6,则p=3.

第一条链:

A[0]->A[6],A[6]->A[12],A[12]->A[3],A[3]->A[9],A[9]->A[0].

第二条链:

A[1]->A[7],A[7]->A[13],A[13]->A[4],A[4]->A[10],A[10]->A[1].

第三条链:

A[2]->A[8],A[8]->A[14],A[14]->A[5],A[5]->A[11],A[11]->

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 初中教育 > 政史地

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1