数据结构算法与应用c语言描述答案.docx

上传人:b****8 文档编号:10488539 上传时间:2023-02-13 格式:DOCX 页数:22 大小:24.03KB
下载 相关 举报
数据结构算法与应用c语言描述答案.docx_第1页
第1页 / 共22页
数据结构算法与应用c语言描述答案.docx_第2页
第2页 / 共22页
数据结构算法与应用c语言描述答案.docx_第3页
第3页 / 共22页
数据结构算法与应用c语言描述答案.docx_第4页
第4页 / 共22页
数据结构算法与应用c语言描述答案.docx_第5页
第5页 / 共22页
点击查看更多>>
下载资源
资源描述

数据结构算法与应用c语言描述答案.docx

《数据结构算法与应用c语言描述答案.docx》由会员分享,可在线阅读,更多相关《数据结构算法与应用c语言描述答案.docx(22页珍藏版)》请在冰豆网上搜索。

数据结构算法与应用c语言描述答案.docx

数据结构算法与应用c语言描述答案

数据结构算法与应用——c语言描述答案

【篇一:

《数据结构——用c语言描述》+课后题答案】

book/read/data-structure/h971111102.html

习题解答(唐策善版)(其他版本在上面)

第一章绪论(参考答案)

1.3

(1)o(n)

(2)

(2)o(n)

(3)(3)o(n)

(4)(4)o(n1/2)

(5)(5)执行程序段的过程中,x,y值变化如下:

循环次数xy

0(初始)91100

192100

293100

?

?

?

?

?

?

9100100

10101100

119199

1292100

?

?

?

?

?

?

2010199

219198

?

?

?

?

?

?

3010198

319197

到y=0时,要执行10*100次,可记为o(10*y)=o

(1)

1.52100,(2/3)n,logn2n,n1/2,n3/2,(3/2)n,nlogn2,2,n!

第二章线性表(参考答案)

在以下习题解答中,假定使用如下类型定义:

(1)顺序存储结构:

#definemaxsize1024

typedefintelemtype;//实际上,elemtype可以是任意类型

typedefstruct

{elemtypedata[maxsize];

intlast;//last表示终端结点在向量中的位置

}sequenlist;

(2)链式存储结构(单链表)

typedefstructnode

{elemtypedata;

structnode*next;

}linklist;

(3)链式存储结构(双链表)

typedefstructnode

{elemtypedata;

structnode*prior,*next;

nn

}dlinklist;

(4)静态链表

typedefstruct

{elemtypedata;

intnext;

}node;

nodesa[maxsize];

2.1头指针:

指向链表的指针。

因为对链表的所有操均需从头指针开始,即头指针具有标识链表的作用,所以链表的名字往往用头指针来标识。

如:

链表的头指针是la,往往简称为“链表la”。

头结点:

为了链表操作统一,在链表第一元素结点(称为首元结点,或首结点)之前增加的一个结点,该结点称为头结点,其数据域不无实际意义(当然,也可以存储链表长度,这只是副产品),其指针域指向头结点。

这样在插入和删除中头结点不变。

开始结点:

即上面所讲第一个元素的结点。

2.2只设尾指针的单循环链表,从尾指针出发能访问链表上的任何结点。

voidinsert(elemtypea[],intelenum,elemtypex)

//向量a目前有elenum个元素,且递增有序,本算法将x插入到向量a中,并保持向量的递增有序。

{inti=0,j;

while(ielenuma[i]=x)i++;//查找插入位置

for(j=elenum-1;j=i;j--)a[j+1]=a[j];//向后移动元素

a[i]=x;//插入元素

}//算法结束

voidrightrotate(elemtypea[],intn,k)

//以向量作存储结构,本算法将向量中的n个元素循环右移k位,且只用一个辅助空间。

