BUAA数据结构与程序设计第一次作业复习

准备把之前的作业都再写一遍作为复习,方法可能并不是最佳的,如有大佬请指点啊~

扩展字符A(43min)

扩展字符A

【问题描述】

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

要求:只处理[a-z]、[A-Z]、[0-9]范围内的字符扩展,即只有当扩展符前后的字符同时是小写字母、大写字母或数字,并且扩展符后的字符大于扩展符前的字符时才进行扩展,其它情况不进行扩展,原样输出。例如:a-R、D-e、0-b、4-B等字符串都不进行扩展。

【输入形式】

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

【输出形式】

输出扩展后的字符串

【输入样例1】

ADEa-g-m02

【输出样例1】

ADEabcdefghijklm02

【输入样例2】

cdeT-bcd

【输出样例2】

cdeT-bcd

【样例说明】

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

【评分标准】

该题要求扩展字符,提交程序文件expand.c。

c 复制代码
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<ctype.h>
void Expand(char*,int);
int main()
{
    char str[1000];
    gets(str);
    int newlen=strlen(str);

    int i=0;
    while(str[i]!='\0')
    {
        if(i>0&&i<newlen&&str[i]=='-')
        {
            if(str[i-1]>='a'&&str[i+1]<='z'||str[i-1]>='A'&&str[i+1]<='Z'||str[i-1]>='0'&&str[i+1]<='9')
            {
                int oldlen=strlen(str);
                Expand(str,i);
                newlen=strlen(str);
                i=i+(newlen-oldlen+1);
            }
        }
        i++;
    }
    printf(str);
}
void Expand(char* str,int i)
{
    int expandlen=str[i+1]-str[i-1]-1;
    int movelen=strlen(str)-i-1;
    memmove(str+i+1+expandlen-1,str+i+1,sizeof(char)*(movelen+1));
    int j=i;
    for(;j<i+expandlen;j++)
    {
        str[j]=str[j-1]+1;
    }
}

注:此题有以下需要注意的地方

  • 第一次做的时候还不知道有memmove这么好的函数,所以多写了好多行用于调整位置,但是这个函数在用的时候要注意,我们这里移动的是从 ' - ' 到字符串末尾,包含'\0',而在代码中,movelen记录的长度仅为有效长度,因此在使用memmove的时候,最后一个参数应该给movelen+1;
  • 然后就是更新字符串以及下标这部分,我们画图看:
  • 在扩展前,i为4,扩展后,怎么调整呢?
  • 扩展后字符串长度 -- 扩展前字符串长度 + 1就是黄色部分的长度,我们设这个长度为x
  • i + x是不是就相当于i指向了g?然后在if语句之外,还有一个不受任何if约束的i++,那现在i是不是就指向g的下一位-了呀?至于g,不需要再参与到遍历当中。

表达式计算

这个题留到后面,我整理一个表达式计算的方法合集。

小数形式与科学计数法转换(简)(50min)

【问题描述】

编写一个程序,将用小数表示的浮点数,转换成科学计数法的形式输出。输入的数据没有符号,小数点前后必有数字,且全为有效数据,即小数点后的末尾数字不为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

【样例说明】

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

【评分标准】

该题要求以科学计数法形式输出数据,提交程序文件名为notation.c。

输入的小数有以下几种情况:

我们大体可以先分为这几种情况,然后再做具体操作

if(str[0]=='0')
{

}
else if(strlen(str)==1||str[0]>='0'&&str[0]<='9'&&str[1]=='.')
{

}
else if(strlen(str)>=3&&str[0]>='0'&&str[0]<='9'&&str[1]>='0'&&str[1]<='9')
{
    
}

第一种情况,小数点右移的数目等于从左向右数第一个非零的数的下标 -- 小数点下标。若小数点移到了最后一位,则最后一位赋值为'\0'.
第二种情况,直接输出即可。
第三种情况,小数点左移次数等于小数点下标 -- 1,如果是整数,则假设小数点在字符串末尾。

