深大OJ——数据结构专项——基础练习


基础练习(C语言版)

A. 月份查询(指针数组)

题目描述

已知每个月份的英文单词如下,要求创建一个指针数组,数组中的每个指针指向一个月份的英文字符串,要求根据输入的月份数字输出相应的英文单词

1月 January

2月 February

3月 March

4月 April

5月 May

6月 June

7月 July

8月 Aguest

9月 September

10月 October

11月 November

12月 December

输入

第一行输入t表示t个测试实例

接着每行输入一个月份的数字

依次输入t行

输出

每行输出相应的月份的字符串,若没有这个月份的单词,输出error

输入样例1

3
5
11
15

输出样例1

May
November
error

代码如下:

#include<iostream>
using  namespace std;
int main(){
    char*p[12]={"January","February","March","April","May","June","July","Agust","September","October","November","December"};
    int t;
    cin>>t;
    while(t--){
    int num;
    cin>>num;
    if(num<1||num>12) cout<<"error"<<endl;
    else
    cout<<p[num-1]<<endl;
    }
}

B. 成绩查询(指针运算)

题目描述

已知一组学生成绩,然后根据输入的序号查询成绩

要求:

  1. 使用一个整数数组存储学生成绩

  2. 使用一个指针指向数组中间元素

  3. 使用++和–运算符,求出数组中间元素的前一个成绩和后一个成绩

  4. 输入一个序号,然后计算这个序号的元素和中间元素的距离,然后使用指针去访问

例如有11个学生,指针指向中间的学生也就是第6个学生,若输入序号3,即查询第3个学生的成绩,第3和第6之间距离为3,那么指针应该怎么运算呢???

  1. 整个程序除了输入时可以使用数组下标,其他部分都不能使用,都必须使用指针进行访问,且只能定义一个指针变量。

输入

第一行输入t表示有t个测试实例

第二行先输入n,表示有n个学生,然后再输入n个成绩(正整数)

第三行输入1个序号,表示要查询成绩的学生的序号。

依次输入t个实例

按自然意义,序号是从1开始计算

提示:在数组中是从…

输出

对于每个测试实例:

第一行输出数组中间元素的前一个成绩和后一个成绩(若为偶数,取中间右边的数为中间数)

第二行根据序号输出1个成绩

输入样例1

2
7 66 99 88 44 77 33 11
2
10 60 80 50 20 90 35 70 40 10 95
10

输出样例1

88 77
99
90 70
95

代码:

#include<stdio.h>
int main()
{
	int T,i,num,n;
	scanf("%d",&T);
	while(T--){
		scanf("%d",&num);
		int a[100],mid,last ,later;
		int *p1=a,*p2=a,*p3=a,*t;
		for(i=0;i<num;i++)
			scanf("%d",&a[i]);
	    scanf("%d",&n);
	    t=p1+num/2;
	    mid=*(p1+num/2);
	    last=*(--t);
	    t++;
	    later=*(++t);
	    printf("%d %d\n",last,later);
	    printf("%d\n",*(p3+n-1));
	    p1=a;p2=a;p3=a;
	}
}

C.Date(类与对象)

题目描述

下面是一个日期类的定义,请在类外实现其所有的方法,并在主函数中生成对象测试之。
在这里插入图片描述
注意,在判断明天日期时,要加入跨月、跨年、闰年的判断

例如9.月30日的明天是10月1日,12月31日的明天是第二年的1月1日

2月28日的明天要区分是否闰年,闰年则是2月29日,非闰年则是3月1日

输入

测试数据的组数t

第一组测试数据的年 月 日

要求第一个日期的年月日初始化采用构造函数,第二个日期的年月日初始化采用setDate方法,第三个日期又采用构造函数,第四个日期又采用setDate方法,以此类推。

输出

输出今天的日期

输出明天的日期

输入样例1

4
2012 1 3
2012 2 28
2012 3 31
2012 4 30

输出案例

Today is 2012/01/03
Tomorrow is 2012/01/04
Today is 2012/02/28
Tomorrow is 2012/02/29
Today is 2012/03/31
Tomorrow is 2012/04/01
Today is 2012/04/30
Tomorrow is 2012/05/01

#include<iostream>
#include<iomanip>

using namespace std;