{intnum=0;//计数,最终应等于n

intstart=0;//记录开始位置(下标)

while(numn)

{temp=a[start];//暂存起点元素值,temp与向量中元素类型相同

empty=start;//保存空位置下标

next=(start-k+n)%n;//计算下一右移元素的下标

while(next!

=start)

{a[empty]=a[next];//右移

num++;//右移元素数加1

empty=next;

next=(next-k+n)%n;//计算新右移元素的下标

}

a[empty]=temp;//把一轮右移中最后一个元素放到合适位置

num++;

start++;//起点增1,若numn则开始下一轮右移。

}

}//算法结束

算法二

算法思想:

先将左面n-k个元素逆置,接着将右面k个元素逆置,最后再将这n个元素逆置。

voidrightrotate(elemtypea[],intn,k)

//以向量作存储结构,本算法将向量中的n个元素循环右移k位,且只用一个辅助空间。

{elemtypetemp;

for(i=0;i(n-k)/2;i++)//左面n-k个元素逆置

{temp=a[i];a[i]=a[n-k-1-i];a[n-k-1-i]=temp;}

for(i=1;i=k;i++)//右面k个元素逆置

{temp=a[n-k-i];a[n-k-i]=a[n-i];a[n-i]=temp;}

for(i=0;in/2;i++)//全部n个元素逆置

{temp=a[i];a[i]=a[n-1-i];a[n-1-i]=temp;}

}//算法结束

voidinsert(linklist*l,elemtypex)

//带头结点的单链表l递增有序,本算法将x插入到链表中,并保持链表的递增有序。

{linklist*p=l-next,*pre=l,*s;

//p为工作指针,指向当前元素,pre为前驱指针,指向当前元素的前驱

s=(linklist*)malloc(sizeof(linklist));//申请空间,不判断溢出

s-data=x;

while(pp-data=x){pre=p;p=p-next;}//查找插入位置

pre-next=s;s-next=p;//插入元素

}//算法结束

voidinvert(linklist*l)

//本算法将带头结点的单链表l逆置。

//算法思想是先将头结点从表上摘下,然后从第一个元素结点开始,依次前插入以l为头结点的链表中。

{linklist*p=l-next,*s;

//p为工作指针,指向当前元素,s为p的后继指针

l-next=null;//头结点摘下,指针域置空。

算法中头指针l始终不变

while(p)

{s=p-next;//保留后继结点的指针

p-next=l-next;//逆置

l-next=p;

p=s;//将p指向下个待逆置结点

}

}//算法结束

(1)intlength1(linklist*l)

//本算法计算带头结点的单链表l的长度

{linklist*p=l-next;inti=0;

//p为工作指针,指向当前元素,i表示链表的长度

while(p)

{i++;p=p-next;}

return(i);

}//算法结束

(2)intlength1(nodesa[maxsize])

//本算法计算静态链表s中元素的个数。

{intp=sa[0].next,i=0;

//p为工作指针,指向当前元素,i表示元素的个数,静态链指针等于-1时链表结束while(p!

=-1)

{i++;p=sa[p].next;}

return(i);

}//算法结束

voidunion_invert(linklist*a,*b,*c)

//a和b是两个带头结点的递增有序的单链表,本算法将两表合并成

//一个带头结点的递减有序单链表c,利用原表空间。

{linklist*pa=a-next,*pb=b-next,*c=a,*r;

//pa,pb为工作指针,分别指向a表和b表的当前元素,r为当前逆置

//元素的后继指针,使逆置元素的表避免断开。

//算法思想是边合并边逆置,使递增有序的单链表合并为递减有序的单链表。

c-next=null;//头结点摘下,指针域置空。

算法中头指针c始终不变

while(papb)//两表均不空时作

if(pa-data=pb-data)//将a表中元素合并且逆置

{r=pa-next;//保留后继结点的指针

pa-next=c-next;//逆置

c-next=pa;

pa=r;//恢复待逆置结点的指针

}

else//将b表中元素合并且逆置

{r=pb-next;//保留后继结点的指针

pb-next=c-next;//逆置

c-next=pb;

pb=r;//恢复待逆置结点的指针

}

//以下while(pa)和while(pb)语句,只执行一个

while(pa)//将a表中剩余元素逆置

{r=pa-next;//保留后继结点的指针

pa-next=c-next;//逆置

c-next=pa;

pa=r;//恢复待逆置结点的指针

}

while(pb)//将b表中剩余元素逆置

{r=pb-next;//保留后继结点的指针

pb-next=c-next;//逆置

c-next=pb;

pb=r;//恢复待逆置结点的指针

}

free(b);//释放b表头结点

}//算法结束

