BUAA数据结构22级第一次作业

1.扩展字符

【问题描述】

从键盘输入包含扩展符'-'的字符串,将其扩展为等价的完整字符,例如将a-d扩展为abcd,并输出扩展后的字符串。

【输入形式】

从键盘输入包含扩展符的字符串 

【输出形式】

输出扩展后的字符串

【输入样例1】

ADEa-g-m02

【输出样例1】

ADEabcdefghijklm02

【输入样例2】

cdeT-bcd

【输出样例2】

cdeT-bcd

【样例说明】

将样例1的输入ADEa-g-m02扩展为:ADEabcdefghijklm02;样例2的输入cdeT-bcd中,扩展符前的字符为大写字母,扩展符后的字符为小写字母,不在同一范围内,所以不进行扩展。

解题思路:

1/ 由于不知道数据范围 输入先不考虑使用gets(s) scanf("%s",&s)

*使用getchar()而不用scanf(" %s",&ch)的原因 

首先是scanf不会扫描'\n'会卡在最后的输入 从而超时

其次是getchar() putchar()的运行速度更快

2/ 问题的关键在于'-'前后的判断 所以要储存上一个字符的结果 

在碰到'-'时在扫描下一个字符 从而进行是否扩展的判断

*不确定环判断条件时候 果断while(1) 到后面在break continue

代码

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <math.h>
#define LL long long
#define MAX(A,B) (A)>(B)?(A):(B)
#define MIN(A,B) (A)<(B)?(A):(B)

int main(int argc,const char* argv[]){
    char ch_l='\0',ch,ch_r='\0';
    int i;
    while(1){
        ch=getchar();
        if(!isgraph(ch)) break; //判断是否到字符串结尾
        if(ch!='-'){ //非'-' 正常输出
            putchar(ch);
            ch_l=ch; //记录上个字符
            continue;
        }
        //扫描到'-' 接着扫描入下一个字符
        ch_r=getchar(); 
        if(!isgraph(ch_r)) break;  //判断是否到字符串结尾      
        if(((islower(ch_l)&&islower(ch_r))||  //判断'-'前后字符是否满足条件
            (isupper(ch_l)&&isupper(ch_r))||
            (isdigit(ch_l)&&isdigit(ch_r)))  && ch_l<ch_r){
            for(i=ch_l+1;i<ch_r;i++)
                putchar(i); //扩展'-'
            putchar(ch_r);
            ch_l=ch_r; //记录值
            continue;
        }
        //不满足扩展要求
        putchar(ch); 
        putchar(ch_r);
        ch_l=ch_r; //记录上个字符
    }
    return 0;
}

2. 表达式的计算(支持空格 连乘 连除)

【问题描述】

从标准输入中读入一个整数算术运算表达式,如5 - 1 * 2 * 3 + 12 / 2 / 2 = 。计算表达式结果,并输出。

要求:

1、表达式运算符只有+、-、*、/,表达式末尾的’=’字符表示表达式输入结束,表达式中可能会出现空格;

2、表达式中不含圆括号,不会出现错误的表达式;

3、出现除号/时,以整数相除进行运算,结果仍为整数,例如:5/3结果应为1。

【输入形式】

在控制台中输入一个以’=’结尾的整数算术运算表达式。

【输出形式】

向控制台输出计算结果(为整数)。

【样例1输入】

5 - 1 * 2 * 3 + 12 / 2 / 2 =

【样例1输出】

2

【样例2输入】

500 =

【样例2输出】

500

【样例1说明】

输入的表达式为5 - 1 * 2 * 3 + 12 / 2 / 2 =,按照整数运算规则,计算结果为2,故输出2。

【样例2说明】

输入的表达式为500 = ,没有运算符参与运算,故直接输出500。

算法之一提示:

1、可以利用gets函数,读取整行表达式;

2、对于空格,可以考虑首先去除表达式中的所有空格

3、可以设一计数器用来记录已读取、但未参加运算的运算符的个数,根据该计数器来判断如何进行运算;

4、可以设计一函数:实现二元整数算术运算。

解题思路1:

scanf("%d %c",&num,&op)解决空格问题

加减号可以看成分隔符 乘除优先运算 结果先储存到tmp_value 遇到+-时在加到result上