c 复制代码
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<stdbool.h>
void transform_1(char*);
void transform_2(char*);
int main()
{
    char str[150];
    scanf("%s",str);
    
    if(str[0]=='0')
    {
        transform_1(str);
    }
    else if(strlen(str)==1||str[0]>='0'&&str[0]<='9'&&str[1]=='.')
    {
        printf("%se0",str);
    }
    else if(strlen(str)>=3&&str[0]>='0'&&str[0]<='9'&&str[1]>='0'&&str[1]<='9')
    {
        transform_2(str);
    }
    return 0;
}
void transform_1(char* str)
{
    int exponent=0;
    int i=0;
    for(;i<strlen(str);i++)
    {
        if(str[i]>'0'&&str[i]<'9')
        {
            exponent=1-i;
            break;
        }
    }
    if(str[i+1]!='\0')
    {
        memmove(str+i+1+1,str+i+1,sizeof(char)*(strlen(str)-i));
        str[i+1]='.';
        memmove(str,str+i,sizeof(char)*(strlen(str)-i+1));
        printf("%se%d",str,exponent);
    }
    else
    {
        printf("%ce%d",str[i],exponent);
    }
}
void transform_2(char*str)
{
    int exponent=0;
    char*p=strchr(str,'.');
    if(p==NULL)
    {
        int len=strlen(str);
        str[len]='.';
        str[len+1]='\0';
        exponent=len-1;
        memmove(str+2,str+1,sizeof(char)*(strlen(str)));
        str[1]='.';
    }
    else
    {
        exponent=p-str-1;
        int i=p-str;
        memmove(str+i,str+i+1,sizeof(char)*(strlen(str)-i));
        memmove(str+2,str+1,sizeof(char)*strlen(str));
        str[1]='.';
    }
    int j=strlen(str)-1;
    while(str[j]!='.')
    {
        if(str[j]=='0')
        {
            str[j]='\0';
            j--;
        }
        else
        {
            break;
        }
    }
    if(str[strlen(str)]=='.')
        str[strlen(str)]='\0';
    printf("%se%d",str,exponent);
}

超长正整数的减法(71min)

【问题描述】

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

【输入形式】

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

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

【输出形式】

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

【输入样例】

234098

134098703578230056

【输出样例】

-134098703577995958

【样例说明】

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

【评分标准】

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

c 复制代码
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
int flag=0;
void front_zero(char*);
void subtract(char*,char*);
void reverse(char*);

int main()
{
    char minuend[100];
    char subtran[100];
    gets(minuend);
    gets(subtran);
    front_zero(minuend);
    front_zero(subtran);

    if(strlen(minuend)<strlen(subtran))
    {
        flag=1;
        char tmp[100];
        strcpy(tmp,minuend);
        strcpy(minuend,subtran);
        strcpy(subtran,tmp);
    }
    else if(strlen(minuend)==strlen(subtran))
    { 
        int cmp=strcmp(minuend,subtran);
        if(cmp==0)
        {
            printf("0");
            exit(1);
        }
        else if(cmp<0)
        {
            flag=1;
            char tmp[100];
            strcpy(tmp,minuend);
            strcpy(minuend,subtran);
            strcpy(subtran,tmp);
        }
    }   
    
    subtract(minuend,subtran);

}
void reverse(char* a)
{
    int i,j;
    for(i=0,j=strlen(a)-1;i<j;i++,j--)
    {
        char tmp=a[i];
        a[i]=a[j];
        a[j]=tmp;
    }
}
void subtract(char*a,char*b)
{
    char c[100];
    reverse(a);
    reverse(b);
    
    int j=0;
    int x,y;
    while(b[j]!='\0')
    {
        if(a[j]<b[j])
        {
            x=a[j]-'0'+10;
            y=b[j]-'0';
            a[j+1]--;   
        }
        else
        {
            x=a[j]-'0';
            y=b[j]-'0';
        }
        c[j]=x-y+'0';
        j++;
    }
    c[j]='\0';
    if(b[j]=='\0'&&a[j]!='\0')
    {
        strcat(c,a+j);
    }
    reverse(c);
    front_zero(c);
    if(flag==1)
    {
        printf("-%s",c);
    }
    else
        printf("%s",c);
}
void front_zero(char* str)
{   
   
    if(strlen(str)>1&&str[0]=='0')
    {
        int j=0;
        while(str[j++]=='0');
        j--;
        memmove(str,str+j,sizeof(char)*(strlen(str)-j+1));
    }
}
  • 这道题要注意的是:
  • 要先判断大小,大的做被减数,小的做减数,如果调换,那么最后输出的时候打印负号
  • 做减法时要先逆转字符串
  • 最后要给差也前端去零
  • 调换字符串的时候,不要用指针很容易错,就老老实实地用strcpy三次