voiddeleteprior(linklist*l)

//长度大于1的单循环链表,既无头结点,也无头指针,本算法删除*s的前驱结点{linklist*p=s-next,*pre=s;//p为工作指针,指向当前元素,

//pre为前驱指针,指向当前元素*p的前驱

while(p-next!

=s){pre=p;p=p-next;}//查找*s的前驱

pre-next=s;

free(p);//删除元素

}//算法结束

voidone_to_three(linklist*a,*b,*c)

//a是带头结点的的单链表,其数据元素是字符字母、字符、数字字符、其他字符。

本算法//将a表分成

//三个带头结点的循环单链表a、b和c,分别含有字母、数字和其它符号的同一类字符,利用原表空间。

{linklist*p=a-next,r;

//p为工作指针,指向a表的当前元素,r为当前元素的后继指针,使表避免断开。

//算法思想是取出当前元素,根据是字母、数字或其它符号,分别插入相应表中。

b=(linklist*)malloc(sizeof(linklist));//申请空间,不判断溢出

b-next=null;//准备循环链表的头结点

c=(linklist*)malloc(sizeof(linklist));//申请空间,不判断溢出

c-next=null;//准备循环链表的头结点

while(p)

{r=p-next;//用以记住后继结点

if(p-data=’a’p-data=’z’||p-data=’a’p-data=’z’)

{p-next=a-next;a-next=p;}//将字母字符插入a表

elseif(p-data=’0’p-data=’9’)

{p-next=b-next;b-next=p;}//将数字字符插入b表

else{p-next=c-next;c-next=p;}//将其它符号插入c表

p=r;//恢复后继结点的指针

}//while

}//算法结束

voidlocate(dlinklist*l)

//l是带头结点的按访问频度递减的双向链表,本算法先查找数据x,

//查找成功时结点的访问频度域增1,最后将该结点按频度递减插入链表中适当位置。

{linklist*p=l-next,*q;

//p为工作指针,指向l表的当前元素,q为p的前驱,用于查找插入位置。

while(pp-data!

=x)p=p-next;//查找值为x的结点。

if(!

p)return(“不存在值为x的结点”);

else{p-freq++;//令元素值为x的结点的freq域加1。

p-next-prir=p-prior;//将p结点从链表上摘下。

p-prior-next=p-next;

q=p-prior;//以下查找p结点的插入位置

while(q!

=lq-freqp-freq)q=q-prior;

p-next=q-next;q-next-prior=p;//将p结点插入

p-prior=q;q-next=p;

}

}//算法结束

第三章栈和队列(参考答案)

//从数据结构角度看,栈和队列是操作受限的线性结构,其顺序存储结构

//和链式存储结构的定义与线性表相同,请参考教材,这里不再重复。

3.11234213432144321

124321433241

132423143421

13422341

14322431

设入栈序列元素数为n,则可能的出栈序列数为c2nn=(1/n+1)*(2n!

/(n!

)2)

3.2证明:

由jk和pjpk说明pj在pk之前出栈,即在k未进栈之前pj已出栈,之后k进栈,

然后pk出栈;由jk和pjpk说明pj在pk之后出栈,即pj被pk压在下面,后进先出。

【篇二:

《数据结构——c语言描述》习题及答案耿国华】

一、问答题

1.什么是数据结构?

2.四类基本数据结构的名称与含义。

