C++课本的练习题及答案(第五章)
第五章练习题
1.语句 cout<<(1&2)<<","<<(1&&2)<<endl; 的输出结果是( )。
(A)0, 0 (B)0, 1 (C)1, 0 (D)1, 1
2.语句 cout<<(1|2)<<","<<(1||2)<<endl; 的输出结果是( )。
(A)0, 0 (B)1, 1 (C)2, 0 (D)3, 1
3.语句 cout<<(3<<3)<<endl; 的输出结果是( )。
(A)24 (B)12 (C)9 (D)6
4.语句 cout<<(24>>3)<<endl; 的输出结果是( )。
(A)12 (B)9 (C)6 (D)3
5.语句 cout<<(2^5)<<endl; 的输出结果是( )。
(A)1 (B)3 (C)7 (D)10
【解答】 B D A D C
二、程序练习
使用按位异或(^)运算,可以不需要中间变量,快速交换两个变量的值。设计一个函数,实现快速交换两个长度相同整型数组元素的值。
【解答】
voidSwap(int * Aary, int * Bary , int n)
{
for(int i=0; i<n; i++)
{
Aary[i]=Aary[i]^Bary[i];
Bary[i]=Aary[i]^Bary[i];
Aary[i]=Aary[i]^Bary[i];
}
}
一、选择题
设有
unsigned A, B; //表示两个集合
unsigned x; //表示集合元素
1.实现集合运算A∪B运算的对应表达式是( )。
(A)A|B (B)A&B (C)A&(~(A&B)) (D)A|B==B
2.实现集合运算A&B运算的对应表达式是( )。
(A)A|B (B)A&B (C)A&(~(A&B)) (D)A|B==B
3.实现集合运算A-B运算的对应表达式是( )。
(A)A|B (B)A&B (C)A&(~(A&B)) (D)A|B==B
4.实现集合运算AB运算的对应表达式是( )。
(A)A|B (B)A&B (C)A&(~(A&B)) (D)A|B==B
5.实现集合运算求补集~A运算的对应表达式是( )。
(A)~A (B)A==0 (C)A&(~(A&B)) (D)1<<(x-1)&A==1<<(x-1)
6.判断元素x∈A对应的表达式是( )。
(A)~A (B)A==0 (C)A&(~(A&B)) (D)1<<(x-1)&A==1<<(x-1)
【解答】 A B C D D
二、程序练习
设计一个函数:
int count( unsigned S );
计算由无符号整数S表示的集合中包含的元素个数。
【解答】
int count(unsigned S )
{
unsigned bitMask = 1<<31, t=0;
for(unsigned c=1; c<=32; c++)
{
if(S&bitMask)
t++;
S<<=1;
}
return t;
}
一、选择题
1.有以下说明语句,则对应正确的赋值语句是( )。
structpoint
{int x; int y; }p;
(A)point.x = 1; point.y = 2; (B)point={ 1, 2 };
(C)p.x = 1; p.y = 2; (D)p = { 1, 2 };
2.已知有职工情况结构变量emp定义如下,则对emp中的birth正确赋值方法是( )。
struct Date
{ int year;
intmonth;
int day;
};
strnct Employee
{ char name[20];
long code;
Datebirth
};
Employee emp;
(A)year=1980; month=5; day=1;
(B)birth.year=1980; birth.month=5; birth.day=1;
(C)emp.year=1980; emp.month=5; emp.day=1;
(D)emp.birth.year=1980; emp.birth.month=5; emp.birth.day=1;
3.有以下说明语句,则叙述正确的是( )。
struct Point
{ int x;
int y;
};
(A)正确的结构类型说明 (B)正确的结构变量说明
(C)错误的原因是结构中成员类型相同 (D)无意义的说明
4.有以下说明语句,则下列错误的引用是( )。
struct Worker
{ int no;
char name[20];
};
Worker w, *p =&w;
(A)w.no (B)p->no (C)(*p).no (D)*p.no
5.s1和s2是两个结构类型变量,若要使赋值s1=s2合法,则要求( )。
(A)s1只接收s2中相同类型的数据成员
(B)s1和s2中的数据成员个数相同
(C)s1和s2是同一结构类型的变量
(D)s1和s2是存储字节长度一样的变量
【解答】 C D A D C
二、程序练习
1.阅读程序,写出运行结果。
#include <iostream>
using namespace std;
struct Data
{ int n;
doublescore;
};
int main()
{ Data a[3] = { 1001,87,1002,72,1003,90 }, *p =a;
cout<< (p++)->n << endl;
cout<< (p++)->n << endl;
cout<< p->n++ << endl;
cout<< (*p).n++ << endl;
}
【解答】
2.阅读程序,写出运行结果。
#include <iostream>
using namespace std;
struct Employee
{ char name[ 20 ];
charsex;
};
void fun( Employee *p )
{ if( (*p).sex == 'm' )
cout << (*p).name << endl;
}
int main()
{ Employee emp[5] = { "Liming", 'm',"Wangxiaoping", 'f', "Luwei", 'm' };
int i;
for(i=0; i<3; i++ )
fun( emp+i );
}
【解答】
3.编写程序,定义一个表示 ( x, y ) 坐标点的结构类型:
struct Point{ int x; inty; };
main函数输入两个坐标点的值。函数:
int Line(Point a, Pointb);
判断两点的连线是否为水平线、垂直线或斜线。
【解答】
#include<iostream>
#include <iomanip>
using namespace std;
struct Point
{
int x;
int y;
};
int Line(Point a, Point b)
{
if(a.x==b.x) return 1;
if(a.y==b.y) return 2;
return 0;
}
int main()
{
Point a,b;
cout<<"输入第一点坐标值:\n";
cout<<"x ="; cin>>a.x;
cout<<"y ="; cin>>a.y;
cout<<"输入第二点坐标值:\n";
cout<<"x ="; cin>>b.x;
cout<<"y ="; cin>>b.y;
int t=Line(a,b);
if(t==1)
cout<<"这是一条水平线\n";
else
if(t==2)
cout<<"这是一条垂直线\n";
else
cout<<"这是一条斜线\n";
}
一、选择题
1.有以下说明语句,则正确的赋值语句是( )。
struct Point
{ double x;
double y;
};
Point pp[3];
(A)pp[0]={0,0} (B)pp.x= pp.y=1;
(C)pp[2]->x= pp[2]->y=2; (D)pp[3].x=3; pp[3].y=3
2.有以下说明语句,则引用形式错误的是( )。
struct Student
{ int num;
doublescore;
};
Studentstu[3]={{1001,80}, {1002,75}, {1003,91}}, *p=stu;
(A)p->num (B)(p++).num (C)(p++)->num (D)(*p).num
【解答】 D B
二、程序练习
1.阅读程序,写出运行结果。
#include <iostream>
using namespace std;
struct Node
{ char * s;
Node *q;
};
int main()
{ Node a[ ] = { { "Mary", a+1 }, {"Jack", a+2 }, { "Jim", a } };
Node*p = a;
cout<< p->s << endl;
cout<< p->q->s<< endl;
cout<< p->q->q->s << endl;
cout<< p->q->q->q->s << endl;
}
【解答】
2.编写程序,定义点结构类型:
struct Point{ int x; inty; };
从键盘输入若干个点的数据,存放在结构数组中。函数:
int Line(Point ary[], intn);
判断这些点是否在一条水平线或垂直线上。
【解答】
#include<iostream>
#include <iomanip>
using namespace std;
struct Point
{
int x;
int y;
};
int Line(Point ary[], int n)
{
int i, t1=0, t2=0;
for( i=0; i<n-1; i++)
{
t1+=ary[i].x==ary[i+1].x;
t2+=ary[i].y==ary[i+1].y;
}
if(t1==n-1) return 1;
if(t2==n-1) return 2;
return 0;
}
int main()
{
const int N=3;
Point ary[N];
for(int i=0; i<N; i++)
{
cout<<"输入第"<<i+1<<"点坐标值:\n";
cout<<"x ="; cin>>ary[i].x;
cout<<"y ="; cin>>ary[i].y;
}
int t=Line(ary, N);
if(t==1)
cout<<"构成一条水平线\n";
else
if(t==2)
cout<<"构成一条垂直线\n";
else
cout<<"不能构成水平线或垂直线\n";
}
一、选择题
有说明语句:
Struct Node{ int data;Node * next; };
Node *head, *p,*q, *s;
并且,head是单向链表的头指针,p指向链表中的节点,q指向*p的前驱节点。
1.在*p之后插入节点*s的操作是( )。
(A)p->next=s; s->next=p->next; (B)s->next=p-next; p->next=s;
(C)p =s->next; s =p->next; (D)s =p->next; p =s->next;
2.在*p之前插入节点*s的操作是( )。
(A)q =s->next; s =p->next; (B)q->next=s; s->next=p;
(C)s=p->next; q=s->next; (D)s->next=p; q->next=s;
3.在*hear之前插入节点*s的操作是( )。
(A)s->next=head; head=s; (B)s->next=head->next; head->next=s;
(C)head=s; s->next=head; (D)head->next=s; s->next=head->next;
4.删除*p节点的操作是( )。
(A)q = p; delete p; (B)p = q; delete q;
(C)q->next=p->next; delete p; (D)p->next = q->next; delete q;
5.删除*(head->next)的操作是( )。
(A)p=head->next; head->next=head->next->next; delete p;
(B)head->next=head->next->next; p=head->next; delete p;
(C)p=head; head=head->next; delete p;
(D)head=head->next; p=head; delete p;
【解答】 B D A C A
二、程序练习
有以下声明语句和主函数。其中Create函数从键盘输入整数序列,以输入0为结束,按输入逆序建立一个以head为表头的单向链表。程序在main函数调用Create建立链表,调用ShowList函数验证链表。例如,输入序列为1 2 3 4 5 0,建立的链表是5 4 3 2 1。补充程序中的Create函数和ShowList函数。
#include<iostream>
using namespace std;
struct Node{int data;Node * next;};
void Create(Node*&head);
void ShowList(Node*head);
void main()
{ Node *head=new Node;
head=NULL;
cout<<"输入链表元素,以输入 0 结束:\n";
Create(head);
cout<<"输出逆向链表\n";
ShowList(head);
}
【解答】
void Create(Node *&head)
{
Node *p;
p = new Node ;
cin>>p->data;
while(p->data!=0)
{
if(head==NULL)
{ head=p;head->next=NULL; }
else
{
p->next= head;
head =p;
}
p=new Node;
cin>>p->data;
}
}
void ShowList(Node *head)
{
cout << "now theitems of node are: \n";
while( head )
{
cout <<head->data << '\t';
head = head->next;
}
cout << endl;
}
综合练习
一、思考题
1.判断一个整数n的奇偶性,可以利用位运算吗?请你试一试。
【解答】
可以。一个整数当最低位为1时,它是奇数,否则为偶数。以下函数返回对参数k的奇偶判断。
bool odd( int k )
{
return 1&k;
}
2.长度为N的数组可以表示N个元素的集合,若有 S[i]==1,表示对应元素在集合中,如何实现集合的基本运算?请你试一试。并从内存和处理要求上与5.2.2节中集合的实现方法进行比较。
【解答】
长度为N的数组S可以表示有N个元素的集合。当S[i]==1,表示元素i+1在集合中;当S[i]==0,表示元素i+1不在集合中。集合运算通过对数组元素操作完成。
用数组实现集合,每一个数组元素只能表示一个集合元素,运算的空间和时间消耗高于用无符号整数和位运算实现集合运算。
用数组实现集合运算程序如下。
#include<iostream>
using namespacestd;
void setPut(unsigned *S ); //输入集合S的元素
void setDisplay(const unsigned *S ); //输出集合S中的全部元素
bool putX(unsigned *S, unsigned x ); //元素x并入集合
void Com( unsigned *C, const unsigned *A, constunsigned *B); //求并集C=A∪B
void setInt( unsigned *C, const unsigned A, const unsignedB); //求交集C=A∩B
void setDif(const unsigned A, const unsigned B ); //求差集C=A-B
bool Inc( constunsigned *A, const unsigned *B ); //判蕴含
bool In( constunsigned *S, const unsigned x ); //判属于x∈S
bool Null( constunsigned *S ); //判空集
const int N=32;
//输入集合元素
voidsetPut(unsigned *S)
{ unsigned x;
cin >> x;
while( x>0&&x<=N)
{ putX(S, x ); //把输入元素并入集合S
cin>> x;
}
}
//输出集合S中的全部元素
void setDisplay(const unsigned *S )
{ cout <<"{ ";
if (Null(S))
cout<<" }\n";
else
{ for(int i=0; i<N; i++ ) //输出元素
{
if( S[i] )
cout << i+1 <<", ";
}
cout<< "\b\b }\n"; //擦除最后的逗号
}
return;
}
//元素x并入集合S
bool putX(unsigned *S, unsigned x )
{if(x>0&&x<=N)
{ S[x-1] = 1;
return true;
}
return false;
}
//求并集C=A∪B
void Com( unsigned *C, const unsigned *A, constunsigned *B )
{ for( int i=0; i<N;i++ )
C[i]=int( A[i] || B[i] ) ;
}
//求交集C=A∩B
void setInt(unsigned *C, const unsigned *A, const unsigned *B )
{ for( int i=0;i<N; i++ )
C[i]=int( A[i]&&B[i] ) ;
}
//求差集C=A-B
void setDif( unsigned *C, const unsigned *A, constunsigned *B )
{ for( int i=0;i<N; i++ )
C[i]=int( A[i]&&!(A[1]&&B[i]) ) ;
}
//判蕴含,A蕴含于B时返回true
bool Inc( constunsigned *A, const unsigned *B )
{ for(int i=0;i<N; i++)
{ if(A[i]&&!B[i])
return false;
}
return true;
}
//判属于,x∈S时返回true
bool In( constunsigned *S, const unsigned x )
{ return S[x-1];
}
//判空集,S为空集时返回true
bool Null( constunsigned *S )
{ for( int i=0;i<N; i++)
{ if( S[i])
return false;
}
return true;
}
int main()
{ unsignedA[N]={0}, B[N]={0}, C[N]={0};
unsigned x;
cout << "Input the elements of setA, 1-"<<N<<", until input 0 :\n";
setPut( A );
cout << "Input the elements of setB, 1-"<<N<<", until input 0 :\n";
setPut( B );
cout<<"A = ";
setDisplay( A );
cout<<"B = ";
setDisplay( B );
cout << "Input x: ";
cin>>x;
cout << "Put " << x<< " in A = ";
putX( A, x) ;
setDisplay(A);
cout << "C = A+B = ";
Com( C, A, B );
setDisplay( C );
cout << "C = A*B = ";
setInt( C, A, B );
setDisplay( C );
cout << "C = A-B = ";
setDif( C, A, B );
setDisplay( C );
if( Inc( A, B ) )
cout<< "A <= B is true\n";
else
cout<< "not A <= B\n";
cout << "Input x: ";
cin >> x;
if( In( A, x ) )
cout<< x << " in A\n";
else
cout<< x << " not in A\n";
}
3.分析以下说明结构的语句:
struct Node
{ int data;
Nodeerror; //错误
Node *ok; //正确
};
error和ok分别属于什么数据类型?有什么存储要求?error出错的原因是什么?
【解答】
error是Node结构类型数据成员,错误。原因是结构定义的数据成员若为本身的结构类型,是一种无穷递归。ok是指向Node类型的指针,定义正确,占4字节。
4.例5-15中用辅助数组对结构数组进行关键字排序,有定义:
person *index[100];
index数组存放结构数组元素的地址。如果把index定义改为:
int index[100];
用于存放结构数组元素的下标,可以实现对结构数组的索引排序吗?如何修改程序?请你试一试。
【解答】
可以。关键是通过整型索引数组元素作为下标访问结构数组。表示为:
all[pi[i]].name all[pi[i]].id all[pi[i]].salary
有关程序如下:
#include<iostream>
usingnamespace std;
structperson //说明结构类型
{
charname[10];
unsigned int id;
double salary;
};
voidInput( person[], const int );
voidSort( person[], int[],const int );
voidOutput( const person[], int[],const int );
intmain()
{
personallone[100] ; //说明结构数组
int index[100]; //说明索引数组
int total ;
for(int i=0; i<100; i++) //索引数组元素值初始化为结构数组元素下标
index[i]=i ;
cout<<"输入职工人数:";
cin>>total;
cout<<"输入职工信息:\n";
Input(allone,total);
cout<<"以工资做关键字排序\n";
Sort(allone,index, total);
cout<<"输出排序后信息:\n";
Output(allone,index,total);
}
voidInput( person all[], const int n )
{
inti ;
for( i=0; i<n; i++ ) // 输入数据
{
cout<<i<<":姓名:";
cin>>all[i].name;
cout<<"编号:";
cin >> all[i].id;
cout<<"工资:";
cin >> all[i].salary ;
}
}
voidSort(person all[], int pi[], const int n)
{
int i,j;
int t; //交换用中间变量
for(i=1; i<n; i++) //以成员salary做关键字排序
{
for(j=0;j<=n-1-i; j++)
if(all[pi[j]].salary>all[pi[j+1]].salary) //通过索引数组访问结构数组元素
{
t=pi[j]; //交换索引数组元素值
pi[j]=pi[j+1];
pi[j+1]=t;
}
}
}
voidOutput(const person all[], int pi[], const int n)
{
for( int i=0; i<n; i++ ) // 输出排序后数据
cout<<all[pi[i]].name<<'\t'<<all[pi[i]].id<<'\t'<<all[pi[i]].salary<<endl;
}
5.有以下结构说明和遍历单向链表的函数。函数内有错误吗?是什么性质的错误?请上机验证你的分析。
struct Node
{ int data;
Node *next;
};
void ShowList( Node *head)
{ while( head )
{ cout<< head->date << '\n';
head++;
}
}
【解答】
head++错误,原因是动态链表的结点存放不是连续顺序的内存空间,它们是逐个结点通过new建立的,所以不能用++做地址偏移运算。应该用:
head=head->next;
二、程序设计
1.编写程序,将一个整型变量右移4位,并以二进制数形式输出该整数在移位前和移位后的数值。观察系统填补空缺的数位情况。
【解答】
#include<iostream>
using namespacestd;
voidbitDisplay(unsigned value);
int main()
{
unsigned x;
cout << "Enter an unsigned integer:";
cin >> x;
bitDisplay(x);
x>>=4;
cout<<"Right 4-bit\n";
bitDisplay(x);
}
voidbitDisplay(unsigned value)
{
unsigned c;
unsigned bitmask = 1<<31;
cout << value << " =\t";
for( c=1; c<=32; c++ )
{
cout << ( value&bitmask ? '1': '0' );
value <<= 1;
if( c%8 == 0 )
cout << ' ';
}
cout << endl;
}
2.整数左移一位相当于将该数乘以2。编写一个函数:
unsigned power2( unsignednumber, unsigned pow );
使用移位运算计算number*2pow,并以整数形式输出计算结果。注意考虑数据的溢出。
【解答】
unsigned power2( unsigned number, unsigned pow )
{
unsigned c=1;
unsigned bitmask = 1<<31;
while(c<31) //溢出判断
{
if( number&bitmask )break; //查找最高位的1
c++;
bitmask>>=1;
}
if(pow<c)
return number<<pow;
else
{
cout<<"overflow!\n";
return 0;
}
}
3.设计重载函数,使用按位异或(^)运算,实现快速交换两个整型变量和浮点型变量的值。
【解答】
void swap (int &a, int &b)
{
a=a^b;
b=a^b;
a=a^b;
}
void swap(double &x,double &y)
{
int*xp,*yp;
xp = (int*)(&x);
yp = (int*)(&y);
*xp=(*xp)^*(yp); *yp=(*xp)^(*yp); *xp=(*xp)^(*yp);
xp++; yp++;
*xp=(*xp)^*(yp); *yp=(*xp)^(*yp); *xp=(*xp)^(*yp);
}
4.设计函数,不使用辅助数组,实现两个int类型或double类型数组的数据快速交换。
【解答】
void Swap(char * Aary, char * Bary , int n)
{
for(int i=0; i<n; i++)
{
Aary[i]=Aary[i]^Bary[i];
Bary[i]=Aary[i]^Bary[i];
Aary[i]=Aary[i]^Bary[i];
}
}
以上函数使用char*,字节指针做数组参数,对于不同类型的数组,调用函数时,只需要对实参地址做指针类型转换,并且设定参数n对应的实参是交换数据的总字节数。例如,交换double类型数组的数据可以有以下方式:
const int N=100;
double x[N];
double y[N];
//……
Swap((char*)x,(char*)y,sizeof(double)*N);
5.集合的元素通常是字符。设计程序,用无符号整数表示ASCII码字符集合,用位运算实现各种基本集合运算。
【解答】
ASCII码是0~127的整数,可以用长度为4的无符号整型数组表示集合,如教材例5-6所示。区别是,在输入集合元素时,需要把字符转换成整型数据,在输出操作中,把整型集合元素转换成字符型数据。
程序略。
6.使用结构类型表示复数。设计程序,输入两个复数,可以选择进行复数的+、-、×或÷运算,并输出结果。
【解答】
#include<iostream>
#include<iomanip>
usingnamespace std;
struct complex
{
double re, im;
};
int main()
{
complex a,b,c; char oper;
cout << "输入复数a的实部和虚部: ";
cin >> a.re >>a.im;
cout << "输入复数b的实部和虚部:";
cin >> b.re >>b.im;
cout << "输入运算符: ";
cin >> oper;
switch ( oper )
{
case '+': c.re=a.re+b.re; c.im=a.im+b.im;
break;
case '-': c.re=a.re-b.re; c.im=a.im-b.im;
break;
case '*': c.re=a.re*b.re-a.im*b.im;
c.im=a.im*b.re+a.re*b.im;
break;
case '/': c.re=(a.re*b.re+a.im*b.im)/(b.re*b.re+b.im*b.im);
c.im=(a.im*b.re-a.re*b.im)/(b.re*b.re+b.im*b.im);
break;
default: cout<< "input error!" << endl;
return 0;
}
cout << "c=" << c.re;
cout << setiosflags( ios::showpos );
cout << c.im << "i" << endl;
return 0;
}
7.把一个班的学生姓名和成绩存放到一个结构数组中,寻找并输出最高分者。
【解答】
#include <iostream>
using namespace std;
struct data
{
char name[12];
double score;
};
double searchMax(data *a, int n );
int main()
{
data stu[ ] = {"李小平",90,"何文章",66,"刘大安",87,"汪立新",93,"罗建国",78,
"陆丰收",81,"杨勇",85,"吴一兵",55,"伍晓笑",68,"张虹虹",93};
double max;
int n=sizeof(stu) /sizeof(data);
max=searchMax(stu, n);
for( int i=0; i<n; i++ )
if( stu[i].score ==max )
cout<<stu[i].name <<'\t'<< stu[i].score<<endl;
}
double searchMax(data *a, int n )
{
int i;
double max=a[0].score;
for( i=1; i<n; i++ )
if( a[i].score > max ) max = a[i].score;
return max;
}
8.使用结构表示X-Y平面直角坐标系上的点,编写程序,顺序读入一个四边形的4个顶点坐标,判别由这个顶点的连线构成的图形是否为正方形、矩形或其他四边形。要求:定义求两个点距离的函数使用结构参数。
【解答】
#include<iostream>
#include<cmath>
usingnamespace std;
struct point
{
double x;
double y;
};
double d( point p1, point p2 )
{
return sqrt( pow( p1.x-p2.x,2 )+pow( p1.y-p2.y,2 ) );
}
int main()
{
int i; point p[5];
for( i=1; i<=4; i++ )
{ cout << "输入第"<< i << "个顶点的横坐标和纵坐标:";
cin >> p[i].x >> p[i].y;
}
if( fabs( d( p[1],p[2] ) - d( p[3],p[4] ))<=1e-8
&& fabs( d( p[1],p[4] ) - d( p[2],p[3] ))<=1e-8
&& fabs( d( p[1],p[3] ) - d( p[2],p[4] ))<=1e-8)
if( fabs( d( p[1],p[2] ) - d( p[2],p[3] ))<1e-8 )
cout << "四个顶点构成的图形为正方形!"<< endl;
else cout << "四个顶点构成的图形为矩形!"<< endl;
else cout << "四个顶点构成的图形为其它四边形!"<< endl;
}
9.建立一个结点包括职工的编号、年龄和性别的单向链表,分别定义函数完成以下功能:
(1)遍历该链表输出全部职工信息;
(2)分别统计男、女职工的人数;
(3)在链表尾部插入新职工结点;
(4)删除指定编号的职工结点;
(5)删除年龄在60岁以上的男性职工或55岁以上的女性职工结点,并保存在另一个链表中。
要求:用主函数建立简单菜单选择,并测试程序。
【解答】
#include<iostream>
usingnamespace std;
struct employee
{
int num;
int age;
char sex;
employee *next;
};
employee *head, *head1;
//建立单向链表
employee *create()
{
employee *head, *p, *pend;
char ch;
head = NULL;
cout << "\t输入数据?(y/n)";cin >> ch;
if( ch == 'y' )
{
p= new employee;
cout << "\t编号:"; cin >> p->num;
cout << "\t年龄:"; cin >> p->age;
cout << "\t性别:"; cin >> p->sex;
}
else
goto L0;
while( ch == 'y' )
{
if( head == NULL ) head = p;
else pend->next = p;
pend = p;
cout << "\t输入数据?(y/n)"; cin>>ch;
if( ch == 'y' )
{
p= new employee;
cout << "\t编号:"; cin >> p->num;
cout << "\t年龄:"; cin >> p->age;
cout << "\t性别:"; cin >> p->sex;
}
}
pend->next = NULL;
L0: return head;
}
//显示单向链表中全部职工信息
void show( employee *head )
{
employee *p = head;
if( !head ) { cout << "\t空链表!" << endl; goto L1; }
cout << "\t链表中的数据是:\n";
while( p )
{
cout << '\t' << p->num <<"," << p->age << "," << p->sex<< endl;
p = p->next;
}
L1:
}
//统计男女职工人数
void count( employee *head )
{
employee *p = head;
int m, f;
m= 0; f = 0;
while( p )
{
if( p->sex == 'm' )
m++;
else
f++;
p = p->next;
}
cout << "\t男职工人数:"<< m << endl;
cout << "\t女职工人数:"<< f << endl;
}
//在链表尾部插入新结点
employee *insert()
{
employee *pend = head, *p;
//在空链表尾部插入新结点
if( !head )
{
p = new employee;
cout << "\t编号:"; cin >> p->num;
cout << "\t年龄:"; cin >> p->age;
cout << "\t性别:"; cin >> p->sex;
head = p;
p->next = NULL;
return head;
}
//在链表尾部插入新结点
while( pend->next != NULL )
{
pend = pend->next;
}
p= new employee;
cout << "\t编号:"; cin >> p->num;
cout << "\t年龄:"; cin >> p->age;
cout << "\t性别:"; cin >> p->sex;
pend->next = p;
pend = p;
pend->next = NULL;
return head;
}
//删除指定编号的结点
employee *del( int bh )
{
employee *p, *q;
if ( !head )
{
cout << "\t空链表!" << endl;
goto L2;
}
//删除链首结点
if( head->num == bh )
{
p= head;
head = head->next;
delete p;
cout << "\t结点已被删除!" << endl;
goto L2;
}
//删除非链首结点
q= head;
while( q->next != NULL )
{
if ( q->next->num == bh )
{
p= q->next; //待删除结点
q->next = p->next;
delete p;
cout << "\t结点已被删除!"<< endl;
goto L2;
}
q = q->next;
}
cout << "\t找不到需删除结点!"<< endl;
L2: return ( head );
}
//删除指定年龄段的结点,并把被删除结点保存在另一链表中
employee *delcreate()
{
employee *p, *pd, *p1, *q;
int flag;
//建立新链表
if ( head == NULL )
{
cout << "\t空链表!" << endl;
goto L3;
}
head1 = NULL;
pd = new employee;
p= head;
flag = 0;
while ( p != NULL )
{
if( p->age >= 55 &&p->age <=60 )
{
pd->num = p->num;
pd->age = p->age;
pd->sex = p->sex;
if( head1 == NULL )
head1 = pd;
else
p1->next = pd;
p1 = pd;
pd = new employee;
flag = 1;
}
p = p->next;
}
if ( flag == 0 )
{cout << "\t没有需删除的结点!"<< endl; goto L3; }
p1->next = NULL;
//显示新链表
cout <<"\t新链表中的数据是: \n";
p = head1;
while( p )
{
cout << '\t' << p->num <<"," << p->age << "," << p->sex<< endl;
p = p->next;
}
//删除指定年龄的结点
p = head;
q = p;
while ( p != NULL )
{
if( p->age >= 55 && p->age<= 60)
if( head->age == p->age )
{
pd = head; //待删除结点
head = head->next;
deletepd;
p= head;
continue;
}
else
if(p->next == NULL )
{
pd= p; //待删除结点
q->next = NULL;
delete pd;
goto L3;
}
else
{
pd = p; //待删除结点
q->next = p->next;
delete pd;
p = q->next;
continue;
}
q = p;
p = p->next;
}
L3: return ( head );
}
int main()
{
int choice, bh ;
L:
cout << "\n\t\t请键入操作选择\n" << endl;
cout << "\t 1 --- 建立单向链表" << endl;
cout << "\t 2 --- 显示单向链表中全部职工信息" << endl;
cout << "\t 3 --- 统计男女职工人数" << endl;
cout << "\t 4 --- 在职工尾部插入新结点" << endl;
cout << "\t 5 --- 删除指定编号的结点" << endl;
cout << "\t 6 --- 删除指定年龄的结点,并把被删除结点保存在另一链表中" << endl;
cout << "\t 0 --- 退出" << endl ;
cout << "\t\t";
cin >> choice ;
switch ( choice )
{
case 1 : head = create() ; goto L ;
case 2 : show( head ); goto L ;
case 3 : count( head ); goto L;
case 4 : head = insert(); goto L;
case 5 : cout << "\t输入需删除结点编号:";
cin >> bh;
head = del( bh ); goto L;
case 6 : head = delcreate(); goto L;
case 0 : cout << " \t退出程序的运行!\n" << endl ; break ;
default : cout << "\t输入错误,请重新输入!\n" << endl ; goto L;
}
}
10.输入一行字符,按输入字符的反序建立一个字符结点的单向链表,并输出该链表中的字符。
【解答】
#include<iostream>
usingnamespace std;
struct node
{
char ch;
node *next;
};
void show( node *head );
int main()
{
node *head, *p;
char c;
head = NULL;
while( (c = getchar()) != '\n' ) //输入一行字符
{
p= new node; //建立新结点
p->ch = c;
p->next = head; //插入表头
head=p;
}
show(head);
}
void show( node *head ) //输出链表
{
node *p = head;
cout << "链表中的字符是:\n";
while( p )
{ cout << p->ch;
p = p->next;
}
cout << endl;
}
11.设有说明语句:
struct List { intdata; List * next; };
List *head;
head是有序单向链表的头指针。请编写函数:
void Count( List * head);
计算并输出链表数据相同值的结点及个数。例如,若数据序列为:
2 3 3 3 4 5 5 6 6 6 6 7 89 9
则输出结果为:
data number
3 3
5 2
6 4
9 2
可以用例5-18的程序生成有序链表,测试Count函数。
【解答】略
12.用带头结点的有序单向链表可以存放集合,如图5.16所示。头结点不存放集合元素,仅为操作方便而设置。使用这种数据结构,设计集合的输入、输出和各种基本运算的函数。
图5.16 带头结点的有序单向链表
【解答】略
推荐阅读
全部习题章节:
C++课本的练习题及答案(第四章)
C++课本的练习题及答案(第五章)
C++课本的练习题及答案(第六章)
C++课本的练习题及答案(第七章)
C++课本的练习题及答案(第八章)