全排列数的生成

【问题描述】输入整数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开头的所有全排列中同样遵循此原则。

【样例输入3】10

【样例输出3】

1 2 3 4 5 6 7 8 9 10

1 2 3 4 5 6 7 8 10 9

1 2 3 4 5 6 7 9 8 10

1 2 3 4 5 6 7 9 10 8

1 2 3 4 5 6 7 10 8 9

1 2 3 4 5 6 7 10 9 8

1 2 3 4 5 6 8 7 9 10

1 2 3 4 5 6 8 7 10 9

1 2 3 4 5 6 8 9 7 10

1 2 3 4 5 6 8 9 10 7

........................

【样例说明3】输入整数N=10,要求整数1、2、3、......、10的所有全排列。上例显示了输出的前10行。

【运行时限】要求每次运行时间限制在20秒之内。超出该时间则认为程序错误。提示:当N增大时,运行时间将急剧增加。在编程时要注意尽量优化算法,提高运行效率。

【评分标准】该题要求输出若干行整数。。

这道题我当时是看一个b站视频写的,up讲的真的超级好,链接放这里有需要的自取哈,记得给up三连link

主要思想就是递归,想不明白的可以画一画递归展开图,一会儿给大家放个事例:

c 复制代码
#include<stdio.h>
#include<stdlib.h>
void perm(int [],int,int);
void printArry(int [],int);
void swap(int [],int,int);
void swapback(int [],int,int);
int main()
{
    int N;
    scanf("%d",&N);
    
    int* arr=(int*)malloc(sizeof(int)*N);
    for(int i=0;i<N;i++)
    {
        arr[i]=i+1;
    }
    perm(arr,0,N-1);
    return 0;
}
void perm(int arr[],int p,int q)
{
    if(p==q)
    {
        printArry(arr,q+1);
        return;
    }
    else
    {
        for(int i=p;i<=q;i++)
        {
            swap(arr,p,i);
            perm(arr,p+1,q);
            swapback(arr,p,i);
        }
    }
}
void printArry(int arr[],int n)
{
    for(int i=0;i<n;i++)
    {
        printf("%d ",arr[i]);
    }
    printf("\n");
}
void swap(int arr[],int p,int q)
{
    int temp=arr[q];
    for(int i=q;i>=p+1;i--)
    {
        arr[i]=arr[i-1];
    }
    arr[p]=temp;
}
void swapback(int arr[],int p,int q)
{
    int temp=arr[p];
    for(int i=p;i<=q-1;i++)
    {
        arr[i]=arr[i+1];
    }
    arr[q]=temp;
}
  • 简化思路就是,把每一位数与第一位数进行字典序的交换,然后让后面的数进行排列直至只剩一个数。

好啦今天就复习完毕了,明天接着肝剩下的内容(呜呜呜内容好多大佬保佑我)

相关推荐
朱一头zcy8 分钟前
C语言复习第9章 字符串/字符/内存函数
c语言
此生只爱蛋11 分钟前
【手撕排序2】快速排序
c语言·c++·算法·排序算法
blammmp18 分钟前
Java:数据结构-枚举
java·开发语言·数据结构
何曾参静谧31 分钟前
「C/C++」C/C++ 指针篇 之 指针运算
c语言·开发语言·c++
昂子的博客40 分钟前
基础数据结构——队列(链表实现)
数据结构
lulu_gh_yu1 小时前
数据结构之排序补充
c语言·开发语言·数据结构·c++·学习·算法·排序算法
~yY…s<#>3 小时前
【刷题17】最小栈、栈的压入弹出、逆波兰表达式
c语言·数据结构·c++·算法·leetcode
XuanRanDev4 小时前
【每日一题】LeetCode - 三数之和
数据结构·算法·leetcode·1024程序员节
代码猪猪傻瓜coding4 小时前
力扣1 两数之和
数据结构·算法·leetcode
EricWang13585 小时前
[OS] 项目三-2-proc.c: exit(int status)
服务器·c语言·前端