3.算法的定义与特性。

4.算法的时间复杂度。

5.数据类型的概念。

6.线性结构与非线性结构的差别。

7.面向对象程序设计语言的特点。

8.在面向对象程序设计中,类的作用是什么?

9.参数传递的主要方式及特点。

10.抽象数据类型的概念。

二、判断题

1.线性结构只能用顺序结构来存放,非线性结构只能用非顺序结构来存放。

2.算法就是程序。

3.在高级语言(如c、或pascal)中,指针类型是原子类型。

三、计算下列程序段中x=x+1的语句频度

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

for(j=1;j=i;j++)

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

x=x+1;

[提示]:

f(n)=[(1+2+3+……+n)+(12+22+32+……+n2)]/2

=[(1+n)n/2+n(n+1)(2n+1)/6]/2

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

=n3/6+n2/2+n/3

区分语句频度和算法复杂度:

o(f(n))=o(n3)

四、试编写算法求一元多项式pn(x)=a0+a1x+a2x2+a3x3+…anxn的值pn(x0),并确定算法中的每一语句的执行次数和整个算法的时间复杂度,要求时间复杂度尽可能的小,规定算法中不能使用求幂函数。

注意:

本题中的输入ai(i=0,1,…,n),x和n,输出为pn(x0).通常算法的输入和输出可采用下列两种方式之一:

(1)通过参数表中的参数显式传递;

(2)通过全局变量隐式传递。

试讨论这两种方法的优缺点,并在本题算法中以你认为较好的一种方式实现输入和输出。

[提示]:

floatpolyvalue(floata[],floatx,intn){……}

核心语句:

p=1;(x的零次幂)

s=0;

i从0到n循环

s=s+a[i]*p;

p=p*x;

或:

p=x;(x的一次幂)

s=a[0];

i从1到n循环

s=s+a[i]*p;

p=p*x;

实习题

设计实现抽象数据类型“有理数”。

基本操作包括有理数的加法、减法、乘法、除法,以及求有理数的分子、分母。

第一章答案

1.3计算下列程序中x=x+1的语句频度

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

for(j=1;j=i;j++)

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

x=x+1;

【解答】x=x+1的语句频度为:

t(n)=1+(1+2)+(1+2+3)+……+(1+2+……+n)=n(n+1)(n+2)/6

1.4试编写算法,求pn(x)=a0+a1x+a2x2+…….+anxn的值pn(x0),并确定算法中每一语句的执行次数和整个算法的时间复杂度,要求时间复杂度尽可能小,规定算法中不能使用求幂函数。

注意:

本题中的输入为ai(i=0,1,…n)、x和n,输出为pn(x0)。

算法的输入和输出采用下列方法

(1)通过参数表中的参数显式传递

(2)通过全局变量隐式传递。

讨论两种方法的优缺点,并在算法中以你认为较好的一种实现输入输出。

【解答】

(1)通过参数表中的参数显式传递

优点:

当没有调用函数时,不占用内存,调用结束后形参被释放,实参维持,函数通

用性强,移置性强。

缺点:

形参须与实参对应,且返回值数量有限。

(2)通过全局变量隐式传递

优点:

减少实参与形参的个数,从而减少内存空间以及传递数据时的时间消耗

缺点:

函数通用性降低,移植性差

算法如下:

通过全局变量隐式传递参数

polyvalue()

{inti,n;

floatx,a[],p;

printf(“\nn=”);

scanf(“%f”,n);

printf(“\nx=”);

scanf(“%f”,x);

for(i=0;in;i++)

scanf(“%f”,a[i]);/*执行次数:

n次*/

p=a[0];

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

{p=p+a[i]*x;/*执行次数:

n次*/

x=x*x;}

printf(“%f”,p);

}

算法的时间复杂度:

t(n)=o(n)

通过参数表中的参数显式传递

floatpolyvalue(floata[],floatx,intn)

