第2章 基本数据结构及算法习题参 考答案
合集下载
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
while((q ->lchild!=p)&& (q->rchild!=p))//未到叶子结点
if(q->data>key)//插入到左子树
{if(q->lchild!=NULL) q=q->lchild;
else q->lchild=p;
}
else //插入到右子树
{if(q->rchild!=NULL) q=q->rchild;
if(top>0) tag=0;
}
13.现有如下的稀疏矩阵,要求写出其三元组表示。
参考答案:
14.现有一个稀疏矩阵的三元组表示如下,试写出其对应的稀疏矩阵。
参考答案:
15.编写一个算法,将给定的m×n稀疏矩阵转换成三元组表示。
参考答案:
int change(int m,int n,int a[ ][M],int b[ ][3])
22.对下列有向图,求出每个顶点的度、入度和出度以及图的度,并给出其邻接矩阵及邻接表的表示。
解1:
顶点入度出度vi的度
1)303
2)213
3)224
4)134
5)134
6)112
图的度为4。
解2:有向图1的邻接矩阵
000000
100000
100100
010011
111000
001000
第i行非零元素的个数为第i个顶点的出度,
(3)在栈中插入一个元素Y;
(4)删除栈顶元素;
(5)在栈中插入一个元素Z;
(6)在栈中插入一个元素W;
(7)栈初始化。
top
→
Y
top
→
X
X
top
→
栈空
在栈中插入一个元素X
在栈中插入一个元素Y
top
→
W
top
→
Z
Z
top
→
X
X
X
删除栈顶元素
在栈中插入一个元素Z
在栈中插入一个元素W
top
→→
栈初始化
{node *pa,*pb,*pc,*ch,*q;
pa=ah;pb=bh;ch=NULL;
while(pa!=NULL&&pb!=NULL)
{pc=new node;
if(pa->data<=pb->data)
{pc->data=pa->data;
pa=pa->next;
}
else
{pc->data=pb->data;
11.设循环队列的容量为50(序号1~50),现经过一系列的进队与退队运算后,有:
(1)front=15,rear=22。
(2)front=26,rear=12。
问在这两种情况下,循环队列中各有多少个元素?
(1)7
(2)36
12.假设一个算术表达式中包含圆括号、方括号和花括号三种类型的括号,编写一个判别表达式中括号是否正确配对的算法。
pb=pb->next;
}
if(ch==NULL)
ch=pc;
else q->next=pc;
q=pc;
}
if(pb==NULL)
while(pa!=NULL)
{pc=new node;
pc->data=pa->data;
pa=pa->next;
if(ch==NULL)
ch=pc;
else q->next=pc;
struct node *p;
n=0;
p=head;
while(p!=NULL)
{n++;
p=p->next;
}
return n;
}
9.用筛选法求1000以内的素数。用单链表存放2~1000的值,编写一个函数删除该单链表中非素数的结点(即剩下的结点中的值均为素数)。
#include <iostream.h>
struct node
{char d;
struct node *next
};
invlst(struct node **head)
{struct node *p,*q,*r;
if(*head!=NULL)
{p=*head;q=p->next;
p->next=NULL;
while(q!=NULL)
{r=q->next;q->next=p;
参考答案:
btree *insertree(btree *t,int key)
{btree *p,*q;
p=new btree; //申请结点,并插入之
p->data=key;
p->lchild=NULL;
p->rchild=NULL;
q=t;
if(q==NULL) t=p; //二叉查找树为空
else //二叉查找树不空
head=p;
else
q->next=p;
q=p;
}
return(head);
}
node *delst( node *head)
{
node *p,*q,*r;
p=head;
r=p;
while(p!=NULL)
{
q=p->next;
while(q!=NULL)
{
if( (q->d)%(p->d)==0)
{
int *p,*q;
q=&a[n/2];
p=a;
if(n==1) return a[0];
else return min(minnum(p,n/2),minnum(q,n/2));
}
4.试写出将一个元素插入到有序线性表中的算法。
参考答案:
int insert(int a[ ], int b, int n ,int m)
}
if(exp[i]==')')
if(st[top]=='(')top--;
else tag=0;
if(exp[i]==']')
if(st[top]=='[')top--;
else tag=0;
if(exp[i]=='}')
if(st[top]=='{')top--;
else tag=0;
i++;
}
else q->rchild=p;
}
return(t); //插入成功返回t
}
void main()
{int key;
btree *t=NULL;
cin>>key;
while(key!=0)
{
t=insertree(t,key);
cin>>key;
};
}
21.设有5个结点为K1,K2,K3,K4,K5,其权值分别为16,2,18,16,23。请构造一棵Huffman树。
{
r->next=q->next;
delete q;
q=r->next;
}
else
{
r=q;
q=q->next;
}
}
p=p->next;
}
return(head);
}
void print( node *head)
{
node *p,*q;
p=head;
while(p!=NULL)
{
cout<<p->d<<' ';
习题
1.分别写出求两个正整数最大公约数的递推与递归算法。
参考答案:
int gcd(int x, int y)
{int a, b, t, r;
a=x; b=y;
if (a<b)
{t=a; a=b; b=t;}
r=a%b;
while (r!=0)
{a=b; b=r; r=a%b; }
return(b);
p=q;q=r;
}
*head=p;
}
}
8.写出计算线性链表长度的算法。
参考答案:
struct node /*定义线性单链表结点类型*/
{ET d; /*定义线性单链表结点数据类型*/
struct node *next;/*结点指针*/
};
intlen(struct node *head)
{int n;
{
if(num>0)
{
dec_to_bin(num/base, base);
cout<<num%base;
}
}
3.利用减半递推技术,写出求长度为n(n=2k)的一维数组中的最小元素的递归算法。
参考答案:
int min(int x, int y)
{
return x>y?y:x;
}
int minnum(int a[ ],int n)
参考答案:
#define M 100
correct(char exp[],int tag)
{char st[M];
int top=0,i=1;
tag=1;
while(i<=M&&tag)
{if(exp[i]=='('||exp[i]=='['||exp[i]=='{')
{top++;
st[top]=exp[i];
q=pc;
}
else
while(pb!=NULL)
{pc=new node;
pc->data=pb->data;
pb=pb->next;
if(ch==NULL)
ch=pc;
else q->next=pc;
q=pc;
}
q->next=NULL;
return(ch);
}
7.试写出逆转线性单链表的算法。
参考答案:
while(j<n)
c[k++]=b[j++];
}
6.设有两个有序线性单链表,头指针分别为ah与bh。试写出将这两个有序线性单链表合并为一个头指针为ch的有序线性单链表的算法。
参考答案:
structnode
{int data;
structnode* next;
};
node *merge(node *ah,node *bh)
q=p;
p=p->next;
delete q;
}
cout<<endl;
}
void main()
{
node *head,*q;
head=creat( );
q=delst(head);
print(head);
}
10.对于下面的每一步,画出栈元素与栈顶指针的示意图:
(1)栈空;
(2)在栈中插入一个元素X;
(1)请还原该二叉树;
(2)写出先序遍历结果。
(1)
(2)ABDFGHIEC
19.依次输入元素序列{ 37,81,43,75,20,10,14,26 },试构造一棵二叉查找树。在这棵二叉查找树中查找33,需要比较多少次?
需要比较3次
20.写出构造二叉查找树的算法,如输入序列:23, 45, 11, 98, 16, 67, 35, 73, 53, 56, 78, 34, 0,输入为0表示序列结束。
第i列非零元素的个数为第i个顶点的入度。
解3:邻接表
顶点vi的出度是第i个链表中的结点个数,
顶点vi的入度,是所有链表中其邻接点域的值为i的结点的个数。
struct node
{ int d;
node *next;
};
node *creat(void)
{node *head,*p,*q;
int i;
head=NULL;
q=NULL;
for(i=2;i<1000;i++)
{
p=new node ;
p->d=i;
p->next=NULL;
if(head==NULL)
{ if (n = =m) printf("overflow");
else
{ if (n= =0) a[n]= b;
else
{ i=n-1;
while((i>=0)&&(a[i]>b))
{ a[i+1]=a[i];i=i-1;}
a[i+1]= b;
}
n=n+1;
}
return n;
}
5.编写一个算法,将两个线性表合并成一个有序表。
}
16.设一棵完全二叉树具有500个结点。问该完全二叉树有多少个叶子结点?有多少个度为2的结点?有多少个度为1的结点?若完全二叉树有501个结点,再回答上述问题,并说明理由。
(1)叶子结点:250
度为2的结点:249
度为1的结点:1wk.baidu.com
因为总的结点数是偶数,第一层为一个结点,中间各层均为偶数个结点,因此最后一层是奇数个结点,可知叶子结点只有1个。由性质知,度为0的结点数比度为2的结点数多1,则可推导出上述结论。
(2)同理可得
叶子结点:251
度为2的结点:250
度为1的结点:0
17.以先序遍历法访问某二叉树各结点的顺序是ABDHEICFJK,以中序遍历法访问该二叉树结点的顺序是DHBEIACJFK,要求:
(1)请还原该二叉树;
(2)写出后序遍历结果。
(1)
(2)HDJEBJKFCA
18.以后序遍历法访问某二叉树各结点的顺序是FHIGDEBCA,以中序遍历法访问该二叉树结点的顺序是FDHGIBEAC,要求:
参考答案:
void merge(int a[ ],int b[ ],int c[ ],int m,int n)
{int i,j,k;
i=j=k=0;
while(i<m&&j<n)
if(a[i]<=b[j])
c[k++]=a[i++];
else c[k++]=b[j++];
while(i<m)
c[k++]=a[i++];
{int i,j,k=1,t=0;
for(i=0;i<m;i++)
for(j=0;j<n;j++)
if(a[i][j]!=0)
{t=t+1;
b[k][0]=i;
b[k][1]=j;
b[k++][2]=a[i][j];
}
b[0][0]=m;b[0][1]=n;b[0][2]=t;
return k; //k为三列二维数组中的行数
}
int gcd(int x, int y)
{int a, b, t, r;
a=x; b=y;
if (a<b)
{ t=a; a=b; b=t; }
if(a%b==0) return b;
else gcd(b, a%b);
}
2.编写将一个十进制整数转换成二进制数的递归算法。
参考答案:
void dec_to_bin(int num,int base)//base为2
if(q->data>key)//插入到左子树
{if(q->lchild!=NULL) q=q->lchild;
else q->lchild=p;
}
else //插入到右子树
{if(q->rchild!=NULL) q=q->rchild;
if(top>0) tag=0;
}
13.现有如下的稀疏矩阵,要求写出其三元组表示。
参考答案:
14.现有一个稀疏矩阵的三元组表示如下,试写出其对应的稀疏矩阵。
参考答案:
15.编写一个算法,将给定的m×n稀疏矩阵转换成三元组表示。
参考答案:
int change(int m,int n,int a[ ][M],int b[ ][3])
22.对下列有向图,求出每个顶点的度、入度和出度以及图的度,并给出其邻接矩阵及邻接表的表示。
解1:
顶点入度出度vi的度
1)303
2)213
3)224
4)134
5)134
6)112
图的度为4。
解2:有向图1的邻接矩阵
000000
100000
100100
010011
111000
001000
第i行非零元素的个数为第i个顶点的出度,
(3)在栈中插入一个元素Y;
(4)删除栈顶元素;
(5)在栈中插入一个元素Z;
(6)在栈中插入一个元素W;
(7)栈初始化。
top
→
Y
top
→
X
X
top
→
栈空
在栈中插入一个元素X
在栈中插入一个元素Y
top
→
W
top
→
Z
Z
top
→
X
X
X
删除栈顶元素
在栈中插入一个元素Z
在栈中插入一个元素W
top
→→
栈初始化
{node *pa,*pb,*pc,*ch,*q;
pa=ah;pb=bh;ch=NULL;
while(pa!=NULL&&pb!=NULL)
{pc=new node;
if(pa->data<=pb->data)
{pc->data=pa->data;
pa=pa->next;
}
else
{pc->data=pb->data;
11.设循环队列的容量为50(序号1~50),现经过一系列的进队与退队运算后,有:
(1)front=15,rear=22。
(2)front=26,rear=12。
问在这两种情况下,循环队列中各有多少个元素?
(1)7
(2)36
12.假设一个算术表达式中包含圆括号、方括号和花括号三种类型的括号,编写一个判别表达式中括号是否正确配对的算法。
pb=pb->next;
}
if(ch==NULL)
ch=pc;
else q->next=pc;
q=pc;
}
if(pb==NULL)
while(pa!=NULL)
{pc=new node;
pc->data=pa->data;
pa=pa->next;
if(ch==NULL)
ch=pc;
else q->next=pc;
struct node *p;
n=0;
p=head;
while(p!=NULL)
{n++;
p=p->next;
}
return n;
}
9.用筛选法求1000以内的素数。用单链表存放2~1000的值,编写一个函数删除该单链表中非素数的结点(即剩下的结点中的值均为素数)。
#include <iostream.h>
struct node
{char d;
struct node *next
};
invlst(struct node **head)
{struct node *p,*q,*r;
if(*head!=NULL)
{p=*head;q=p->next;
p->next=NULL;
while(q!=NULL)
{r=q->next;q->next=p;
参考答案:
btree *insertree(btree *t,int key)
{btree *p,*q;
p=new btree; //申请结点,并插入之
p->data=key;
p->lchild=NULL;
p->rchild=NULL;
q=t;
if(q==NULL) t=p; //二叉查找树为空
else //二叉查找树不空
head=p;
else
q->next=p;
q=p;
}
return(head);
}
node *delst( node *head)
{
node *p,*q,*r;
p=head;
r=p;
while(p!=NULL)
{
q=p->next;
while(q!=NULL)
{
if( (q->d)%(p->d)==0)
{
int *p,*q;
q=&a[n/2];
p=a;
if(n==1) return a[0];
else return min(minnum(p,n/2),minnum(q,n/2));
}
4.试写出将一个元素插入到有序线性表中的算法。
参考答案:
int insert(int a[ ], int b, int n ,int m)
}
if(exp[i]==')')
if(st[top]=='(')top--;
else tag=0;
if(exp[i]==']')
if(st[top]=='[')top--;
else tag=0;
if(exp[i]=='}')
if(st[top]=='{')top--;
else tag=0;
i++;
}
else q->rchild=p;
}
return(t); //插入成功返回t
}
void main()
{int key;
btree *t=NULL;
cin>>key;
while(key!=0)
{
t=insertree(t,key);
cin>>key;
};
}
21.设有5个结点为K1,K2,K3,K4,K5,其权值分别为16,2,18,16,23。请构造一棵Huffman树。
{
r->next=q->next;
delete q;
q=r->next;
}
else
{
r=q;
q=q->next;
}
}
p=p->next;
}
return(head);
}
void print( node *head)
{
node *p,*q;
p=head;
while(p!=NULL)
{
cout<<p->d<<' ';
习题
1.分别写出求两个正整数最大公约数的递推与递归算法。
参考答案:
int gcd(int x, int y)
{int a, b, t, r;
a=x; b=y;
if (a<b)
{t=a; a=b; b=t;}
r=a%b;
while (r!=0)
{a=b; b=r; r=a%b; }
return(b);
p=q;q=r;
}
*head=p;
}
}
8.写出计算线性链表长度的算法。
参考答案:
struct node /*定义线性单链表结点类型*/
{ET d; /*定义线性单链表结点数据类型*/
struct node *next;/*结点指针*/
};
intlen(struct node *head)
{int n;
{
if(num>0)
{
dec_to_bin(num/base, base);
cout<<num%base;
}
}
3.利用减半递推技术,写出求长度为n(n=2k)的一维数组中的最小元素的递归算法。
参考答案:
int min(int x, int y)
{
return x>y?y:x;
}
int minnum(int a[ ],int n)
参考答案:
#define M 100
correct(char exp[],int tag)
{char st[M];
int top=0,i=1;
tag=1;
while(i<=M&&tag)
{if(exp[i]=='('||exp[i]=='['||exp[i]=='{')
{top++;
st[top]=exp[i];
q=pc;
}
else
while(pb!=NULL)
{pc=new node;
pc->data=pb->data;
pb=pb->next;
if(ch==NULL)
ch=pc;
else q->next=pc;
q=pc;
}
q->next=NULL;
return(ch);
}
7.试写出逆转线性单链表的算法。
参考答案:
while(j<n)
c[k++]=b[j++];
}
6.设有两个有序线性单链表,头指针分别为ah与bh。试写出将这两个有序线性单链表合并为一个头指针为ch的有序线性单链表的算法。
参考答案:
structnode
{int data;
structnode* next;
};
node *merge(node *ah,node *bh)
q=p;
p=p->next;
delete q;
}
cout<<endl;
}
void main()
{
node *head,*q;
head=creat( );
q=delst(head);
print(head);
}
10.对于下面的每一步,画出栈元素与栈顶指针的示意图:
(1)栈空;
(2)在栈中插入一个元素X;
(1)请还原该二叉树;
(2)写出先序遍历结果。
(1)
(2)ABDFGHIEC
19.依次输入元素序列{ 37,81,43,75,20,10,14,26 },试构造一棵二叉查找树。在这棵二叉查找树中查找33,需要比较多少次?
需要比较3次
20.写出构造二叉查找树的算法,如输入序列:23, 45, 11, 98, 16, 67, 35, 73, 53, 56, 78, 34, 0,输入为0表示序列结束。
第i列非零元素的个数为第i个顶点的入度。
解3:邻接表
顶点vi的出度是第i个链表中的结点个数,
顶点vi的入度,是所有链表中其邻接点域的值为i的结点的个数。
struct node
{ int d;
node *next;
};
node *creat(void)
{node *head,*p,*q;
int i;
head=NULL;
q=NULL;
for(i=2;i<1000;i++)
{
p=new node ;
p->d=i;
p->next=NULL;
if(head==NULL)
{ if (n = =m) printf("overflow");
else
{ if (n= =0) a[n]= b;
else
{ i=n-1;
while((i>=0)&&(a[i]>b))
{ a[i+1]=a[i];i=i-1;}
a[i+1]= b;
}
n=n+1;
}
return n;
}
5.编写一个算法,将两个线性表合并成一个有序表。
}
16.设一棵完全二叉树具有500个结点。问该完全二叉树有多少个叶子结点?有多少个度为2的结点?有多少个度为1的结点?若完全二叉树有501个结点,再回答上述问题,并说明理由。
(1)叶子结点:250
度为2的结点:249
度为1的结点:1wk.baidu.com
因为总的结点数是偶数,第一层为一个结点,中间各层均为偶数个结点,因此最后一层是奇数个结点,可知叶子结点只有1个。由性质知,度为0的结点数比度为2的结点数多1,则可推导出上述结论。
(2)同理可得
叶子结点:251
度为2的结点:250
度为1的结点:0
17.以先序遍历法访问某二叉树各结点的顺序是ABDHEICFJK,以中序遍历法访问该二叉树结点的顺序是DHBEIACJFK,要求:
(1)请还原该二叉树;
(2)写出后序遍历结果。
(1)
(2)HDJEBJKFCA
18.以后序遍历法访问某二叉树各结点的顺序是FHIGDEBCA,以中序遍历法访问该二叉树结点的顺序是FDHGIBEAC,要求:
参考答案:
void merge(int a[ ],int b[ ],int c[ ],int m,int n)
{int i,j,k;
i=j=k=0;
while(i<m&&j<n)
if(a[i]<=b[j])
c[k++]=a[i++];
else c[k++]=b[j++];
while(i<m)
c[k++]=a[i++];
{int i,j,k=1,t=0;
for(i=0;i<m;i++)
for(j=0;j<n;j++)
if(a[i][j]!=0)
{t=t+1;
b[k][0]=i;
b[k][1]=j;
b[k++][2]=a[i][j];
}
b[0][0]=m;b[0][1]=n;b[0][2]=t;
return k; //k为三列二维数组中的行数
}
int gcd(int x, int y)
{int a, b, t, r;
a=x; b=y;
if (a<b)
{ t=a; a=b; b=t; }
if(a%b==0) return b;
else gcd(b, a%b);
}
2.编写将一个十进制整数转换成二进制数的递归算法。
参考答案:
void dec_to_bin(int num,int base)//base为2