class Date {
    int year, month, day;
public:
    Date();

    Date(int y, int m, int d);

    int getYear();

    int getMonth();

    int getDay();

    int jud();

    void setDate(int y, int m, int d);

    void print1();

    void print2();

    void addOneDay();
};

Date::Date() {
    year = 1900, month = 1, day = 1;
}

Date::Date(int y, int m, int d) {
    year = y, month = m, day = d;
}

int Date::jud() {
    if ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0))
        return 1;
    else return 0;
}

int Date::getYear() {
    return year;
}

int Date::getMonth() {
    return month;
}

int Date::getDay() {
    return day;
}

void Date::setDate(int y, int m, int d) {
    year = y, month = m, day = d;
}

void Date::print1() {
    cout << "Today is " << year << '/';
    cout << setw(2) << setfill('0') << month << '/';
    cout << setw(2) << setfill('0') << day << endl;

}

void Date::print2() {
    cout << "Tomorrow is " << year << '/';
    cout << setw(2) << setfill('0') << month << '/';
    cout << setw(2) << setfill('0') << day << endl;

}

void Date::addOneDay() {
    int a[13] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
    int b[13] = {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
    if (jud()) {
        if (day < b[month]) day++;
        else {
            if (month == 12) {
                year++;
                month = 1;
                day = 1;
            } else {
                month++;
                day = 1;
            }
        }
    } else {
        if (day < a[month]) day++;
        else {
            if (month == 12) {
                year++;
                month = 1;
                day = 1;
            } else {
                month++;
                day = 1;
            }
        }
    }
}

int main() {
    int t, y, m, d;
    cin >> t;

    int i;
    for (i = 0; i < t; i++) {
        cin >> y >> m >> d;
        if (!(i % 2)) {
            Date p(y, m, d);
            p.print1();
            p.addOneDay();
            p.print2();
        } else {
            Date q;
            q.setDate(y, m, d);
            q.print1();
            q.addOneDay();
            q.print2();
        }
    }
}

D. 点圆运算

题目描述

设计一个点类Point,包含私有属性x坐标和y坐标,操作包括

1、构造函数,要求满足两个条件:1.能够使用类Point去创建一个对象数组(缺省构造方法!);2.能够接收外来输入的x和坐标做初始化,提示:构造函数重载

2、析构函数,把x坐标和y坐标都清0,并输出信息“point clear”

3、设置(setXY),接受外来输入,并设置x坐标和y坐标

4、获取x坐标,直接返回x值

5、获取y坐标,直接返回y值

设计一个圆类Circle,包含私有属性:圆心坐标x和y、半径r;操作包括:

1、构造函数,接受外来输入,设置圆心x坐标、y坐标和半径

2、析构函数,将圆心坐标x和y以及半径都清零,并输出"circle clear"

3、包含(Contain),判断一个圆是否包含一个点,计算圆心到这个点的距离,然后和半径做比较,大于则不包含,小于等于则包含。提示:用点对象做参数不一定符合输出

输入

第一行输入一个点的x坐标和y坐标,用Point类去创建一个点对象,并且自动通过构造函数来初始化

第二行输入n,用Point类去创建一个点对象数组,包含n个点

第三行起输入n行,每行输入一个点的x和y坐标,使用设置(setXY)来设置每个点的x和y坐标

接着一行输入三个参数,表示一个圆的圆心坐标x和y,以及半径,使用Circle类去创建一个圆对象,并自动通过构造函数来初始化

输出

通过调用圆的包含(Contain)方法,判断每个点是否在圆内。

按照点的输入顺序,每行输出一个点的判断结果,如果包含则输出in,不包含则输出out

说明:当一个对象数组是动态创建的,那么在程序结束时,这个数组是不会被回收。只有增加代码delete []p,才会回收数组。

!!本题目不要求回收数组!!

输入样例1

5 2
3
4 7
9 9
2 4
3 3 3

输出样例1

in
out
out
in
circle clear
point clear

#include<iostream>
#include<iomanip>
#include<cmath>
using namespace std;

class Point {
    int x, y;
public:
    Point(int xx=0, int yy=0) : x(xx), y(yy) {}

    ~Point() {
        x = 0, y = 0;
        cout << "point clear" << endl;
    }

    void setXY(int xx, int yy) {
        x = xx, y = yy;
    }

    int getX() {
        return x;
    }

    int getY() {
        return y;
    }
};
 class Circle{
     int x,y,r;
 public:
     Circle(int xx,int yy,int rr):
     x(xx),y(yy),r(rr){}
     ~Circle(){
         x=0,y=0,r=0;
         cout<<"circle clear"<<endl;
     }
     void Contain(int a,int b){
         double c;
         c=sqrt((a-x)*(a-x)+(b-y)*(b-y));
         if(c>r) cout<<"out"<<endl;
         else cout<<"in"<<endl;
     }
 };

int main() {
    int x, y, r;
    cin >> x >> y;
    Point p(x, y);
    int n, i;
    cin >> n;
    Point *q=new Point[n];
    for (i = 0; i < n; i++) {
        cin >> x >> y;
        q[i].setXY(x, y);
    }
    cin >> x >> y >> r;
    Circle s(x, y, r);
    s.Contain(p.getX(), p.getY());
    for (i = 0; i < n; i++)
        s.Contain(q[i].getX(), q[i].getY());
}

E. Point_Array

题目描述

在这里插入图片描述
上面是我们曾经练习过的一个习题,请在原来代码的基础上作以下修改:1、增加自写的拷贝构造函数;2、增加自写的析构函数;3、将getDisTo方法的参数修改为getDisTo(const Point &p);4、根据下面输出的内容修改相应的构造函数。

然后在主函数中根据用户输入的数目建立Point数组,求出数组内距离最大的两个点之间的距离值。

输入

测试数据的组数 t

第一组点的个数

第一个点的 x 坐标 y坐标

第二个点的 x坐标 y坐标

输出

输出第一组距离最大的两个点以及其距离

在C++中,输出指定精度的参考代码如下:

#include

#include //必须包含这个头文件

using namespace std;

void main( )

{ double a =3.141596;

cout<<fixed<<setprecision(3)<<a<<endl; //输出小数点后3位

输入样例1

2
4
0 0
5 0
5 5
2 10
3
-1 -8
0 9
5 0

输出样例1

Constructor.
Constructor.
Constructor.
Constructor.
The longeset distance is 10.44,between p[1] and p[3].
Distructor.
Distructor.
Distructor.
Distructor.
Constructor.
Constructor.
Constructor.
The longeset distance is 17.03,between p[0] and p[1].
Distructor.
Distructor.
Distructor.

#include<iostream>
#include<iomanip>
#include<cmath>

using namespace std;

class Point {
    double x, y;
public:
    Point() {
        x = 0, y = 0;
        cout << "Constructor." << endl;
    }

    Point(Point &p) {
        x = p.x;
        y = p.y;
        cout << "Constructor." << endl;
    }

    Point(double xx, double yy) : x(xx), y(yy) {
        cout << "Constructor." << endl;
    }

    ~Point() {
        x = 0, y = 0;
        cout << "Distructor." << endl;
    }

    void setXY(double xx, double yy) {
        x = xx, y = yy;
    }

    void setX(double xx) {
        x = xx;
    }

    void setY(double yy) {
        y = yy;
    }

    double getX() {
        return x;
    }

    double getY() {
        return y;
    }

    double getDisTo(const Point &p) {

        return sqrt((p.x - x) * (p.x - x) + (p.y - y) * (p.y - y));

    }
};


int main() {
    int t;
    cin >> t;
    while (t--) {
        int n, i, j;
        double x,y;
        cin >> n;
        Point p[n];
        for (i = 0; i < n; i++) {
            cin >> x >> y;
            p[i].setXY(x, y);
        }
        double max = 0;
        int one=0,two=0;
        for (i = 0; i < n ; i++) {
            for (j = i + 1; j < n ; j++) {
                if (p[i].getDisTo(p[j]) > max) {
                    max = p[i].getDisTo(p[j]);
                    one=i,two=j;
                }
            }
        }
        cout << "The longeset distance is " << fixed << setprecision(2) << max;
        cout << ",between " << "p[" << one << ']' << " and p[" << two << "]." << endl;
    }
}

F. 手机服务

题目描述

设计一个类来实现手机的功能。它包含私有属性:号码类型、号码、号码状态、停机日期;包含方法:构造、拷贝构造、打印、停机。

1、号码类型表示用户类别,只用单个字母,A表示政府,B表示企业、C表示个人

2、号码是11位整数,用一个字符串表示

3、号码状态用一个数字表示,1、2、3分别表示在用、未用、停用

4、停机日期是一个日期对象指针,在初始化时该成员指向空,该日期类包含私有属性年月日,以及构造函数和打印函数等


5、构造函数的作用就是接受外来参数,并设置各个属性值,并输出提示信息,看示例输出

6、拷贝构造的作用是复制已有对象的信息,并输出提示信息,看示例输出。

想一下停机日期该如何复制,没有停机如何复制??已经停机又如何复制??

7、打印功能是把对象的所有属性都输出,输出格式看示例

8、停机功能是停用当前号码,参数是停机日期,无返回值,操作是把状态改成停用,并停机日期指针创建为动态对象,并根据参数来设置停机日期,最后输出提示信息,看示例输出


要求:在主函数中实现号码备份的功能,对已有的虚拟手机号的所有信息进行复制,并将号码类型改成D表示备份;将手机号码末尾加字母X

输入

第一行输入t表示有t个号码

第二行输入6个参数,包括号码类型、号码、状态、停机的年、月、日,用空格隔开

依次输入t行

输出

每个示例输出三行,依次输出原号码信息、备份号码信息和原号码停机后的信息

每个示例之间用短划线(四个)分割开,看示例输出

输入样例1

2
A 15712345678 1 2015 1 1
B 13287654321 2 2012 12 12

输出样例1

Construct a new phone 15712345678
类型=政府||号码=15712345678||State=在用
Construct a copy of phone 15712345678
类型=备份||号码=15712345678X||State=在用
Stop the phone 15712345678
类型=政府||号码=15712345678||State=停用||停机日期=2015.1.1

Construct a new phone 13287654321
类型=企业||号码=13287654321||State=未用
Construct a copy of phone 13287654321
类型=备份||号码=13287654321X||State=未用
Stop the phone 13287654321
类型=企业||号码=13287654321||State=停用||停机日期=2012.12.12

代码如下:

#include<iostream>
#include<iomanip>
#include<cmath>

using namespace std;

class Date {
    int year, month, day;
public:
    Date(int y, int m, int d) :
            year(y), month(m), day(d) {
    }
    void print() {
        cout<<year<<'.'<<month<<'.'<<day<<endl;
    }
    friend class Phone;
};

class Phone {
    char type;
    char *a;
    int stage;
    Date *p ;
public:

    Phone(char t, char b[], int s, Date *pp) :
            type(t), a(b), stage(s), p(pp) {
        cout << "Construct a new phone " << a << endl;
        prin1();
    }

    Phone(Phone &po) {
        type = po.type;
        a = po.a;
        stage = po.stage;
        p = po.p;
        cout << "Construct a copy of phone " << a << endl;
        prin2();
    }

    void stop(Date *p) {
        cout << "Stop the phone " << a << endl;
        prin3();
       p->print();
    }

    void prin3() {
        char *str, *S;
        if (type == 'A') str = "政府";
        else if (type == 'B') str = "企业";
        else if (type == 'C') str = "个人";
        S = "停用";

        cout << "类型=" << str << "||号码=" << a << "||State=" << S << "||停机日期=";
    }

    void prin2() {
        char *str, *S;
         str = "备份";
        if (stage == 1) S = "在用";
        else if (stage == 2) S = "未用";
        else if (stage == 3) S = "停用";
        char *b = new char[13];
        int i;
        for (i = 0; i < 11; i++)
            b[i] = a[i];
        b[11] = 'X',b[12]='\0'; 
        cout << "类型=" << str << "||号码=" << b << "||State=" << S << endl;
    }

    void prin1() {
        char *str, *S;
        if (type == 'A') str = "政府";
        else if (type == 'B') str = "企业";
        else if (type == 'C') str = "个人";
        if (stage == 1) S = "在用";
        else if (stage == 2) S = "未用";
        else if (stage == 3) S = "停用";
        cout << "类型=" << str << "||号码=" << a << "||State=" << S << endl;
    }
};


int main() {
    int t;
    cin >> t;
    while(t--) {
        char type;
        char a[11];
        int stage;
        int y, m, d;
        cin >> type >> a >> stage >> y >> m >> d;
        Date *s=new Date(y, m, d);
        Phone p(type, a, stage,s);
        Phone q(p);
        p.stop(s);
        cout <<"----"<<endl;
    }
}

G. 动态数组

题目描述

一开始未知数组长度,根据要求创建不同类型的指针,并且使用指针创建相应长度的数组,然后再完成不同的要求

若要求创建整数数组,计算数组内所有数据的平均值

若要求创建字符数组,找出数组内的最大字母

若要求创建浮点数数组,找出数组的最小值

要求程序整个过程不能使用数组下标,从数组创建、输入到搜索、比较、计算,到输出都必须使用指针

提示:使用new关键字

输入

第一行输入t表示有t个测试实例

第二行先输入一个大写字母表示数组类型,I表示整数类型,C表示字符类型,F表示浮点数类型;然后输入n表示数组长度。

第三行输入n个数据

依次输入t个实例

输出

每个根据不同的数组类型输出相应的结果

输入样例1

3
C 5
A D E B C
I 6
22 55 77 33 88 55
F 4
3.1 1.9 6.5 4.8

输出样例1

E
55
1.9

代码

#include <bits/stdc++.h>
using namespace std;
int main() {
int t,i;
scanf(“%d\n”,&t);
while(t–) {
char ch;
scanf(“%c”,&ch);
if(ch==‘I’) {
int num,sum=0;
scanf(“%d”,&num);
//printf(“num = %d\n”,num);
int a;
a=new int[num];
for(i=0; i<num; i++) {
scanf(“%d”,a+i);
sum+=
(a+i);
}
int ave;
ave=sum/num;
printf(“%d\n”,ave);
getchar();
} else if(ch==‘F’) {
float min;
int num2;
scanf(“%d”,&num2);
float b;
b=new float[num2];
for( i=0; i<num2; i++)
scanf(“%f”,b+i);
for( i=0,min=b; i<num2; i++) {
if(min>
(b+i))
min=
(b+i);
}
printf(“%.1f\n”,min);
getchar();
} else if(ch==‘C’) {
int num3;
scanf(“%d\n”,&num3);
char c,max;
c=new char [num3];
char t;
for(i=0; i<num3; i++) {
scanf(“%c”,c+i);
scanf(“%c”,&t);
//printf(“%d %c\n”,i,c[i]);
}
max = (c+0);
for(i=0; i<num3; i++) {
if(max<
(c+i)) max=
(c+i);
}
printf(“%c\n”,max);
}
//printf(“—\n”);
}
}

H. 矩阵左转

题目描述

输入一个2*3的矩阵,将这个矩阵向左旋转90度后输出

比如现在有2*3矩阵 :

1 2 3

4 5 6

向左旋转90度后的矩阵变为:

3 6

2 5

1 4

要求:除了矩阵创建和数据输入可以使用数组和数组下标的方法,其他过程对矩阵的任何访问都必须使用指针

提示:m行n列的二维矩阵,第i行第j列的元素与首元素的距离为i*n+j,序号从0开始计算

输入

第一行输入t表示有t个测试实例

连续两行输入一个2*3的矩阵的数据

依次输入t个实例

输出

依次输出左转后的矩阵结果

在输出的每行中,每个数据之间都用空格隔开,最后一个数据后面也带有空格

输入样例1

2
1 2 3
4 5 6
4 5 6
7 8 9

输出样例1

3 6
2 5
1 4
6 9
5 8
4 7

代码

#include<stdio.h>
int main() {
	int a[2][3],b[3][2];
	int i,j,t,temp;
	scanf("%d",&t);
	while(t--) {
		for(i=0; i<2; i++)
			for(j=0; j<3; j++)
				scanf("%d",&a[i][j]);
				
		for(i=0; i<2; i++)
			for(j=0; j<3; j++)
				*(*(b+2-j)+i)=*(*(a+i)+j);
		for(i=0; i<3; i++)
			{
			for(j=0; j<2; j++)	
			printf("%d ",*(*(b+i)+j));
		printf("\n");}
		}
}

总结

到此结束。

  • 2
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值