数据结构实用教程(第三版)课后答案
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
数据结构实用教程( 第三版) 课后答案
file:///D|/ ------------------ 上架商品---------------------- / 数据结构实用教程( 第三版)
课后答案(徐孝凯著)清华大学/第一章绪论.txt
第一章绪习题一
一、单选题
1. 一个数组元数a[i] 与( A ) 的表示等价。
A *(a+i)
B a+i
C *a+i
D &a+i
2. 对于两个函数,若函数名相同,但只是( C) 不同则不是重载函数。
A 参数类型
B 参数个数
C 函数类型
3. 若需要利用形参直接访问实参,则应把形参变量说明为(B) 参数。
A 指针
B 引用
C 值
4. 下面程序段的复杂度为(C ) 。
for(int i=0;i<m;i++)
for(int j=0;j<n;j++)
a[i][j]=i*j;
A O(m2)
B O(n2)
C O(m*n)
D O(m+n)
5. 执行下面程序段时,执行S语句的次数为(D )。
for(int i=1;i<=n;i++)
for(int j=1; j<=i;j++)
S;
A n2
B n2/2
C n(n+1)
D n(n+1)/2
6. 下面算法的时间复杂度为( B) 。
int f(unsigned int n){
if(n==0||n==1) return 1;
Else return n*f(n-1);
}
A O(1)
B O(n)
C O(n2)
D O(n!)
二、填空题
1. 数据的逻辑结构被除数分为集合结构、线性结构、树型结构和图形结构四种。
2. 数据的存储结构被分为顺序结构、结构、索引结构和散列结构四种。
3. 在线性结构、树型结构和图形结构中,前驱和后继结点之间分别存在着1 对1 、1 对N 和
M对N的关系。
4. 一种抽象数据类型包括数据和操作两个部分。
5. 当一个形参类型的长度较大时,应最好说明为引用,以节省参数值的传输时间和存储参数的空间。
6. 当需要用一个形参访问对应的实参时,则该形参应说明为引用。
7. 在函数中对引用形参的修改就是对相应实参的修改,对值(或赋值) 形参的修改只局限在该
函数的部,不会反映到对应的实参上。
file:///D|/ ------------------ 上架商品 --- ... 教程( 第二版) 课后答案( 徐孝凯
著)清华大学/第一章绪论.txt (第1 /10页)[2010-3-16 22:06:17]
file:///D|/ ------------------ 上架商品---------------------- / 数据结构实用教程( 第二版)
课后答案(徐孝凯著)清华大学/第一章绪论.txt
8. 当需要进行标准I/O 操作时,则应在程序文件中包含iostream.h 头文件,当需要进行文件I/O 操作时,
则应在程序文件中包含fstream.h 头文件。
9. 在包含有stdlib.h 头文件的程序文件中,使用rand()%21 能够产生0-20 之间的一个随机数。
10. 一个记录r 理论上占有的存储空间的大小等于所有域的长度之和,实际上占有的存储空间的大小即
记录长度为sizeof(r) 。
11. 一个数组a 所占有的存储空间的大小即数组长度为sizeof(a) ,下标为i 的元数a[i] 的存储地址
为a+1 ,
或者为(char*)a+i*sizeof(a[i]) 。
12. 函数重载要求参数类型、参数个数或排列顺序有所不同。
13. 对于双目操作符,其重载函数带有2 个参数,其中至少有一个为用户自定义的类型。
14. 若对象ra 和rb 中至少有一个属于用户定义的类型,则执行ra==rb 时,需要调用等于号(==)
重载函数,该函数第一个参数应与ra ,的类型相同,第二个参数应与rb 的类型相同。
15. 从一维数组a[n] 中顺序查找出一个最大值元素的时间复杂度为O(n) ,输出一个二维数组
b[m][n] 中所有元素值的时间复杂度为O(m*n) 。
16. 在下面程序段中,s=s+p 语句的执行次数为n ,p*=j 语句的执行次数为n(n+1)/2 ,该程序段
的时间复杂度为O(n2) 。
int i=0,s=0;
while(++i<=n){
int p=1;
for(int j=1;j<=i;j++) P*=j;
s=s+p;
}
17. 一个算法的时间复杂度为(3n2+2nlog2n+4n-7)/(5n), 其数量级表示为O(n) 。
18. 从一个数组a[7] 中顺序查找元素时,假定查找第一个元素a[0] 的概率为1/3 ,查找第二个元素
a[1] 的概率为1/4 ,查找其余元素的概率均相同,则在查找成功时同元素的平均比较次数为
35/12 。
三、普通题
1. 有下列几种用二元组表示的数据结构,试画出它们分别对应的图形表示 (当出现多个关系时,
对每个关系画出相应的结构图) ,并指出它们分别属于何种结构。
⑴ A=(K,R) 其中
K={a1,a2,a3...,an}
R={}
⑵ B=(K,R) 其中
file:///D|/ ------------------ 上架商品 --- ... 教程( 第二版) 课后答案( 徐孝凯
著)清华大学/第一章绪论.txt (第2 /10页)[2010-3-16 22:06:17]
file:///D|/ ------------------ 上架商品---------------------- / 数据结构实用教程
(第二版)课后答案(徐孝凯著)清华大学/第一章绪论.txt
K={a,b,c,d,e,f,g,h}
R={r} r={<a,b>,<b,c>,<c,d>,<d,e>,<e,f>,<f,g>,<g,h>}
⑶ C=(K,R) 其中
K={a,b,c,d,f,g,h}
R={r} r={<d,b>,<d,g>,<b,a>,<b,c>,<g,e>,<g,h>,<e,f>}
⑷ D=(K,R) 其中
K={1,2,3,4,5,6}
R={r} r={(1,2),(2,3),(2,4),(3,4),(3,5),(3,6),(4,5),(4,6)}
⑸ E=(K,R) 其中
K={48,25,64,57,82,36,75,43}
R={r1,r2,r3} r1={<48,25>,<25,64>,<64,57>,<57,82>,<82,36>,<36,75>,<75,43>}
r2={<48,25>,<48,64>,<64,57>,<64,82>,<25,36>,<82,75>,<36,43>}
r3={<25,36>,<36,43>,<43,48>,<48,57>,<57,64>,<64,75>,<75,82>}
解:⑴是集合结构;⑵是线性结构;⑶⑷是树型结构;⑸散列结构。
只作为参考。
2. 设计二次多项式ax2+bx+c 的一种抽象数据类型,假定起名为QIAdratic,
该类型的数据部分分为三个系数项a、b和C,操作部分为:(请写出下面每一个
操作的具体实现)。
⑴ 初始化数据成员ab 和C( 假定用记录类型Quadratie 定义成员),每个数据成员的默认值为0。
QuadratiC InitQuadratiC(float aa=0,float bb=0,float CC=0);
解:
QuadratiC InitQuadratiC(float aa,float bb,float CC)
{ QuadratiC q;
q.a=aa;
q.b=bb;
q.C=CC;
return q;
}
⑵ 做两个多项式加法, 即使对应的系数相加, 并返回相加的结果。
QuadratiC Add(QuadratiC q1,QuadratiC q2);
解:
QuadratiC Add(QuadratiC q1,QuadratiC q2);
{
QuadratiC q;
q.a=q1.a+q2.a;
q.b=q1.b+q2.b;
q.c=q1.c+q2.c;
file:///D|/ ------------------ 上架商品----------------- ... 教程( 第二版) 课后答案( 徐孝凯
著) 清华大学/ 第一章绪论.txt (第3 /10 页) [2010-3-16 22:06:17]
file:///D|/ ------------------ 上架商品---------------------- / 数据结构实用教程( 第二版)
课后答案(徐孝凯著)清华大学/第一章绪论.txt
return q;
}
⑶ 根据给定x 的值计算多项式的值。
float Eval(Quadratic q,float x);
解:
float Eval(Quadratic q,float x)
{
return(q.a*x*x+q.b*x+q.c);
}
⑷ 计算方程ax2+bx+c=0 的两个实数根,对于有实根、无实根和不是实根方程
(即a==0)这三种情况要返回不同的整数值,以便于工作调用函数做不同的处理。
int Root(Quadratic q,float& r1,float& r2);
解:
int Root(Quadratic q,float& r1,float& r2)
{
if(q.a==0)return -1;
float x=q.b*q.b-4*q.a*q.c;
if(x>=0){
r1=(float)(-q.b+sqrt(x))/(2*q.a); r2=(float)(-q.b-sqrt(x))/(2*q.a);
return 1;
}
else return 0;
}
⑸按照ax**2+bx+c的格式(x2用x**2表示)输出二次多项式,在输出时要注意去掉系数为0的项,并且当b和c的值为负时,其前不能出现加号。
void Print(Quadratic q)
解:
void Print(Quadratic q)
{
if(q.a) cout<<q.a<<"x**2";
if(q.b) if(q.b>0)
cout<<"+"<<q.b<<"x";
else
cout<<q.b<<"x";
if(q.c)
if(q.c>0) cout<<"+"<<q.c;
else
cout<<q.c;
cout<<end1;
}
file:///D|/ ------------------ 上架商品----------------- ... 教程( 第二版) 课后答案( 徐孝凯
著) 清华大学/ 第一章绪论.txt (第4 /10 页) [2010-3-16 22:06:17]
file:///D|/ ------------------ 上架商品---------------------- / 数据结构实用教程( 第二版)
课后答案(徐孝凯著)清华大学/第一章绪论.txt
3. 用C++函数描述下列每一个算法,并分别求出它们的时间复杂度。
⑴ 比较同一简单类型的两个数据x1 和x2 的大小,对于x1>x2,x1=x2 和x1<x2 这三种不同情况分别返回'>''=' 和'<' 字符。
假定简单类型用SimpleType 表示,它可通过typedef
语句定义为任一简单类型。
解:
Char Compare(SimpleType x1,SimpleType x2)
{
if(x1>x2) return'>';
else if(x1==x2) return '=';
else return'<';
}
其时间复杂度为O(1)
⑵ 将一个字符串中的所有字符按相反方的次序重新放置。
解:
void Reverse(Char*p)
{
int n=strlen(p);
for(int i=0;i<n/2;i++){
Char Ch;
Ch=p[i] p[i]=p[n-i-1];
p[n-i-1]=Ch;
}
}
其时间复杂度为O(n)
⑶ 求一维double 型数组a[n] 中的所有元素之乘积。
解:
double produCt(double a[],int n)
{
double p=1;
for(int i=0;i<n;i++)
p*=a[i];
return p;
}
其时间复杂度为 O(n)
⑷计算刀ni=0xi/i+1 的值。
解:
double Accumulate(double x,int n)
{
double p=1,s=1;
for(int i=1;i<=n;i++){
p*=x;
s+=p/(i+1);
file:///D|/ ------------------ 上架商品 --- ... 教程 ( 第二版 ) 课后答案 ( 徐孝凯 著) 清华大学 / 第一章 绪论 .txt (第 5 /10 页) [2010-3-16 22:06:17]
file:///D|/ ------------------
上架商品 -------- / 课后答案(徐孝凯 著)清华大学/第一章 绪论.txt } return s;
} 其时间复杂度为 O(n)
⑸ 假定一维数组 a[n] 中的每个元素值均在 [0 ,200]区间,分别统计出落在 [0,20) ,[20,50),[50,80),[80,130),[130,200]
等各区间的元素个数。
解:
用数组 c[5] 保存统计结果 用来保存各统计区间的上限 给数组 c[5] 中的每个元素赋初值 0
if(a[i]<0||a[i]>200) return 0;// 返回数值 0 表示数组中数据有错,统计失败
if(a[i]<d[j]) break;
c[j]++;//
使统计相应区间的元素增 1 }
return 1;//
返回数值 1 表示统计成功 }
其时间复杂度为 O(n)
⑹ 从二维整型数组 a[m][n] 中查找出最大元素所在的行、列下标。
解:
void find(int a[M][N],int m,int n,int&Lin,int&Col)
//M 和N 为全局常量,应满足
皿>=门和N>=n 的条件,Lin 和Col 为引用 // 形参,它是对应实参的别名,其值由实参带回
{
Lin=0;Col=0;
for(int i=0;i<m;i++)
for(int j=0;j<n;j++)
if(a[i][j]>a[Lin][Col]){Lin=i;Col=j;}
}
其时间复杂度为 O(m*n)
4. 指出下列各算法的功能并求出其时间复杂度。
数据结构实用教程 ( 第二版 ) int Count(int a[],int n,int c[5])//
{
int d[5]={20,50,80,130,201};// int i,j;
for(i=0;i<5;i++)c[i]=0;//
for(i=0;i<n;i++)
{
for(j=0;j<5;j++)//
查找 a[i] 所在区间
⑴ int prime(int n)
{
int i=2;
int x=(int)sqrt(n);
while(i<=x){
if(n%i==0)break;
i++;
}
file:///D|/ ------------------ 上架商品----------------- ... 教程( 第二版) 课后答案( 徐孝凯著) 清华大学/ 第一章绪论.txt (第6 /10 页) [2010-3-16 22:06:17]
file:///D|/ ------------------ 上架商品---------------------- / 数据结构实用教程( 第二版)课后答案(徐孝凯著)清华大学/第一章绪论.txt
if(i>x)
return 1;
else
return 0;
}
解:
判断n 是否是一个素数,若是则返回数值1,否则返回0。
该算法的时间复杂度为O(n1/2) 。
⑵ int sum1(int n)
{
int p=1,s=0;
for(int i=1;i<=n;i++){
p*=i;
s+=p;
}
return s;
}
解:
计算刀i!(上标为n,下标为i=1)的值,其时间的复杂度为0(n)。
⑶ int sum2(int n)
{
int s=0;
for(int i=1;i<=n;i++){
int p=1;
for(int j=1;j<=i;j++)
p*=j;
s+=p;
}
return s;
}
解:
计算刀i!的值,时间复杂度为0(n2)
⑷ int fun(int n)
{
int i=1,s=1;
while(s<n)
s+=++i;
return i;
} 解:
求出满足不等式1+2+3...+i > n的最小i值,其时间复杂度为0(n1/2)。
⑸ void UseFile(ifstream& inp,int c[10])
// 假定inp 所对应的文件中保存有n 个整数
file:///D|/ ------------------ 上架商品 --- ... 教程( 第二版) 课后答案( 徐孝凯
著)清华大学/第一章绪论.txt (第7 /10页)[2010-3-16 22:06:17]
file:///D|/ ------------------ 上架商品---------------------- / 数据结构实用教程( 第二版)
课后答案(徐孝凯著)清华大学/第一章绪论.txt
{
for(int i=0;i<10;i++)
c[i]=0;
int x;
while(inp>>x){
i=x%10;
c[i]++;
}
}
解:
利用数组c[10] 中的每个元素c[i] 对应统计出inp 所联系的整数文件中个位值同为i 的整数个数,时间复杂度为0(n)
⑹ void mtable(int n)
{
for(int i=1;i<=n;i++){
for(int j=i;j<=n;j++)
cout<<i<<"*"<<j<<"="
<<setw(2)<<i*j<<"";
cout<<end1;
}
}
解:
打印出一个具有n行的乘法表,第i行(1 < i < n)中有n-i+1个乘法项,每个乘法项为i 与j(
i w j w n)的乘积,时间复杂度为0(n2)。
⑺ void cmatrix(int a[M][N],int d)
//M 和N 为全局整型常量
{
for(int i=0;i<M;i++)
for(int j=0;j<N;j++)
a[i][j]*=d;
}
解:
使数组a[M][N] 中的每一个元素均详细以 d 的值,时间复杂度为0(M*N)
⑻ void matrimult(int a[M][N],int b[N][L],int c[M][L])
//
{
int i,j,k;
for(i=0;i<M;i++)
for(j=0;j<L;j++)
c[i][j]=0;
for(i=0;i<M;i++)
for(j=0;j<L;j++)
for(k=0;k<N;k++) c[i][j]+=a[i][k]*b[k][j];
file:///D|/ ------------------ 上架商品----------------- ... 教程( 第二版) 课后答案( 徐孝凯
著)清华大学/第一章绪论.txt (第8 /10页)[2010-3-16 22:06:17]
file:///D|/ ------------------ 上架商品---------------------- / 数据结构实用教程( 第二版)课后答案(徐孝凯著)清华大学/第一章绪论.txt
}
解:
矩阵相乘,即a[M][N] X b[N][L] T c[M][L],时间复杂度为O(MX NX L)。
5. 题目略
⑴解:
void InitSet(Set& s)
{
for(int i=1;i<=SETSIZE;i++)
s.m[i]=0;
}
⑵解:void InitSet(Set& s,int a[],int n)
{
fot(int i=0;i<n;i++)
s.m[a[i]]=1;
}
⑶解:
Set operator + (Set s1,Set s2)
{
Set s;
InitSet(s);
for(int i=1;i<=SETSIZE;i++)
if((s1.m[i]==1)||s2.m[i]===1))
s.m[i]=1;
return s;
}
⑷解:
Set operator*(Set s1,Set s2)
{
Set s;
InitSet(s);
for(int i=1;i<=SETSIZE;i++)
if((s1.m[i]==1)&&(s2.m[i]==1))
s.m[i]=1;
return s;
⑸解:
Boolean operator 人(int elt,Set s)
{
if(s.m[elt]==1)
return True;
else
file:///D|/ ------------------ 上架商品----------------- ... 教程( 第二版) 课后答案( 徐孝凯
著) 清华大学/ 第一章绪论.txt (第9 /10 页) [2010-3-16 22:06:17]
file:///D|/ ------------------ 上架商品---------------------- / 数据结构实用教程( 第二版)课后答案(徐孝凯著)清华大学/第一章绪论.txt
return False;
}
⑹解:
void Inisert(Set& s,int n)
{
s.m[n]=1;
}
⑺解:
void Delete(Set& s,int n)
{
s.m[n]=0;
} ⑻解:
ostream& operator<<(ostream& ostr,Set& s) { ostr<<'{' for(int i=1;i<=SETSIZE;i++) if(s.m[i]==1)
ostr<<i<<','; ostr<<'}'<<end1; return ostr; }
类别:数据结构 上架商品 ... 程 ( 第二版 ) 课后答案 ( 徐孝凯 著 ) 第 10 / 10 页) [2010-3-16 22:06:17]
file:///D|/ ------------------ 上架商品 ----------------------- / 数据结构实用教程 ( 第二版 ) 课后答案 ( 徐孝凯 著) 清华大学 /第二章 线性表 .txt 习题二 一、单选题 1. 在一个长度为n 的顺序存储的线性表中,向第 i 个元素(1 < i < n+1)之前插入一个新元素
时,
需要从年向前依次移 B 个元素。
A n-i B n-i+1 C n-i-1 D i
2. 在一个长度为n 的顺序存储的线性表中,删除第 i 个元素(1 < i < n+1)时,需要从前向后 依次 前移 A 个元素。
3. 在一个长度为 n 的线性表中顺序查找值为 x 的元素时,查找成功的平均查找长度(即 x 同元素 的平均比较次数,假定查找每个元素的概率都相等)为 C 。
A n B n/2 C (n+1)/2 D (n-1)/2
4. 在一个单链表HL 中,若要向表头插入一个自由指针 p 指向的结点,则执行 B 。
A HL=p;p->next=HL;
B p=next=HL; HL=p;
C p->next=HL; p=HL;
D p->next=HL->next;HL->next=p;
5. 在一个单链表HL 中,若要在指针q 所指结点的后面插入一个自由指针 p 所指向的结点,
则执行 D 。
A q->next=p->next;p->next=q;
B p->next=q->next;q=p;
C q->next=p->next;p->next=q
D p->next=q->next;q->next=p;
6. 在一个单链表HL 中,若要删除由指针 q 所指向结点的后继结点,则执行 C 。
A p=q->next;p->next=q->next; B p=q->next;q->next=p;
C p=q->next;q->next;q->next=q;
D q->next=q=->Next->next;q->next=q; 二、填空题
1. 在线性表的单存储结构中,每个结点包含有两个域,一个叫 值 ,另一个叫 指针 域。
2. 在下面数组 a 中存储着一个线性表,表头指针为 a[0].next ,则该线性表为 (38,56,25,
60,42,74) 。
a 0 1 2 3 4 5 6 7 8
file:///D|/
清华大学 / 第一章 绪论 .txt
data 60 56 42 38 74 25 next 4 3 7 6 2 0 1
3. 对于一个长度为l 的顺序存储的线性表,在表头插入元素的时间复杂度帾o(n) ,在表尾插
入元素的时间复杂度为O(1) 。
4. 对于一个单存储的线性表,在表头插入结点祫时话里有话复杂度为o(1) ,在表尾插入元素的时间复杂度为o(n) 。
5. 在线性表的顺序存储中,若一个元素的下标为i ,则它的前驱元素的下标为i-1 ,后继的下标为i+1 。
file:///D|/ ------------------ 上架商品---------------- ... 程( 第二版) 课后答案( 徐孝凯著)
清华大学/第二章线性表.txt (第1/21 页) [2010-3-16 22:06:59]
file:///D|/ ------------------ 上架商品----------------------- / 数据结构实用教程( 第二版)
课后答案( 徐孝凯著) 清华大学/第二章线性表.txt
6. 在线性表的单存储中,若一个元素所在结点的地址为p,则后继结点的地址为p->next , 若假定p为一个数组a中的下标,则其后继结点的下标为a[p].next 。
7. 在循环单表中,最后一个结点的指针域指向表头结点。
8. 在双向表中每个结点包含有两个针域,一个指向其前驱结点,另一个指向其后继结点。
9. 在循环双向表中表头结点的左指针域指向表尾结点,最后一个结点的右指针域指向表头结点。
10. 在以HL 为表头指针的带表头附加结点的单表中 , 链表为空的条件分别为HL->next==NULL
HL->next==HL 。
11. 在由数组a 中元素结点构成的单链表中,删除下标为i 的结点后,需要把该结点插入到空闲表的表头,具体操作为a[i].next=a[1].next;a[1].next=i; 。
12. 在由数组a 中元素结点构成的单链表中,在插入下标为i 的结点后,需要从空闲表头中删除一个结点,并将该结点下标赋给i ,具体操作为i=a[1].next;a[1].next=a[i].next; 。
13. 在由数组a 中元素结点构成的单链表中,删除下标为i 的后继结点并将被删除结点的下标赋给i 时
,所进行的操作描述为p=a[i].next;a[i].next=a[p].next;i=p; 。
14. 在由数组a 中元素结点构成的单链表中,在下标为i 的结点的后面插入一个下标为j 的结点时,需要进行的操作为a[j].next=a[i].next;a[i].next=j; 。
三、普通题
1.
⑴解:(79,62,34,57,26,48)
⑵解: (26,34,48,57,62,79) ⑶解: (48,56,57,62,79,34) ⑷解: (56,57,79,34) ⑸解: (26,34,39,48,57,62) 2. 解:
上架商品 ... 程 ( 第二版 ) 课后答案 ( 徐孝凯 著 ) 第 2 /21 页) [2010-3-16 22:06:59]
file:///D|/ ------------------ 上架商品 ---------------------- / 数据结构实用教程 ( 第二版 ) 课后答案 ( 徐孝凯 著) 清华大学 /第二章 线性表 .txt
为了排版方便,假定采用以下输出格式表示单表的示意图;每个括号的数据表示一个元 素结点, 其中第一个数据为元素值, 第二个数据为后继结点的指针, 第一个元素结点前的数 值为 表头指针。
1. (7(79,6),(62,5),(34,4),(57,3),(26,2),(48,0))
2. (3(26,5),(34,2),(48,4),(57,6),(62,7),(79,0))
3. (2(48,8),(56,4),(57,6),(62,7),(79,5),(34,0))
4. (8(56,4),(57,7),(79,5),(34,0))
3. 对于 List 类型的线性表 , 编写出下列每个算法。
⑴ 从线性表中删除具有最小值的元素并由函数返回,空出的位置由最后一个元素填补,若 线性表为空则显示出错信息并退出运行。
解: ElemType DMValue(List&L)
// 从线性表中删除具有最小值的元素并由函数返回 , 空出的位置 // 由最后一个元素填补 , 若线性表为空则显示出错信息并退出运行 { if(ListEmpty(L)){
cerr<<"List is Empty!"<<end1; exit(1); }
ElemType x; x=L.list[0]; int k=0;
for(int i=1;i<L.size;i++){
ElemType y=L.list[i]; if(y<x){x=y;k=i;} } L.list[k]=L.list[L.size-1]; L.size--; return x; }
⑵ 从线性表中删除第 i 个元素并由函数返回。
解: int Deletel(List& L,int i)
// 从线性表中删除第 i 个元素并由函数返回
file:///D|/ ------------------
清华大学 /第二章 线性表 .txt
{
if(i<1||i>L.size){
cerr<<"Index is out range!"<<end1; exit(1);
}
ElemType x;
x=L.list[i-1];
for(int j=i-1;j<L.size-1;j++)
L.list[j]=L.list[j+1];
L.size--;
file:///D|/ ------------------ 上架商品---------------- ... 程( 第二版) 课后答案( 清华大学/第二章线性表.txt (第3/21 页) [2010-3-16 22:06:59]
file:///D|/ ------------------ 上架商品---------------------- / 数据结构实用教程课后答案( 徐孝凯著) 清华大学/第二章线性表.txt return x;
}
⑶ 向线性表中第i 个元素位置插入一个元素。
解:void Inser1(List& L,int i,ElemType x)
// 向线性表中第i 个元素位置插入一个元素
{
if(i<1||i>L.size+1){
cerr<<"Index is out range!"<<end1;
exit(1);
}
if(L.size==MaxSize)
{
cerr<<"List overflow!"<<end1; exit(1);
}
for(int j=L.size-1;j>i-1;j--) L.list[j+1]=L.list[j];
L.list[i-1]=x;
L.size++;
}
⑷ 从线性表中删除具有给定值x 的所有元素。
解:void Delete2(List& L,ElemType x)
// 从线性表中删除具有给定值x 的所有元素
{ int i=0;
while(i<L.size)
if(L.list[i]==x){
for(int j=i+1;j<L.sizr;j++)
L.list[j-1]=L.list[j];徐孝凯
著)
(第二版)
{L.size--; } else i++; }
⑸ 从线性表中删除其值在给定值
s 和t 之间(要求s 小于t)的所有元素。
解: void Delete3(List& L,ElemType s,ElemType t)
//
从线性表中删除其值在给定值
s 和t 之间的所有元素
{
int i=0;
while(i<L.size)
file:///D|/ ------------------ 上架商品 ---------------- ... 程 ( 第二版 ) 课后答案 ( 清华大学 /第二章 线性表 .txt (第 4 /21 页) [2010-3-16 22:06:59]
file:///D|/ ------------------ 上架商品 ---------------------- / 数据结构实用教程 课后答案(徐孝凯 著)清华大学/第二章 线性表.txt if((L.list[i]>=s)&&(L.list[i]<=t)){ for(int
j=i+1;j<L.size;j++) L.list[j-i]=L.list[j]; L.size--; } else i++; }
⑹ 从有序表中删除其值在给定值
s 和t 之间(要求s 小于t)的所有元素。
解: void Delete4(List& L,ElemType s,ElemType t)
//
从有序表中删除其值在给定值
s 和t 之间的所有元素
{ int i=0;
while(i<L.size)〃
从有序表L 中查找出大于等于
s 的第一个元素
if(L.list[i]<s)i++; else break;
if(i<L.size){ While((i+j<L.size)&&(L.list[i+j]<=t)) j++;// 求出 s 和 t 之间元素的个数
for(int k=i+j;k<L.size;k++) L.list[k-j]=L.list[k]; L.size-=j; } }
⑺ 将两个有序表合并成一个新的有序表并由变量返回。
解:void Merge(List& L1, List& L2,List& L3)
// 将两个有序表合并成一个新的有序表并由变量返回
徐孝凯 著)
( 第二版 )
if(L1.size+L2.size>MaxSize){
cerr<<"List overflow!"<<end1;
exit(1);
}
int i=0,j=0,k=0;
while((i<L1.size)&&(j<L2.size)){
if(L1.list[i]<=L2.list[j])
{ // 将L1 中的元素赋给L L.list[k]=L1.list[i];
i++;
}
else{ // 将L2 中的元素赋给L
L.list[k]=L2.list[j];
j++;
file:///D|/ ------------------ 上架商品----------------- ... 程( 第二版) 课后答案( 徐孝凯著) 清华大学/第二章线性表.txt (第5/21 页) [2010-3-16 22:06:59]
file:///D|/ ------------------ 上架商品-----------------------/ 数据结构实用教程( 第二版)
课后答案( 徐孝凯著) 清华大学/第二章线性表.txt
}
k++;
}
while(i<L1.size){ // 将L1 中剩余的元素赋给L L.list[k]=L1.list[i];
i++;k++;
}
while(j<L2.size){ // 将L2 中剩余的元素赋给L L.list[k]=L2.list[j];
j++;k++;
}
L.size=k;
}
⑻ 从线性表中删除所有其值重复的元素,使其所有元素的值均不同,如对于线性表(2,8,9, 2,5,5,6,8,7,2) ,则执行此算法后变为(2,8,9,5,6,7) 。
解:void Delete5(List& L)
// 从线性表中删除所有其值重复的元素, 使其所有元素的值均不同
{
int i=0; while(i<L.size){
int j=i+1;
while(j<L.size)
{ // 删除重复值为L.list[i] 的所有元素if(L.list[j]==L.list[i]){
for(int k=j+1;k<L.size;k++)
L.list[k-1]=L.list[k];
L.size--;
}
else
j++;
}
i++;
}
}
4. 对于结点类型为LNode的单表,编写出下列每个算法。
⑴ 将一个单表按逆序, 即若原单链表中存储元素的次序为a1,a2,...,an, 则逆序后变为an,an-1,...a1 。
解:void Contrary(LNode*&HL)
// 将一个单多办实事有按逆序
{
LNode*p=HL;//p 指向待逆序的第一个结点,初始指向原表头结点
HL=NULL;//HL 仍为逆序后的表头指针,禄始值为空
file:///D|/ ------------------ 上架商品----------------- ... 程( 第二版) 课后答案(
清华大学/第二章线性表.txt (第6 /21 页) [2010-3-16 22:06:59]
file:///D|/ ------------------ 上架商品-----------------------/ 数据结构实用教程
课后答案(徐孝凯著)清华大学/第二章线性表.txt
while(p!=NULL)
{ // 把原单链表中的结点依次进行逆序
LNode*q=p; //q 指向待处理的结点
p=p->next; //p 指向下一个待逆序的结点
// 将q 结点插入到已序单链表的表头
q->next=HL;
HL=q;
}
}
⑵ 删除单链表中的第i 个结点。
解:void Delete1(LNode*&HL,int i)
// 删除单链表中的第i 个结点
{
if(i<1||HL==NULL){
cerr<<"Index is out range!"<<end1;
exit(1);
}
LNode*ap,*cp;
ap=NULL;cp=HL; //cp 指向当前结点,ap 指向其前驱结点
int j=1;
while(cp!=NULL)
if(j==i)
break; //cp 结点即为第i 个结点else{ // 继续向后寻找ap=cp;
cp=cp->next;
j++;
} 徐孝凯著) ( 第二版)
if(cp==NULL){
cerr<<"Index is out range!"<<end1;
exit(1);
}
if(ap==NULL)
HL=HL->next;
else
ap->next=cp->next;
delete cp;
}
⑶ 从单链表中查找出所有元素的最大值,该值由函数返回,若单链表为空,则显示出错信
息并停止运行。
解:ElemType MaxValue(LNode*HL)
// 从单链表中查找出所有元素的最大值,该值由函数返回
file:///D|/ ------------------ 上架商品----------------- ... 程( 第二版) 课后答案( 徐孝凯著)
清华大学/第二章线性表.txt (第7/21 页) [2010-3-16 22:06:59]
file:///D|/ ------------------ 上架商品-----------------------/ 数据结构实用教程( 第二版)
课后答案( 徐孝凯著) 清华大学/第二章线性表.txt
{
if(HL==NULL){
cerr<<"Linked list is empty!"<<end1;
exit(1);
}
ElemType max=HL->data;
LNode*p=HL->next;
while(p!=NULL){
if(max<p->data) max=p->data;
p=p->next;
}
return max;
}
⑷ 统计出单链表中结点的值等于给定值x 的结点数。
解:int Count(LNode*HL,ElemType x)
// 统计出单链表中结点的值等于给定值x 的结点数
{ int n=0; while(HL!=NULL){ if(HL->data==x) n++;
HL=HL->next;
}
return n;
}
⑸ 根据一维数组a[n] 建立一个单链表,使单链表中元素的次序与a[n] 中元素的次序相同,并使该算法的时间复杂度为O(n) 。
解:void Create(LNode*&HL,ElemType a[],int n)
// 根据一维数组a[n] 建立一个单链表
{
InitList(HL);
for(int i=n-1;i>=0;i--)
InsertFront(HL,a[i];
}
⑹ 将一个单链表重新成有序单链表。
解:void OrderList(LNode*&HL)
// 将一个单链表重新成有序单链表
{
LNode* p=HL;//p 指向待处理的第一个结点,初始指向原表头结点
HL=NULL; //HL 仍为待建立的有序表的表头指针,禄始值为空
while(p!=NULL)
{ // 把原单链表中的结点依次进行有序
file:///D|/ ------------------ 上架商品----------------- ... 程( 第二版) 课后答案( 徐孝凯著) 清华大学/第二章线性表.txt (第8/21 页) [2010-3-16 22:06:59]
file:///D|/ ------------------ 上架商品-----------------------/ 数据结构实用教程( 第二版)
课后答案( 徐孝凯著) 清华大学/第二章线性表.txt
LNode* q=p; //q 指向待处理的结点
p=p->next; //p 指向下一个待处理的结点LNode* ap=NULL,*cp=HL;
//cp 指向有序表中待比较的结点,ap 指向其前驱结点while(cp!=NULL)
{ // 为插入q 结点寻找插入位置
if(q->data<cp->data) break; else{
ap=cp; cp=cp->next;
}
} // 将 q 结点插入到 ap 和 cpxf hko pp uj q->next=cp; if(ap==NULL) HL=q; else ap->next=q; }
}
⑺ 将两个有序单链表合并成一个有序单链表,合并后使原有单链表为空。
解: LNode*Mergel (LNode*&p1,LNode*&p2)
// 将两个有序单链表合并成一个有序单链表
while((p1!=NULL)&&(p2!=NULL)) {// 处理两个表非空的情况 if(p1->data<p2->data){ p->next=p1;p1=p1->next; } else{
p->next=p2;p2=p2->; p=p->next;
}
if(p1!=NULL)p->next=p1; if(p2!=NULL)p->next=p2; 上架商品 ... 程 ( 第二版 ) 课后答案 ( 徐孝凯 著 )
第 9 /21 页) [2010-3-16 22:06:59]
file:///D|/ ------------------ 上架商品 -----------------------/ 数据结构实用教程 ( 第二版 ) 课后答案 ( 徐孝凯 著) 清华大学 /第二章 线性表 .txt
⑻ 根据两个有序单链表生成一个新的有序单链表,原有单链表保持不变。
如假定两个有序 单链
表中的元素为(2,8,10,20) 和(3,8,9,15,16) ,则生成的新单链表中的元素 为 (2,3,8,8,9,10,15,
//
LNode*p=&a; //p p->next=NULL;//
结束后返回 a 结点的镄针域的值 指向结果的有序单链表的表尾结点 初始指向表头
附加结点
结点作为结果的有序单链表的表头附加结点,这样便于处理,
{
LNode a; //a 处理
p1=p2=NULL; return a.next;
}
file:///D|/ ------------------
清华大学 /第二章 线性表 .txt
16,20) 。
解: LNode*Merge2(LNode*p1,LNode*p2)
// 根据两个有序单链表生成一个新的有序单链表
用 a 作为新的有序单链表的表头附加结点 指向结果有序单链表的表尾结点 初始指向表头附加结点 while((p1!=NULL&&(p2!=NULL))
{ // 处理两个表非空时的情况
LNode*newptr=new LNode; if(p1->data<p2->data) { // 由 p1->data 建立新结点,然后 p1 指针后移
newptr->data=p1->data;
p1=p1->next;
}
else
{ // 由 p2->data 建立新结点,然后 p2 指针后移 newptr->data=p2->data;
p2=p2->next;
}
// 将 newptr 结点插入到结果的有序表的表尾 p->next=newptr;
p=newptr;
}
while(p1!=NULL)
{ // 继续处理 p1 单链表中剩余的结点
LNode*newptr=new LNode;
newptr->data=p1->data;
p1=p1->next;
p->next=newptr;
p=newptr;
}
while(p2!=NULL)
{ // 继续处理 p2 单链表中剩余的结点
LNode*newptr=new LNode;
newptr->data=p2->data;
p2=p2->next;
p->next=newptr;
p=newptr;
}
p->next=NULL;
file:///D|/ ------------------ 上架商品 ... ( 第二版 ) 课后答案 华大学 / 第二章 线性表 .txt (第 10 /21 页) [2010-3-16 22:06:59]
file:///D|/ ------------------ 上架商品 -----------------------/ 数据结构实用教程 ( 第二版 ) 课后答案 ( 徐孝凯 著) 清华大学 /第二章 线性表 .txt
return a.next;
}
LNode a; //
LNode*p=&a; //p
p->next=NULL; // ( 徐孝凯 著 ) 清
⑼ 根据一个元素类型为整型的单链表生成两个单链表,使得第一个单链表中包含原单链表中所有
元素值为奇数的结点,使得第二个单链表中包含原单链表中所有元素值为偶数的结点。
原有单链表保持不变。
解:void Separate(LNode*HL,LNode*&p1,LNode*&p2)
// 根据一个单链表HL 按条件拆分生成两个单链表p1 和p2
{
LNode a,b; //a 和b 结点分别作为p1 和p2 单链表的表头附加结点LNode*t1=&a,*t2=&b; //t1 和t2 分别作为指向p1 和p2 单链表的
// 表尾结点,初始指向表头附加结点
Lnode*p=HL;
while(p!=NULL)
{ // 每循环一次产生一个新结点,并把它加入到p1 或p2 单链表
// 的未尾
LNode*newptr=new LNode;
if(p->data%2==1){ newptr->data=p->data;
t1->next=newptr;
t1=newptr;
}
else{
newptr->data=p->data; t2->next=newptr;
t2=newptr;
}
p=p->next;
} t1->next=t2->next=NULL;
p1=a.next;p2=b.next; // 把指向两个单链表的表头结点的指针分别赋给//p1 和p2 返回}
6. 编写一个算法,使用表头附加结点的循环单链表解决约瑟夫(Josephus) 问题。
其问题是 :设有n 个人围坐在一圆桌周围,现从某个人开始从1报数,数到m的人出列(即离开坐位,
不参加以后的报数),接着从出列的下一个人开始重新从1报数,数到m的人又出列,如此
下
去直到所有人都出列为止,试求出它们的出列次序。
假如,当n=8、m=4时,若从第一个人(假定每个人的编号依次为1,2...,n) 开始报数,则得到的出列次序为:4,8,5,2,1,3,7,6 。
此算法要求以n、m和s(假定从第s个人开始第一次报数)作为值参。
解:
void Josephus(int n,int m,int s)
// 使用带表头附加结点的循环单链表解决约瑟夫问题
file:///D|/ ------------------ 上架商品---------------- ... ( 第二版) 课后答案( 徐孝凯著) 清
华大学/第二章线性表.txt (第11 /21 页) [2010-3-16 22:06:59]
file:///D|/ ------------------ 上架商品-----------------------/ 数据结构实用教程( 第二版)
课后答案( 徐孝凯著) 清华大学/第二章线性表.txt
{
// 生成表头附加结点,此时循环单链表为空
LNode*HL=new LNode;
HL->next=HL;
int i;
// 生成含有n 个结点、结点依次为1,2,...n 的带表头结点的循环单链表
for(i=n;i>=1;i--){
// 生成新的结点
LNode*newptr=new LNode;
newptr->data=i;
// 把新的结点插入到表头
newptr->next=HL->next;
HL->next=newptr;
}
// 从表头开始顺序查找出第s 个结点,对应第一个开始报数的人LNode*ap=HL,*cp=HL->next;
for(i=1;i<s;i++){
//ap 和cp 指针后移一个位置
ap=cp;
cp=cp->next;
// 若cp 指向了表头附加结点,则仍需后移ap 和cp 指针,使之指向表头结点
if(cp==HL){ap=HL;cp=HL->next;}
}
// 依次使n-1 个人出列
for(i=1;i<n;i++){
// 顺序查找出待出列的人,即为循环结束后cp 所指向的结点
for(int j=1;j<m;j++){
ap=cp;
cp=cp->next;
if(cp==HL){ap=HL;cp=HL->next;}
}
// 输出cp 结点的值,即出列的人cout<<cp->data<<"";
// 从单链表中删除cp 结点
ap->next=cp->next;
delete cp;
// 使cp 指向被删除结点的后继结点cp=ap->next;
// 若cp 指向了表头附加结点,则后移ap 和cp 指针if(cp==HL){ap=HL;cp=HL->next;} }
// 使最后一个人出列
cout<<HL->next->data<<end1;
// 删除表头结点和表头附加结点
file:///D|/ ------------------ 上架商品... (第二版)课后答案(徐孝凯著)清华大学/ 第二章线性表.txt (第12 /21 页)[2010-3-16 22:06:59]
file:///D|/ ------------------ 上架商品----------------------- / 数据结构实用教程(第二版)。