*此方法局限与不包括括号的情况下

代码

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <math.h>
#define LL long long
#define MAX(A,B) (A)>(B)?(A):(B)
#define MIN(A,B) (A)<(B)?(A):(B)

int main(int argc,const char* argv[]){
    long long result=0,tmp_value=1,num; //由于不带括号 不受数字正负影响 开头是负数也不影响
    char op;
    while(1){
        scanf("%lld %c",&num,&op);
        tmp_value*=num;
        while(op=='*' || op=='/'){ //碰到乘除优先计算 不是乘除跳出
            scanf("%lld",&num);
            if(op=='*')  tmp_value*=num;
            else tmp_value/=num;
            scanf(" %c",&op);
        }
        result+=tmp_value; 
        if(op=='+') tmp_value=1; //加号减号直接体现在临时值上
        else if(op=='-') tmp_value=-1;
        else{
            printf("%lld",result);
            break;
        }
    }
    return 0;
}

解题思路2:

应用堆栈实现 

*可以加上括号

3.小数形式与科学计数法换算(简)

【问题描述】

编写一个程序,将用小数表示的浮点数,转换成科学计数法的形式输出。输入的数据没有符号,小数点前后必有数字,且全为有效数据,即小数点后的末尾数字不为0;小数点前若只有一位数字,可以为0,否则小数点前的最高位数字不为0。

提示:以字符串形式保存相关数据。

【输入形式】

从控制台输入一小数,最后有回车换行符,所有输入的字符数不会超过100。

【输出形式】

以科学计数法形式输出数据。输出的数据由以下几部分构成:

1.底数部分是一个小数或整数,若为小数,则小数点前后必有数字,而且都为有效数字。即:小数点前只有一位大于0的数字,小数点后的末尾数字不能为0。若为整数,则只有一位数字,不带小数点。

2.必有小写字母“e”。

3.指数部分是一个整数,若大于等于0,则不带正号“+”。若小于0,则需要带负号“-”,且整数的最高位数字不为0。

【输入样例1】

0.000000000000002

【输出样例1】

2e-15

【输入样例2】

8.9845623489651700659

【输出样例2】

8.9845623489651700659e0

【输入样例3】

367298599999093453490394859509568659795603.4

【输出样例3】

3.672985999990934534903948595095686597956034e41

【样例说明】

以小数形式输入数据,然后转换成科学计数法形式输出。

解题思路:

遍历一遍找到小数点和第一位有效数字的位置 再根据一些特判解决特殊情况

代码

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <math.h>
#define LL long long
#define MAX(A,B) (A)>(B)?(A):(B)
#define MIN(A,B) (A)<(B)?(A):(B)

char s[99999];

int main(int argc,const char* argv[]){
    int len,pos_dot=-1,pos_first_num=-1;
    scanf("%s",s);
    len=strlen(s);
    for(int i=0;i<len;i++){
        if(pos_dot==-1 && s[i]=='.') pos_dot=i; //找到'.'的位置
        if(pos_first_num==-1 && s[i]!='0' && s[i]!='.'){ //找到第一个有效数字的位置
            pos_first_num=i;
            putchar(s[i]);
            if(i!=len-1) putchar('.'); //小数点后不能为0
            continue;
        }
        if(pos_first_num!=-1 && s[i]!='.') putchar(s[i]); 
    }
    if(s[0]=='0') pos_dot++; //小数点前第一位为0的情况
    printf("e%d",pos_dot-pos_first_num-1);
    return 0;
}

4. 超长正整数的减法

问题描述】

编写程序实现两个超长正整数(每个最长80位数字)的减法运算。

【输入形式】

从键盘读入两个整数,要考虑输入高位可能为0的情况(如00083)。

1. 第一行是超长正整数A;

2. 第二行是超长正整数B;

【输出形式】

输出只有一行,是长整数A减去长整数B的运算结果,从高到低依次输出各位数字。要求:若结果为0,则只输出一个0;否则输出的结果的最高位不能为0,并且各位数字紧密输出。

【输入样例】

234098

134098703578230056

【输出样例】

-134098703577995958

【样例说明】

进行两个正整数减法运算, 234098 -134098703578230056 = -134098703577995958。