{

floatp,s;

inti;

p=x;

s=a[0];

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

{s=s+a[i]*p;/*执行次数:

n次*/

p=p*x;}

return(p);

}

算法的时间复杂度:

t(n)=o(n)

第2章线性表

习题

2.1

2.2描述以下三个概念的区别:

头指针,头结点,首元素结点。

填空:

(1)在顺序表中插入或删除一个元素,需要平均移动__一半__元素,具体移动的元

素个数与__插入或删除的位置__有关。

(2)在顺序表中,逻辑上相邻的元素,其物理位置______相邻。

在单链表中,逻

辑上相邻的元素,其物理位置______相邻。

(3)在带头结点的非空单链表中,头结点的存储位置由______指示,首元素结点

的存储位置由______指示,除首元素结点外,其它任一元素结点的存储位置由__其直接前趋的next域__指示。

2.3已知l是无表头结点的单链表,且p结点既不是首元素结点,也不是尾元素结点。

按要求从下列语句中选择合适的语句序列。

a.在p结点后插入s结点的语句序列是:

b.在p结点前插入s结点的语句序列是:

c.在表首插入s结点的语句序列是:

d.在表尾插入s结点的语句序列是:

供选择的语句有:

(1)p-next=s;

(2)p-next=p-next-next;

(3)p-next=s-next;

(4)s-next=p-next;

(5)s-next=l;

(6)s-next=null;

(7)q=p;

(8)while(p-next!

=q)p=p-next;

(9)while(p-next!

=null)p=p-next;

(10)p=q;

(11)p=l;

(12)l=

s;

(13)l=p;

2.4已知线性表l递增有序。

试写一算法,将x插入到l的适当位置上,以保持线性表l的有序性。

[提示]:

voidinsert(seqlist*l;elemtypex)

方法1

(1)找出应插入位置i,

(2)移位,(3)?

?

方法2参p.229

2.5写一算法,从顺序表中删除自第i个元素开始的k个元素。

[提示]:

注意检查i和k的合法性。

(集体搬迁,“新房”、“旧房”)

方法1以待移动元素下标m(“旧房号”)为中心,

计算应移入位置(“新房号”):

for(m=i-1+k;m=l-last;m++)

l-elem[m-k]=l-elem[m];

方法2同时以待移动元素下标m和应移入位置j为中心:

方法3以应移入位置j为中心,计算待移动元素下标:

【篇三:

唐策善数据结构答案-用c语言描述原版】

txt>2.1头指针:

指向链表的指针。

因为对链表的所有操均需从头指针开始,即头指针具有标识链表的作用,所以链表的名字往往用头指针来标识。

如:

链表的头指针是la,往往简称为“链表la”。

头结点:

为了链表操作统一,在链表第一元素结点(称为首元结点,或首结点)之前增加的一个结点,该结点称为头结点,其数据域不无实际意义(当然,也可以存储链表长度,这只是副产品),其指针域指向头结点。

这样在插入和删除中头结点不变。

开始结点:

即上面所讲第一个元素的结点。

2.2只设尾指针的单循环链表,从尾指针出发能访问链表上的任何结点。

voidinsert(elemtypea[],intelenum,elemtypex)

//向量a目前有elenum个元素,且递增有序,本算法将x插入到向量a中,并保持向量的递增有序。

{inti=0,j;

while(ielenuma[i]=x)i++;//查找插入位置for(j=elenum-1;j=i;j--)a[j+1]=a[j];//向后移动元素a[i]=x;//插入元素

}//算法结束

voidrightrotate(elemtypea[],intn,k)

//以向量作存储结构,本算法将向量中的n个元素循环右移k位,且只用一个辅助空间。

{intnum=0;//计数,最终应等于nintstart=0;//记录开始位置(下标)while(numn)

{temp=a[start];//暂存起点元素值,temp与向量中元素类型相同

empty=start;//保存空位置下标

next=(start

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

当前位置:首页 > 农林牧渔 > 林学

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

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