buctoj 数据结构23年补题代码记录
注意有的题是附加代码模式会给出示例代码,大家不要复制错了,ac代码在“代码”目录下
有部分补题已经被系统回收,后续如果有机会找回会再补上
目录
5611: 算法2-2:有序线性表的有序合并(附加代码模式)
5612: 算法2-2:有序线性表的有序合并(附加代码模式-STL)
A
4086: 31.简单计算器
题目描述
一个最简单的计算器支持+,-,*,/ 四种运算。输入只有一行:两个参加运算的数一个操作符(+,-,*,/)。输出运算表达式的结果。考虑下面两种情况:
(1)如果出现除数为0的情况,则输出Divided by zero!
(2)如果出现 无效的操作符(即不为+,-,*,/之一),则输出:Invalid operator!
输入
输入只有一行,两个单精度float浮点数a,b和操作符op
输出
使用cout进行输出, 不用特殊保留小数 (cout自动决定)
样例输入 复制
34 56 +
样例输出 复制
90
代码
#include <stdio.h>
#include<bits/stdc++.h>
using namespace std;
int main() {
float a, b;
char op;
cin >> a >> b >> op;
if(op == '+'){
cout << a+b << endl;
return 0;
}else if (op == '-') {
cout << a-b << endl;
return 0;
}else if(op == '*'){
cout << a*b << endl;
return 0;
}else if(op == '/'){
if(b == 0){
cout << "Divided by zero!" << endl;
return 0;
}else {
cout << a/b << endl;
return 0;
}
}else{
cout << "Invalid operator!" << endl;
return 0;
}
return 0;
}
B
5502: 案例 2-1.1:简单计算器
题目描述
模拟简单计算器的工作,假设计算器只能进行加减乘除运算,运算数和结果都是整数,4种运算符的优先级相同,按从左到右的顺序计算。
输入
输入说明,输入一个四则运算算式,(没有空格,且至少有一个操作数),遇到等号“=”说明输入结束。
输出
输出说明,输出计算式的运算结果,如果除法分母为0或有非法运算符,则输出ERROR。
样例输入 复制
1+2*10-10/2=
样例输出 复制
10
提示
此题4种运算符的优先级相同
代码
#include <stdio.h>
#include<bits/stdc++.h>
#include <string.h>
using namespace std;
float findnum(string f, int &flag){
//cout << f[flag] <<endl;
float num=0;
while (true) {
if(f[flag]>='0' && f[flag]<='9'){
num=num*10+f[flag]-48;
flag++;
}else{
break;
}
}
return num;
}
int main() {
string f;
int flag=0,len;
float a, b;
cin >> f;
a=findnum(f,flag);
len = f.size();
while (flag < len){
if(f[flag]=='+' || f[flag]=='-' || f[flag]=='*' || f[flag]=='/' || f[flag]=='='){
if(f[flag]=='+'){
b=findnum(f,++flag);
a = a+b;
}else if(f[flag]=='-'){
b=findnum(f,++flag);
a = a-b;
}else if(f[flag]=='*'){
b=findnum(f,++flag);
a = a*b;
}else if(f[flag]=='/'){
b=findnum(f,++flag);
if(b==0){
cout << "ERROR";
return 0;
}
a = a/b;
}else if(f[flag]=='='){
cout << a << endl;
return 0;
}else{
if(f[flag+1]<='0' || f[flag+1]>='9'){
cout << f[flag] << endl;
cout << f[flag+1] << endl;
cout << "ERROR";
return 0;
}
}
}else{
cout << "ERROR";
return 0;
}
}
return 0;
}
C
5571: 基础实验2-1.2:数组元素的循环左移
题目描述
一个数组A中有N(N>0)个整数,在不允许使用另外数组的前提下,将每个整数循环向左移动M(M>=0)个位置,即将A中的数据由(A0A1...AN-1)变换为(AM...AN-1A0A1...AM-1)(最前面的M个数据)循环移至最后面的M个位置)。
输入
第一行输入N(1<=N<=100),M(M>=0);
第二行输入N个整数
输出
输出循环左移M位以后的整数序列
样例输入 复制
8 3
1 2 3 4 5 6 7 8
样例输出 复制
4 5 6 7 8 1 2 3
代码
#include <stdio.h>
#include<bits/stdc++.h>
using namespace std;
int main() {
int N, M, n[10000], temp;
cin >> N >> M;
M=M%N;
for(int i=0;i<M;i++){
cin >> n[i];
}
for(int i=M;i<N;i++){
cin >> temp;
cout <<temp<< " ";
}
for(int i=0;i<M;i++){
cout <<n[i]<< " ";
}
return 0;
}
D
5328: 案例2-1.4:递归求简单交错幂级数的部分和
题目描述
构造一个计算简单交错幂级数的部分和的函数:f(x,n)=x-x^2+x^3-x^4+......(-1)^(n-1)x^n。
输入
输入为两个数x,n.其中n为正整数,x为实数且在双精度范围内。
输出
输出为该函数f(x,n)的返回值,保留两位小数,该返回值在双精度范围内
样例输入 复制
0.5 12
样例输出 复制
0.33
提示
使用递归函数
代码
#include <stdio.h>
#include <cmath>
#include<bits/stdc++.h>
using namespace std;
double f(double x, int n){
double sum;
if(n==1){
return x;
}else{
sum=f(x,n-1)+pow(-1,n-1)*pow(x,n);
return sum;
}
}
int main() {
int n;
double x;
cin >> x >> n;
printf("%.2f",f(x,n));
return 0;
}
E
5585: 案例2-1.3:数列求和
题目描述
给定某数字A(1=<A<=9)以及非负整数N(0=<N<=100000),求数列之和S=A+AA+AAA+...+AA..A(N个A)。例如A=1,N=3时S=1+11+111=123.
输入
输入数字A(1<=A<=9)与非负整数N。
输出
输出N项数列之和S的值
样例输入 复制
1 3
样例输出 复制
123
代码
#include <stdio.h>
#include <cmath>
#include<bits/stdc++.h>
using namespace std;
int main() {
int A, N, past=0;
cin >> A >> N;
int n[100000];
if(N==0){
cout<<"0";
return 0;
}
for(int i = N;i>0;i--){
if(i==1&&past+A>9){
cout<<(past+A)/10;
}
past=past+A*i;
n[i-1]=past%10;
past=past/10;
}
for(int i=0;i<N;i++){
cout<<n[i];
}
return 0;
}
F
5568: 基础实验2-2.1:整数的分类处理
题目描述
给定N个正整数,要求从中得到下列三种计算结果:
1.A1=能被三整除的最大整数
2.A2=存在整数K使之可以表示为3K+1的整数个数
3.A3=存在整数K使之可以表示为3K+2的所有整数的平均值(精确到小数点后一位)
输入
第一行输入N,随后一行输入N个正整数,所有数字不超过100
输出
一行按顺序输出A1,A2,A3的值,如果某个数字不存在则输出NONE
样例输入 复制
8
5 8 7 6 9 1 3 10
样例输出 复制
9 3 6.5
代码
#include <stdio.h>
#include <cmath>
#include<bits/stdc++.h>
using namespace std;
int main() {
int N, A1=0, A2=0, num_A3=0,n;
float A3=0;
cin >> N;
for(int i=0;i<N;i++){
cin >> n;
if(n%3==0){
if(A1<n){
A1=n;
}
}else if(n%3==1){
A2++;
}else{
num_A3++;
A3=A3+n;
}
}
if(A1==0){
cout<<"NONE ";
}else{
cout<<A1<<" ";
}
if(A2==0){
cout<<"NONE ";
}else{
cout<<A2<<" ";
}
if(num_A3==0){
cout<<"NONE";
}else{
printf("%.1f",A3/num_A3);
}
return 0;
}
G
2130: 最大连续子序列和问题
题目描述
给定整数序列A1,A2,....,An,对其所有连续子序列求和,寻找累加和最大的序列。如果所有的整数都是负的,那么最大连续子序列的和为0。
输入
输入包括多组测试数据,每组测试数据一行,每行第一个为正整数n(0 < n <= 100000),表示序列长度,紧跟着n个整数,Ai (-1001<Ai < 1001),表示序列每个元素,各个整数之间用空格隔开。
输出
针对每组测试数据,输出最大连续子序列的和,以及该最大连续子序列的起止位置。当最大连续子序列的长度为0时,序列的起止位置都输出为-1。如果有多个连续子序列的值为最大值,输出第一个连续子序列。
多组输出用换行隔开
样例输入 复制
6 -2 11 -4 13 -5 2
1 -1
样例输出 复制
20 1 3
0 -1 -1
代码
#include <stdio.h>
#include <cmath>
#include<bits/stdc++.h>
using namespace std;
int main() {
int N,max,fin_front,fin_end,front,now,sum;
while(scanf("%d",&N)!=EOF){
sum=max=0;
fin_front=-1;
front=0;
fin_end=-1;
for(int i = 0;i<N;i++){
cin >> now;
sum=sum+now;
if(sum>max){
max=sum;
fin_end=i;
fin_front=front;
}else if(sum<0){
front=i+1;
sum=0;
}
}
cout<<max<<" "<<fin_front<<" "<<fin_end<<" "<<endl;
}
return 0;
}
H
5229: 数据结构--绪论--求解多项式的值
题目描述
给定系数和变量x的值,计算多项式f(x) = a0 + a1x+…+an-1xn-1+anxn的值
输入
输入包括3行数据,对应一个多项式
输入第一行为正整数n,n小于10000
输入第二行为空格分开的n+1个浮点数,代表n+1个系数
输入第三行为浮点数x
输出
输出一个浮点数,对应多项式计算后的结果,小数点后保留2位有效数字。
样例输入 复制
2
1.0 2.0 3.0
1
样例输出 复制
6.00
代码
#include <stdio.h>
#include <cmath>
#include<bits/stdc++.h>
using namespace std;
int main() {
int n;
double a[100000],x,sum=0;
cin>>n;
for(int i=0;i<n+1;i++){
cin>>a[i];
}
cin>>x;
for(int i=0;i<n+1;i++){
sum+=a[i]*pow(x,i);
}
printf("%.2f",sum);
return 0;
}
I
5381: 基础实验1-2.1:有序数组的插入
题目描述
给定大小为N(0<N<1000),从小到大排列的整数数组A[],以及待插入的整数X。试将整数X插入数组中的合适位置以保持数组有序性。
输入
第一行 数组大小 N
第二行 数组A[]
第三行 带插入的整数X
输出
输出:整数X在新数组中第一次出现的位置。
样例输入 复制
5
1 2 4 4 5
4
样例输出 复制
3
代码
#include <stdio.h>
#include <cmath>
#include<bits/stdc++.h>
using namespace std;
int main() {
int N,X,a[100000];
cin>>N;
for(int i=0;i<N;i++){
cin>>a[i];
}
cin>>X;
for(int i=0;i<N;i++){
if(a[i]==X){
printf("%d",i+1);
return 0;
}else if(a[i]>X){
printf("%d",i+1);
return 0;
}
}
printf("%d",N+1);
}
J
7250: 一元多项式的求导(附加代码模式)
题目描述
一个一元多项式可以看作由若干个一元单项式按降幂排列成的线性表。请编写程序对输入的一元多项式进行求导,并输出求导的结果。
本题是附加代码模式,主函数main会自动附加在同学们提交的代码后面,请同学们在提交的时候注释掉附加代码。
附加代码如下:
int main(){
// freopen("/config/workspace/answer/DataStructure/test.in","r",stdin);
List list = InputList();
List newlist = getDerivation(list);
PrintList(newlist);
return 0;
}
输入
输入为一个一元多项式,按照降幂依次输入每个单项式的系数和指数,并以-1 -1作为结束。系数和指数均为整数,指数不小于0。
输出
输出为求导结果多项式,按照降幂依次输出每个单项的系数和指数,每个数值后面用一个空格隔开,输出结果多项式后换行。 系数为0的单项式不得输出——除非结果多项式就是0,则直接输出0并换行。
样例输入 复制
2 7 3 5 12 1 6 0 -1 -1
样例输出 复制
14 6 15 4 12 0
提示
数据范围:每个多项式的数据项数量不超过10000
代码框架如下,请完成相关函数的代码实现
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
struct Node{
int r; // 系数
int e; // 指数
};
// 线性表存储一元多项式
struct List{
Node data[10000+5];
int len;
};
// 输出多项式
void PrintList(const List& list){
}
// 输入多项式
List InputList(){
}
// 多项式求导
List getDerivation(const List& list){
}
int main(){
// freopen("/config/workspace/answer/DataStructure/test.in","r",stdin);
List list = InputList();
List newlist = getDerivation(list);
PrintList(newlist);
return 0;
}
代码
#include <stdio.h>
#include <cmath>
#include<bits/stdc++.h>
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
struct Node{
int r; // 系数
int e; // 指数
};
// 线性表存储一元多项式
struct List{
Node data[100000+5];
int len;
};
// 输出多项式
void PrintList(const List& list){
int i=0,flag=0;
while(true){
if(i>=list.len){
break;
}else if(list.data[i].r==0){
i++;
continue;
}else if(list.data[i].e<0){
i++;
continue;
}else{
cout<<list.data[i].r<<" "<<list.data[i].e<<" ";
flag=1;
i++;
}
}
if(flag==0){
cout<<"0";
}
cout<<endl;
}
// 输入多项式
List InputList(){
List list;
int i=0;
while(true){
cin >> list.data[i].r >>list.data[i].e;
if(list.data[i].r==-1 && list.data[i].r==-1){
list.len=i;
return list;
}
i++;
}
}
// 多项式求导
List getDerivation(List& list){
int i=0;
while(true){
if(i==list.len){
return list;
}
list.data[i].r = list.data[i].r * list.data[i].e;
list.data[i].e = list.data[i].e - 1;
i++;
}
}
// int main(){
// // freopen("/config/workspace/answer/DataStructure/test.in","r",stdin);
// List list = InputList();
// List newlist = getDerivation(list);
// PrintList(newlist);
// return 0;
// }
K
1070: 数据结构作业01 -- 一元多项式的求和
题目描述
一个一元多项式可以看作由若干个一元单项式按降幂排列成的线性表。请编写程序对输入的两个一元多项式求和,并输出求和的结果。
输入
输入为两个一元多项式,每个一元多项式输入一行,按照降幂依次输入每个单项式的系数和指数,并以-1 -1作为结束。系数和指数均为整数,指数不小于0。
输出
输出为求和结果多项式,按照降幂依次输出每个单项的系数和指数,每个数值后面用一个空格隔开,输出结果多项式后换行。 系数为0的单项式不得输出——除非结果多项式就是0,则直接输出0。
样例输入 复制
2 7 3 5 12 1 6 0 -1 -1
7 5 9 4 3 0 -1 -1
样例输出 复制
2 7 10 5 9 4 12 1 9 0
提示
数据范围:每个多项式的数据项数量不超过10000
代码
#include <stdio.h>
#include <cmath>
#include<bits/stdc++.h>
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
struct Node{
int r; // 系数
int e; // 指数
};
// 线性表存储一元多项式
struct List{
Node data[100000+5];
int len;
};
// 输出多项式
void PrintList(const List& list){
int i=0,flag=0;
while(true){
if(i>=list.len){
break;
}else if(list.data[i].r==0){
i++;
continue;
}else if(list.data[i].e<0){
i++;
continue;
}else{
cout<<list.data[i].r<<" "<<list.data[i].e<<" ";
flag=1;
i++;
}
}
if(flag==0){
cout<<"0";
}
cout<<endl;
}
// 输入多项式
List InputList(){
List list;
int i=0;
while(true){
cin >> list.data[i].r >>list.data[i].e;
if(list.data[i].r==-1 && list.data[i].r==-1){
list.len=i;
return list;
}
i++;
}
}
// 多项式求和
List getSum(List &list1, List &list2){
List newlist;
int i = 0,newp = 0;
for(int j = 0;j<list2.len;j++){
if(list2.data[j].e == list1.data[i].e){
newlist.data[newp].e = list1.data[i].e;
newlist.data[newp].r = list1.data[i].r + list2.data[j].r;
newp++;
newlist.len = newp;
i++;
}else if(list2.data[j].e > list1.data[i].e){
newlist.data[newp].e = list2.data[j].e;
newlist.data[newp].r = list2.data[j].r;
newp++;
newlist.len = newp;
}else if(list2.data[j].e < list1.data[i].e){
newlist.data[newp].e = list1.data[i].e;
newlist.data[newp].r = list1.data[i].r;
newp++;
newlist.len = newp;
i++;
j--;
}
}
for(;i<list1.len;i++){
newlist.data[newp].e = list1.data[i].e;
newlist.data[newp].r = list1.data[i].r;
newp++;
newlist.len = newp;
}
return newlist;
}
int main(){
List list1 = InputList();
List list2 = InputList();
List newlist;
newlist=getSum(list1, list2);
PrintList(newlist);
return 0;
}
L
2191: 算法2-2:有序线性表的有序合并
题目描述
已知线性表 LA 和 LB 中的数据元素按值非递减有序排列,现要求将 LA 和 LB 归并为一个新的线性表 LC, 且 LC 中的数据元素仍然按值非递减有序排列。例如,设LA=(3,5,8,11) ,LB=(2,6,8,9,11,15,20) 则
LC=(2,3,6,6,8,8,9,11,11,15,20)
算法描述如下:
从上述问题要求可知,LC中的数据元素或是LA中的数据元素,或是LB中的数据元素,则只要先设LC为空表,然后将LA或LB中的元素逐个插入到LC中即可。为使LC中元素按值非递减有序排列,可设两个指针 i 和 j 分别指向LA和LB中某个元素,若设 i 当前所指的元素为 a,j 所指的元素为 b,则当前应插入到 LC 中的元素 c 为 c = a < b ? a : b显然,指针 i 和 j 的初值均为1(实际写代码时往往是从 0 开始的),在所指元素插入 LC 之后,在 LA 或者 LB 中顺序后移。上述归并算法如下图:
图:有序列表有序插入算法(旧图待换新,暂时请大家自行脑补)
输入
有多组测试数据,每组测试数据占两行。第一行是集合A,第一个整数m(0<=m<=100)代表集合A起始有m个元素,后面有m个非递减排序的整数,代表A中的元素。第二行是集合B,第一个整数n(0<=n<=100)代表集合B起始有n个元素,后面有n个非递减排序的整数,代表B中的元素。每行中整数之间用一个空格隔开。
输出
每组测试数据只要求输出一行,这一行含有 m+n 个来自集合 A 和集合B 中的元素。结果依旧是非递减的。每个整数间用一个空格隔开。
样例输入 复制
4 3 5 8 11
7 2 6 8 9 11 15 20
样例输出 复制
2 3 5 6 8 8 9 11 11 15 20
提示
总结: 本题书中提供的算法是基于顺序表的。在使用顺序表时需要两倍于数据元素数目。如果使用链表则只需要存储一倍的元素。然而使用链表同样需要存储一倍的指针。
所以对于这类问题数据结构的选取,如果数据域占用的空间很大则可以使用链表存储来节省空间,而对于数据域占用不大的情况,则使用顺序表也可以。
代码
#include <stdio.h>
#include <cmath>
#include<bits/stdc++.h>
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
int main(){
int m,n,A[101],B[101];
cin >> m;
for(int i = 0;i < m;i++){
cin >> A[i];
}
cin >> n;
for(int i = 0;i < n;i++){
cin >> B[i];
}
int i = 0,j;
for(j = 0;j<n;j++){
if(i>=m){
break;
}
if(B[j] == A[i]){
cout << B[j] <<" "<<A[i]<<" ";
i++;
}else if(B[j] < A[i]){
cout << B[j] <<" ";
}else if(B[j] > A[i]){
cout << A[i] <<" ";
i++;
j--;
}
}
for(;i<m;i++){
cout << A[i] <<" ";
}
for(;j<n;j++){
cout << B[j] <<" ";
}
return 0;
}
M
5624: 复数求和(附加代码模式)
题目描述
从键盘读入n个复数(实部和虚部都为整数),求出n个复数的和并输出。
本题是附加代码模式,主函数main的代码会自动附加在同学们提交的代码后面,请同学们在提交的时候注释掉自己的main函数。
输入
第一行为正整数n(小于100),接下来n行数据,每行为两个整数,表示一个复数的实部和虚部
输出
输出n个复数的加和结果
样例输入 复制
3
3 4
5 2
1 3
样例输出 复制
9+9i
提示
结构体定义以及函数声明如下图所示:
代码
#include <stdio.h>
#include <cmath>
#include<bits/stdc++.h>
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
struct Complex{
int r; //实
int i; //虚
};
Complex Add(Complex c1,Complex c2){
c1.r += c2.r;
c1.i += c2.i;
return c1;
}
// int main(){
// int n;
// cin >> n;
// Complex c;
// for(int i =0;i<n;i++){
// if(i==0) cin >> c.r >>c.i;
// else{
// Complex t;
// cin >>t.r >>t.i;
// c=Add(c,t);
// }
// }
// cout<<c.r<<"+"<<c.i<<"i"<<endl;
// return 0;
// }
N
5625: 复数乘积(附加代码模式)
题目描述
数集拓展到实数范围内,仍有些运算无法进行。比如判别式小于0的一元二次方程仍无解,因此将数集再次扩充,达到复数范围。
定义:形如z=a+bi的数称为复数(complex number),其中规定i为虚数单位,且i^2=i*i=-1(a,b是任意实数)
我们将复数z=a+bi中的实数a称为复数z的实部(real part)记作Rez=a
实数b称为复数z的虚部(imaginary part)记作 Imz=b.
已知:当b=0时,z=a,这时复数成为实数;
当a=0且b≠0时 ,z=bi,我们就将其称为纯虚数。
定义: 对于复数z=a+bi,称复数z'=a-bi为z的共轭复数。
定义:将复数的实部与虚部的平方和的正的平方根的值称为该复数的模,记作∣z∣
规定复数的乘法按照以下的法则进行:
设z1=a+bi,z2=c+di(a、b、c、d∈R)是任意两个复数,那么它们的积(a+bi)(c+di)=(ac-bd)+(bc+ad)i.
其实就是把两个复数相乘,类似两个多项式相乘,在所得的结果中把i2换成-1,并且把实部与虚部分别合并.两个复数的积仍然是一个复数.
本题是附加代码模式,主函数main的代码会自动附加在同学们提交的代码后面,请同学们在提交的时候注释掉自己的main函数。
输入
两个复数分两行,每行两个数,代表复数的实部和虚部。
输出
两个复数的乘积。
样例输入 复制
1 1
1 1
样例输出 复制
0 2
提示
结构体定义和函数声明见下图
代码
#include <stdio.h>
#include <cmath>
#include<bits/stdc++.h>
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
struct Complex{
int r; //实
int i; //虚
};
Complex Add(Complex c1,Complex c2){
c1.r += c2.r;
c1.i += c2.i;
return c1;
}
Complex Mul(Complex c1,Complex c2){
Complex c;
c.r=c1.r*c2.r-c1.i*c2.i;
c.i=c1.i*c2.r+c1.r*c2.i;
return c;
}
// int main(){
// Complex c1, c2;
// cin >> c1.r >>c1.i>> c2.r >>c2.i;
// Complex c = Mul(c1,c2);
// cout<<c.r<<" "<<c.i<<endl;
// return 0;
// }
O
5505: 案例3-1.4:一元多项式的乘法运算
题目描述
给你两个一元多项式,输出这两个一元多项式的乘积。
输入
输入包含两行,每行一个一元多项式。
每行开头一个数字n(小于10000),表示该多项式非零项项数,后面有n组数字,每组数字包含两个数字,按顺序分别为该项的系数和指数。
输出
输出包含一行,按指数从大到小的顺序输出乘积的非0项的系数与指数,以空格分隔开。
如果最终结果为0,直接输出0 0。
样例输入 复制
4 3 4 -5 2 6 1 -2 0
3 5 20 -7 4 3 1
样例输出 复制
15 24 -25 22 30 21 -10 20 -21 8 35 6 -33 5 14 4 -15 3 18 2 -6 1
代码
#include <stdio.h>
#include <cmath>
#include<bits/stdc++.h>
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
struct Node{
int r; // 系数
int e; // 指数
};
// 线性表存储一元多项式
struct List{
Node data[100000+5];
int len;
};
// 输出多项式
void PrintList(const List& list){
int i=0,flag=0;
while(true){
if(i>=list.len){
break;
}else if(list.data[i].r==0){
i++;
continue;
}else if(list.data[i].e<0){
i++;
continue;
}else{
cout<<list.data[i].r<<" "<<list.data[i].e<<" ";
flag=1;
i++;
}
}
if(flag==0){
cout<<"0 0";
}
cout<<endl;
}
// 输入多项式
List InputList(){
List list;
int i=0;
cin >> list.len;
for(i=0;i<list.len;i++){
cin >> list.data[i].r >>list.data[i].e;
}
return list;
}
// 多项式求和
List getSum(List &list1, List &list2){
List newlist;
int i = 0,newp = 0,j;
for(j = 0;j<list2.len;j++){
if(i>=list1.len){
break;
}
if(list2.data[j].e == list1.data[i].e){
newlist.data[newp].e = list1.data[i].e;
newlist.data[newp].r = list1.data[i].r + list2.data[j].r;
newp++;
newlist.len = newp;
i++;
}else if(list2.data[j].e > list1.data[i].e){
newlist.data[newp].e = list2.data[j].e;
newlist.data[newp].r = list2.data[j].r;
newp++;
newlist.len = newp;
}else if(list2.data[j].e < list1.data[i].e){
newlist.data[newp].e = list1.data[i].e;
newlist.data[newp].r = list1.data[i].r;
newp++;
newlist.len = newp;
i++;
j--;
}
}
for(;i<list1.len;i++){
newlist.data[newp].e = list1.data[i].e;
newlist.data[newp].r = list1.data[i].r;
newp++;
newlist.len = newp;
}
for(;j<list2.len;j++){
newlist.data[newp].e = list2.data[j].e;
newlist.data[newp].r = list2.data[j].r;
newp++;
newlist.len = newp;
}
return newlist;
}
List getMul(List &list1, List &list2){
List newl,sum;
sum.len=0;
for(int i=0;i<list1.len;i++){
for(int j=0;j<list2.len;j++){
newl.data[j].r = list1.data[i].r * list2.data[j].r;
newl.data[j].e = list1.data[i].e + list2.data[j].e;
newl.len=j+1;
}
sum = getSum(sum, newl);
}
return sum;
}
int main(){
List list1 = InputList();
List list2 = InputList();
List newlist;
newlist=getMul(list1, list2);
PrintList(newlist);
return 0;
}
P
7251: 一元多项式的求和(附加代码模式)
题目描述
一个一元多项式可以看作由若干个一元单项式按降幂排列成的线性表。请编写程序对输入的两个一元多项式求和,并输出求和的结果。
本题是附加代码模式,主函数main会自动附加在同学们提交的代码后面,请同学们在提交的时候注释掉附加代码。
附加代码如下:
int main(){
// freopen("/config/workspace/answer/DataStructure/test.in","r",stdin);
List list1 = InputList();
List list2 = InputList();
List list = add(list1, list2);
PrintList(list);
return 0;
}
输入
输入为两个一元多项式,每个一元多项式输入一行,按照降幂依次输入每个单项式的系数和指数,并以-1 -1作为结束。系数和指数均为整数,指数不小于0。
数据范围:每个多项式的数据项数量不超过10000
输出
输出为求和结果多项式,按照降幂依次输出每个单项的系数和指数,每个数值后面用一个空格隔开,输出结果多项式后换行。 系数为0的单项式不得输出——除非结果多项式就是0,则直接输出0。
样例输入 复制
2 7 3 5 12 1 6 0 -1 -1
7 5 9 4 3 0 -1 -1
样例输出 复制
2 7 10 5 9 4 12 1 9 0
提示
代码框架如下,请完成相关函数的代码实现
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
struct Node{
int r; // 系数
int e; // 指数
};
// 线性表存储一元多项式
struct List{
Node data[10000+5];
int len;
};
// 输出多项式
void PrintList(const List& list){
}
// 输入多项式
List InputList(){
}
// 多项式求和
List add(const List& list1, const List& list2){
}
int main(){
// freopen("/config/workspace/answer/DataStructure/test.in","r",stdin);
List list1 = InputList();
List list2 = InputList();
List list = add(list1, list2);
PrintList(list);
return 0;
}
代码
#include <stdio.h>
#include <cmath>
#include<bits/stdc++.h>
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
struct Node{
int r; // 系数
int e; // 指数
};
// 线性表存储一元多项式
struct List{
Node data[100000+5];
int len;
};
// 输出多项式
void PrintList(const List& list){
int i=0,flag=0;
while(true){
if(i>=list.len){
break;
}else if(list.data[i].r==0){
i++;
continue;
}else if(list.data[i].e<0){
i++;
continue;
}else{
cout<<list.data[i].r<<" "<<list.data[i].e<<" ";
flag=1;
i++;
}
}
if(flag==0){
cout<<"0";
}
cout<<endl;
}
// 输入多项式
List InputList(){
List list;
int i=0;
while(true){
cin >> list.data[i].r >>list.data[i].e;
if(list.data[i].r==-1 && list.data[i].e==-1){
list.len=i;
return list;
}
i++;
}
}
// 多项式求和
List add(const List& list1,const List& list2){
List newlist;
int i = 0, j = 0, newp = 0;
while(i < list1.len && j < list2.len){
if(list1.data[i].e == list2.data[j].e){
newlist.data[newp].e = list1.data[i].e;
newlist.data[newp].r = list1.data[i].r + list2.data[j].r;
newp++;
i++;
j++;
}else if(list1.data[i].e > list2.data[j].e){
newlist.data[newp] = list1.data[i];
newp++;
i++;
}else{
newlist.data[newp] = list2.data[j];
newp++;
j++;
}
}
while(i < list1.len){
newlist.data[newp++] = list1.data[i++];
}
while(j < list2.len){
newlist.data[newp++] = list2.data[j++];
}
newlist.len = newp;
return newlist;
}
// int main(){
// List list1 = InputList();
// List list2 = InputList();
// List list =add(list1, list2);
// PrintList(list);
// return 0;
// }
Q
2190: 算法2-1:集合union
题目描述
假设利用两个线性表LA和LB分别表示两个集合A和B(即:线性表中的数据元素即为集合中的成员),现要求一个新的集合A=A∪B。这就要求对线性表做如下操作:扩大线性表LA,将存在于线性表LB中而不存在于线性表LA中的数据元素插入到线性表LA中去。只要从线性表LB中依次取得每个元素,并依值在线性表LA中进行查访,若不存在,则插入之。
输入
有多组测试数据,每组测试数据占两行。第一行是集合A,第一个整数m(0<m<=100)代表集合A起始有m个元素,后面有m个整数,代表A中的元素。第二行是集合B,第一个整数n(0<n<=100)代表集合B起始有n个元素,后面有n个整数,代表B中的元素。每行中整数之间用一个空格隔开。
输出
每组测试数据输出n+2行:前两行分别输出集合A、集合B中的数据,后面n行是每次从B中取出元素插入到A尾部后的集合A。每行整数之间用一个空格隔开,每组测试数据之间用一行空行隔开。
样例输入 复制
5 1 5 2 6 3
3 1 7 9
1 3
2 2 7
4 2 5 1 4
4 1 2 4 5
样例输出 复制
1 5 2 6 3
1 7 9
1 5 2 6 3
1 5 2 6 3 7
1 5 2 6 3 7 9
3
2 7
3 2
3 2 7
2 5 1 4
1 2 4 5
2 5 1 4
2 5 1 4
2 5 1 4
2 5 1 4
提示
1、使用数组时,给集合 A 分配的空间不小于200。因为将 B 中的元素添加到 A 中时,可能会超过 100 了。
2、利用 scanf("%d",&m) != EOF 来判断是否还有输入数据。
3、一个细节问题就是题目要求输出的格式是每行中元素之间用一个空格隔开,每组输出间用一个空行隔开。也就是说4个元素间只有3个空格,2组输出间只有1个空行。处理方法都一样。两种方法:一是除了第一个元素,后面的每个元素之前输出个空格;二是除了最后一个元素,前面的每个元素之后都输出一个空格。我往往采用第一种方式,因为许多编程语言中的数组都是从0开始的,而0正是判断语句中的“假”(当然Java中不是这样的)。
总结: 本题考查的是线性表的基本操作。实际上只考察了遍历和添加操作。虽然算法中使用的是“插入”,然而本题只要求插入到链表的尾部,因而只是添加而已。线性表按存储结构分为顺序表和链表。顺序表在插入时往往需要移动某些元素,而移动元素需要消耗大量时间。如果插入操作次数很多的话,采用链表会好些。但由于只是插入到线性表的尾部,因而也不必移动元素。所以采用顺序表解本题也不失为一个好方法。 如果采用顺序表,事先需要分配足够的内存。题目中 m 和 n 都是不大于100的,是不是给两个顺序表(数组实现)分配100的内存就够了呢?答案是否定的。因为将集合 B 添加到集合 A 中很可能就超过100个元素了。
还有,题目没有给定多少组测试数据,我们的方法就是判断是否读到了文件结尾。利用 scanf("%d",&m) != EOF 来作判断即可。 对于解本题的算法,题目描述中已经有了,我就不再赘述。除了基本操作以外,还要看怎么输出。实际上就是在每次插入后使用一个循环将集合 A 中的所有元素输出即可。
代码
#include <stdio.h>
#include <cmath>
#include<bits/stdc++.h>
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
int main(){
int n,m,A[201],B[101],flag=1;
while(scanf("%d",&n) != EOF){
for(int i=0;i<n;i++){
cin >> A[i];
cout << A[i] <<" ";
}
cout << endl;
cin >> m;
for(int i=0;i<m;i++){
cin >> B[i];
cout << B[i] <<" ";
}
cout << endl;
for(int j=0;j<m;j++){
flag=1;
for(int i=0;i<n;i++){
cout << A[i] <<" ";
if(A[i]==B[j]){
flag=0;
}
}
if(flag==1){
A[n++]=B[j]; //这里是n++不是++n不然会存到n外面去
cout << B[j] << endl;
}else{
cout << endl;
}
}
cout << endl;
}
return 0;
}
R
5611: 算法2-2:有序线性表的有序合并(附加代码模式)
题目描述
已知线性表 LA 和 LB 中的数据元素按值非递减有序排列,现要求将 LA 和 LB 归并为一个新的线性表 LC, 且 LC 中的数据元素仍然按值非递减有序排列。例如,设LA=(3,5,8,11) ,LB=(2,6,8,9,11,15,20) 则
LC=(2,3,6,6,8,8,9,11,11,15,20)
本题是附加代码模式,主函数main的代码会自动附加在同学们提交的代码后面,请同学们在提交的时候注释掉自己的main函数。
main函数代码如下:
int main()
{
// freopen("/config/workspace/answer/test.in","r",stdin);
SeqList listA,listB,listC;
InitSeqList(listA,100);
InitSeqList(listB,100);
InitSeqList(listC,200);
int m,n;
cin >> m;
for(int i=0;i<m;i++){
int v; cin >> v;
AddData(listA,v);
}
cin >> n;
for(int i=0;i<n;i++){
int v; cin >> v;
AddData(listB,v);
}
MergeList(listA,listB,listC);
PrintSeqList(listA);
PrintSeqList(listB);
PrintSeqList(listC);
return 0;
}
输入
有多组测试数据,每组测试数据占两行。第一行是集合A,第一个整数m(0<=m<=100)代表集合A起始有m个元素,后面有m个非递减排序的整数,代表A中的元素。第二行是集合B,第一个整数n(0<=n<=100)代表集合B起始有n个元素,后面有n个非递减排序的整数,代表B中的元素。每行中整数之间用一个空格隔开。
输出
每组测试数据只要求输出一行,这一行含有 m+n 个来自集合 A 和集合B 中的元素。结果依旧是非递减的。每个整数间用一个空格隔开。
样例输入 复制
4 3 5 8 11
7 2 6 8 9 11 15 20
样例输出 复制
2 3 5 6 8 8 9 11 11 15 20
提示
结构体定义和相应的操作函数如下图所示,注意如果一个函数的返回值类型不是void,那么在函数体内部必须要加return语句,否则提交到oj系统之后,会报“答案错误”。
#include<iostream>
#include<cstdio>
using namespace std;
struct SeqList
{
int *data;
int bufferlen;
int tablelen;
};
int InitSeqList(SeqList &k,int maxlen)
{
return 0;
}
int AddData(SeqList &t,int v)
{
return 0;
}
int MergeList(SeqList &a,SeqList &b,SeqList &c)
{
return 0;
}
int PrintSeqList(SeqList &s)
{
return 0;
}
代码
#include <stdio.h>
#include <cmath>
#include<bits/stdc++.h>
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
struct SeqList
{
int *data;
int bufferlen;
int tablelen;
};
int InitSeqList(SeqList &k,int maxlen)
{
k.data = new int[maxlen]; //需要开地址不然函数调用完就释放了
k.bufferlen=maxlen;
k.tablelen=0;
return 0;
}
int AddData(SeqList &t,int v)
{
t.data[t.tablelen]=v;
t.tablelen++;
t.bufferlen--;
return 0;
}
int MergeList(SeqList &a,SeqList &b,SeqList &c)
{
int i=0,j=0;
while(i<a.tablelen && j<b.tablelen){
if(a.data[i]<b.data[j]){
AddData(c,a.data[i]);
i++;
}else if(a.data[i]>=b.data[j]){
AddData(c,b.data[j]);
j++;
}
}
if(i<a.tablelen){
for(;i<a.tablelen;i++){
AddData(c,a.data[i]);
}
}
if(j<b.tablelen){
for(;j<b.tablelen;j++){
AddData(c,b.data[j]);
}
}
return 0;
}
int PrintSeqList(SeqList &s)
{
for(int i=0;i<s.tablelen;i++){
cout<<s.data[i]<<" ";
}
cout << endl;
return 0;
}
// int main()
// {
// // freopen("/config/workspace/answer/test.in","r",stdin);
// SeqList listA,listB,listC;
// InitSeqList(listA,100);
// InitSeqList(listB,100);
// InitSeqList(listC,200);
// int m,n;
// cin >> m;
// for(int i=0;i<m;i++){
// int v; cin >> v;
// AddData(listA,v);
// }
// cin >> n;
// for(int i=0;i<n;i++){
// int v; cin >> v;
// AddData(listB,v);
// }
// MergeList(listA,listB,listC);
// PrintSeqList(listA);
// PrintSeqList(listB);
// PrintSeqList(listC);
// return 0;
// }
S
5612: 算法2-2:有序线性表的有序合并(附加代码模式-STL)
题目描述
已知线性表 LA 和 LB 中的数据元素按值非递减有序排列,现要求将 LA 和 LB 归并为一个新的线性表 LC, 且 LC 中的数据元素仍然按值非递减有序排列。例如,设LA=(3,5,8,11) ,LB=(2,6,8,9,11,15,20) 则
LC=(2,3,6,6,8,8,9,11,11,15,20)
本题是附加代码模式,主函数main的代码会自动附加在同学们提交的代码后面,请同学们在提交的时候注释掉自己的main函数。
main函数代码如下:
输入
有多组测试数据,每组测试数据占两行。第一行是集合A,第一个整数m(0<=m<=100)代表集合A起始有m个元素,后面有m个非递减排序的整数,代表A中的元素。第二行是集合B,第一个整数n(0<=n<=100)代表集合B起始有n个元素,后面有n个非递减排序的整数,代表B中的元素。每行中整数之间用一个空格隔开。
输出
每组测试数据只要求输出一行,这一行含有 m+n 个来自集合 A 和集合B 中的元素。结果依旧是非递减的。每个整数间用一个空格隔开。
样例输入 复制
4 3 5 8 11
7 2 6 8 9 11 15 20
样例输出 复制
2 3 5 6 8 8 9 11 11 15 20
提示
对C++ STL不熟悉的同学,可以查看网址C++ vector 容器浅析 | 菜鸟教程
头文件和相应的操作函数如下图所示:
代码
#include <stdio.h>
#include <cmath>
#include<bits/stdc++.h>
#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
using namespace std;
int MergeList(const vector<int> &a,const vector<int> &b, vector<int> &c)
{
int i=0,j=0;
vector<int> listC;
while(i<a.size() && j<b.size()){
if(a[i]<b[j]){
listC.push_back(a[i]);
i++;
}else if(a[i]>=b[j]){
listC.push_back(b[j]);
j++;
}
}
if(i<a.size()){
for(;i<a.size();i++){
listC.push_back(a[i]);
}
}
if(j<b.size()){
for(;j<b.size();j++){
listC.push_back(b[j]);
}
}
c=listC;//c没有const可以改动
return 0;
}
void PrintVector(const vector<int> &s)
{
for(int i=0;i<s.size();i++){
cout<<s[i]<<" ";
}
cout << endl;
}
// int main()
// {
// // freopen("/config/workspace/answer/test.in","r",stdin);
// vector<int> listA,listB,listC;
// int m,n;
// cin >> m;
// for(int i=0;i<m;i++){
// int v; cin >> v;
// listA.push_back(v);
// }
// cin >> n;
// for(int i=0;i<n;i++){
// int v; cin >> v;
// listB.push_back(v);
// }
// MergeList(listA,listB,listC);
// PrintVector(listC);
// return 0;
// }
T(系统回收看不了题)
U(系统回收看不了题)
V
230: 案例3-1.1:线性表元素的区间删除
题目描述
给定一个顺序存储的线性表,删除线性表中所有小于r且大于l的元素。删除后剩余元素保持顺序存储,相对位置不变。
输入
第一行元素个数n、区间l、r。1<=n<=1e6,0<=l<=r<=1e8.
第二行n个整数,对应顺序表的各元素。对于每个元素Ai满足0<=Ai<=1e8
输出
第一行输出删除后元素的个数
第二行输出删除后顺序表中的元素,没有元素直接换行
样例输入 复制
10 0 4
4 -8 2 12 1 5 9 3 3 10
样例输出 复制
6
4 -8 12 5 9 10
代码
#include <stdio.h>
#include <cmath>
#include<bits/stdc++.h>
#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
using namespace std;
int main()
{
int t,j=0,n,l,r,a[1000001];
cin >> n >> l >> r;
for(int i=0;i<n;i++){
cin >> t;
if(l < t && t < r){
}else {
a[j]=t;
j++;
}
}
cout << j <<endl;
for(int i=0;i<j;i++){
cout<<a[i]<<" ";
}
return 0;
}
W(系统回收看不了题)
X(系统回收看不了题)
Y(系统回收看不了题)
Z
5384: 案例3-1.2:最长连续递增子序列
题目描述
给定一个顺序存储的线性表,设计算法查找该线性表中最长的连续递增子序列。例如(1,9,2,5,7,3,4,6,8,0)中最长的递增子序列为(3,4,6,8).
输入
序列长度 n (1<=n<=1e6)
序列元素(整数)a1,a2.....an (1<=ai<=1e9)
输出
最长连续递增子序列(若有多个等长最长连续递增子序列,输出位置靠前的)。
样例输入 复制
15
1 9 2 5 7 3 4 6 8 0 11 15 17 17 10
样例输出 复制
3 4 6 8
代码
#include <stdio.h>
#include <cmath>
#include<bits/stdc++.h>
#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
using namespace std;
int main()
{
int n,a[1000001],fin_head=0,head=0,fin_end=0,fin_len=0,len=0;
cin >> n >>a[0];
for(int i=1;i<n;i++){
cin >> a[i];
if(a[i]>a[i-1]){
len++;
if(len>fin_len){
fin_end=i;
fin_head=head;
fin_len=len;
}
}else{
head=i;
len=0;
}
}
for(int i=fin_head;i<=fin_end;i++){
cout<<a[i]<<" ";
}
return 0;
}