【评分标准】

完全正确得20分,每个测试点4分,提交程序文件名为subtract.c。

解题思路:

注意事项:1/大减小 2/高低位 3/相同数相减

代码

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <math.h>
#define LL long long
#define MAX(A,B) (A)>(B)?(A):(B)
#define MIN(A,B) (A)<(B)?(A):(B)

#define SIZE 100 //提交发现大小设置100就够
char s1[SIZE],s2[SIZE]; 
int num1[SIZE],num2[SIZE],ans_int[SIZE];

void swap(int *a,int *b);
void HighPrecisionSub(char* s1,char* s2);

int main(int argc,const char* argv[]){
    scanf("%s%s",s1,s2); 
    HighPrecisionSub(s1,s2);
    return 0;
}

void swap(int *a,int *b){
    int t;
    t=*a;
    *a=*b;
    *b=t;
    return;
}

void HighPrecisionSub(char* s1,char* s2){
    int len,len1,len2,i,flag=0;
    len1=strlen(s1);
    len2=strlen(s2);
    len=MAX(len1,len2);
    for(i=0;i<len1;i++) num1[len1-i-1]=s1[i]-'0'; //将字符串转换为数组 注意高低位的转换
    for(i=0;i<len2;i++) num2[len2-i-1]=s2[i]-'0';
    if(len1<len2 || (len1==len2 && strcmp(s1,s2)<0)){  //将大的值放到num1里
        for(i=0;i<len;i++) swap(&num1[i],&num2[i]); 
        flag=1; //若交换 输出最前要放'-'
    }
    for(i=0;i<len;i++){ //模拟竖式减法
        ans_int[i]+=num1[i]-num2[i];
        if(ans_int[i]<0){
            ans_int[i]+=10;
            num1[i+1]--;
        }
    }
    while(ans_int[len-1]==0 && len>1) len--; //找最高位的位置 同时答案至少有一位
    if(flag) putchar('-');
    for(int i=len-1;i>=0;i--) printf("%d",ans_int[i]);
    return;
}

5. 全排列数的生成

问题描述】输入整数N( 1 <= N <= 10 ),生成从1~N所有整数的全排列。

【输入形式】输入整数N。

【输出形式】输出有N!行,每行都是从1~N所有整数的一个全排列,各整数之间以空格分隔。各行上的全排列不重复。输出各行遵循“小数优先”原则, 在各全排列中,较小的数尽量靠前输出。如果将每行上的输出看成一个数字,则所有输出构成升序数列。具体格式见输出样例。

【样例输入1】1

【样例输出1】1

【样例说明1】输入整数N=1,其全排列只有一种。

【样例输入2】3

【样例输出2】

1 2 3

1 3 2

2 1 3

2 3 1

3 1 2

3 2 1

【样例说明2】输入整数N=3,要求整数1、2、3的所有全排列, 共有N!=6行。且先输出1开头的所有排列数,再输出2开头的所有排列数,最后输出3开头的所有排列数。在以1开头的所有全排列中同样遵循此原则。

解题思路:

【46. 全排列 Permutations 【LeetCode 力扣官方题解】】 https://www.bilibili.com/video/BV1oa4y1v7Kz/?share_source=copy_web&vd_source=0133d8a1acbf30bcb8f6d49a7f69ace4

观看视频理解思路即可 不用管后面的代码实现

代码

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <math.h>
#define LL long long
#define MAX(A,B) (A)>(B)?(A):(B)
#define MIN(A,B) (A)<(B)?(A):(B)

int path[15],used[15];

void FullPermu(int n,int depth);

int main(int argc,const char* argv[]){
    int N;
    scanf("%d",&N);
    FullPermu(N,0);
    return 0;
}

void FullPermu(int n,int depth){
    int i;
    if(depth==n){ //终止条件
        for(i=0;i<n;i++) printf("%d ",path[i]); //输入排列
        putchar('\n'); 
        return;
    }
    for(i=1;i<=n;i++){
        if(used[i]) continue; //元素被使用则跳过
        path[depth]=i;
        used[i]=1; //标记元素被使用
        FullPermu(n,depth+1); //放入一个元素时 深度加一
        used[i]=0; //消除标记
    }
    return;
}
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值