算法设计与分析作业

算法设计与分析作业

题⽬1 - 使⽤分治算法实现⼗进制⼤整数相乘

一、要求

  1. 给出代码(了解markdown格式如何插入⼀段代码)
  2. 复杂度为 。n为整数的位数。
  3. ⾄少包含add(a,b) minus(a,b) multiply(a,b)三个函数。
  4. ⾃⾏设计测试样例,测试你的程序的正确性和健壮性。给出测试结果。

二、程序如下

#include <iostream>
#include <string.h>
#include<algorithm>
using namespace std;

string multi(string number_a, string number_b) {
    if(number_a=="0"||number_b=="0")return "0";
    int flag1=1;
    int len_a = number_a.length(); //计算长度
    int len_b = number_b.length();

    int* num_arr = new int[len_a+len_b];
    memset(num_arr, 0, sizeof(int)*(len_a+len_b)); //置0

    for (int i=len_a-1; i>=0; --i) { //计算每一位
        for (int j=len_b-1; j>=0; --j) {
        num_arr[i+j+1] += (number_b[j]-'0')*(number_a[i]-'0');
        }
    }

    for (int i=len_a+len_b-1; i>=0; --i) { //进位
        if (num_arr[i] >= 10) {
        	num_arr[i-1] += num_arr[i]/10;
        	num_arr[i] %= 10;
        }
    }
    string result;

    for( int i=0; i<(len_a+len_b); ++i){
        if(num_arr[i]==0&&flag1)continue;
          else flag1=0;
    	result += (char)(((int)'0')+num_arr[i]);
    }


    delete[] num_arr;

    return result;
}
int compareNumber(string a,string b)
{
    if(a.length()>b.length())return 1;
    else if(a.length()<b.length())return -1;
    else
    {
        if(a>b)return 1;
        else if(a<b)return -1;
        else return 0;
    }
}
string add(string number_a, string number_b) {

    string result;
    int i;
    if(compareNumber(number_a,number_b)==-1)swap(number_a,number_b);
    int len_a = number_a.length(); //计算长度
    int len_b = number_b.length();

    int* num_arr = new int[len_a+1];
    memset(num_arr, 0, sizeof(num_arr)); //置0

    for (i=1; i<=len_b; i++) { //计算每一位
        num_arr[len_a-i+1] = (number_b[len_b-i]-'0')+(number_a[len_a-i]-'0');
    }
    for(;i<=len_a;i++)
    {
        num_arr[len_a-i+1]=number_a[len_a-i]-'0';
    }
    for (int i=len_a; i>=0; --i) { //进位并转换成字符串
        if (num_arr[i] >= 10) {
        	num_arr[i-1] += 1;
        	num_arr[i] %= 10;
        }
        if(i==0&&num_arr[0]==0)continue;
    	result = (char)(((int)'0')+num_arr[i])+result;
    }

    delete[] num_arr;
    return result;
}
string Minus(string number_a, string number_b) {

    string result;
    int i,flag=0,flag1=1;
    if(compareNumber(number_a,number_b)==-1)
    {
        swap(number_a,number_b);
        flag=1;
    }
    if(number_a==number_b)return "0";
    int len_a = number_a.length(); //计算长度
    int len_b = number_b.length();

    int* num_arr = new int[len_a+1];
    memset(num_arr, 0, sizeof(num_arr)); //置0

    for (i=1; i<=len_b; i++) { //计算每一位
        num_arr[len_a-i+1] = (number_a[len_a-i]-'0')-(number_b[len_b-i]-'0');
    }
    for(;i<=len_a;i++)
    {
        num_arr[len_a-i+1]=number_a[len_a-i]-'0';
    }
    for (int i=len_a; i>=1; --i) { //进位并
        if (num_arr[i] < 0) {
        	num_arr[i-1]--;
        	num_arr[i] += 10;
        }
    }
        for (int i=0; i<=len_a; i++) { //转换成字符串
          if(num_arr[i]==0&&flag1)continue;
          else flag1=0;
    	result += (char)(((int)'0')+num_arr[i]);
    }
    if(flag)result="-"+result;
    delete[] num_arr;

    return result;
}
void addzone(string &number,int num)
{
    while(num--)
    {
        number+="0";
    }
}
string multi1(string number_a,string number_b)
{
    string a0,a1,b1,b0,c0,c1,c2,a2,b2;
    int half;
    int len_a=number_a.size();
    int len_b=number_b.size();
    if(len_a<=2||len_b<=2)return multi(number_a,number_b);
    if(len_a<len_b)return multi1(number_b,number_a);
    if(len_a==0||len_b==0)return "";
    if(len_a/2>=len_b)half=len_b-1;
    else half=len_a/2;
    a1=number_a.substr(0,len_a-half);
    a0=number_a.substr(len_a-half,half);
    b1=number_b.substr(0,len_b-half);
    b0=number_b.substr(len_b-half,half);
     c1=multi1(a1,b1);
     c0=multi1(a0,b0);
     a2=add(a1,a0);
     b2=add(b0,b1);

     c2=multi1(a2,b2);
     c2=Minus(c2,c1);
     c2=Minus(c2,c0);
    addzone(c1,half*2);
    addzone(c2,half);

    string result=add(add(c1,c0),c2);
    return result;
}
bool checkNumberValid(string a,string b)
{
    for(int i=0;i<a.length();i++)
    {
        if(i==0&&(a[i]<=57&&a[i]>=48||a[i]==45))continue;
        if(a[i]>57||a[i]<48)return false;
    }
        for(int i=0;i<b.length();i++)
    {
        if(i==0&&(b[i]<=57&&b[i]>=48||b[i]==45))continue;
        if(b[i]>57||b[i]<48)return false;
    }
    return true;
}
int main(void){

    string number_a,number_b;
    int index=1;
    while(cin>>number_a>>number_b)
    {
        cout<<"第"<<index++<<"次"<<endl;
        if(!checkNumberValid(number_a,number_b))
        {
            cout<<"Please input the Valid Number"<<endl<<endl;
            continue;
        }
       // cout << number_a << " * " << number_b << " = " <<multi(number_a, number_b) <<endl;
        cout<<number_a<<"+"<<number_b<<"="<<add(number_a,number_b)<<endl;
        cout<<number_a<<"-"<<number_b<<"="<<Minus(number_a,number_b)<<endl;
        cout << number_a << " * " << number_b << " = " <<multi1(number_a, number_b) <<endl;
        cout<<endl;
    }
    return 0;
}
测试样例:

55513513133535351 3513535133135133
535 123
153153 253
25 0
0 135513
22222 22222
2a 122
2153 222c
5555555555555555555555555555555555555555555555555 44444 555555
111111111111111111111111111111111888888888888888888888888888888888888888888

三、完成情况如下

任务0:给出代码。完成
任务1 :复杂度为 。n为整数的位数。multi1采用Karatsuba算法实现乘法的优化。完成
2. ⾄少包含add(a,b) minus(a,b) multiply(a,b)三个函数。完成
3. ⾃⾏设计测试样例,测试你的程序的正确性和健壮性。给出测试结果。

a.正确性判断

我拿出科学计算器测试了程序的加法,减法,乘法与程序运行结果一致。
在这里插入图片描述

b.健壮性

在这里插入图片描述
在这里插入图片描述

  • 1.当输入的字符串里面含有非法字符会提示:"Please input the Valid Number 并等待下一次输出。
  • 2.同时该算法也支持负数计算
  • 3.自动去除多余的零

题⽬2 - ⽤快速排序思想写⼀个分治的查找第K⼩元素的程序

一、要求

  1. 给出代码
  2. 给出证明代码可以正确运⾏的截图
  3. 分析最坏复杂度和平均复杂

二、程序

#include<iostream>
#include<stdlib.h>
using namespace std;
int a[101],n;
void quickFind(int left,int right,int k)
{
    int i,j,t,temp;
    if(left>right)return;
    i=left,j=right;
    while(i!=j)
    {
        //顺序很重要,要先从右往左找
        while(a[j]>=a[left]&&i<j)j--;
        //从左往右找
        while(a[i]<=a[left]&&i<j)i++;
        //找到后交换两个数的位置
        if(i<j)swap(a[i],a[j]);

    }
    //最后将基准数归位

    swap(a[i],a[left]);

    if(k==i)cout<<a[k]<<endl;
    else if(k<i)quickFind(left,i-1,k);//处理左边
    else quickFind(i+1,right,k);//处理右边

}
int main()
{
    int k;
    while(1)
    {
    cout<<"请输入数组的大小:"<<endl;
    cin>>n;
    cout<<"请输入"<<n<<"个实数"<<endl;
    for(int i=1;i<=n;i++)cin>>a[i];
    cout<<"请输入一个整数表示要求的第k小的:"<<endl;
    cin>>k;
    if(k<1||k>n)
    {
        cout<<"请输入有效数字"<<endl;
        continue;
    }
    cout<<"第"<<k<<"小的数字为:";
    quickFind(1,n,k);

    system("pause");
    system("CLS");
    }
    return 0;
}

样例与输出

样例

11
153351 131 513 135 15 35 1351 3513 15353 11 22
4

输出

在这里插入图片描述

这个算法的平均时间复杂度是O ( n ) 的,每一次快排为n,在有序下平均c次即可找到(c为常量),但在最坏情况下的时间复杂度是O ( n 2 )比如:9 8 7 6 5 4 3 2 1,求第9大。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
国科大的算法设计与分析相关1-5章复习题 第一章样: 1.讲义习题一: 第1(执行步改为关键操作数)、第2、3、6、7题 习题一 1答:执行步4pmn+3pm+2m+1;关键操作2n*m*p 2方法一答:2n-2次 方法二答:2n-2次 3 1)证明:任给c,n>c,则10n2>cn 。不存在c使10n22c时,logn>c,从而n2logn>=cn2,同上。 6 答:logn,n2/3,20n,4n2,3n,n! 7 答:1)6+n 2) 3)任意n 2.讲义习题二:第5题。 答:c、e是割点。每点的DFN、L值:A1,1、B2,1、C3,1、D4,4、E5,1、F6,5、G7,5。最大连通分支CD、EFG、ABCE。 3.考虑下述选择排序算法输入:n个不等的整数的数组A[1..n] 输出:按递增次序排序的A For i:=1 to n-1 For j:=i+1 to n If A[j]<A[i] then A[i] A[j] 问:(1)最坏情况下做多少次比较运算?答1+2+..+n-1=n(n-1)/2 (2)最坏情况下做多少次交换运算?在什么输入时发生? n(n-1)/2,每次比较都交换,交换次数n(n-1)/2。 4.考虑下面的每对函数f(n)和g(n) ,比较他们的阶。 (1) f(n)=(n2-n)/2, g(n)=6n (2)f(n)=n+2 , g(n)=n2 (3)f(n)=n+nlogn, g(n)=n (4)f(n)=log(n!), g(n)= 答:(1)g(n)=O(f(n)) (2)f(n)=O(g(n) (3)f(n)=O(g(n) (4)f(n)=O(g(n) 5.在表中填入true或false . 答案: f(n) g(n) f(n)=O(g(n) f(n)=(g(n)) f(n)=(g(n)) 1 2n3+3n 100n2+2n+100 F T F 2 50n+logn 10n+loglogn T T T 3 50nlogn 10nloglogn F T F 4 logn Log2n T F F 5 n! 5n F T F 6.用迭代法求解下列递推方程: (1) (2) ,n=2k 答:(1)T(n)=T(n-1)+n-1=T(n-2)+n-2+n-1 =…=T(1)+1+2+…+n-1=n(n-1)/2=O(n2) (2)T(n)=2T(n/2)+n-1=2(2T(n/4)+n/2-1)+n-1 =4T(n/4)+n-2+n-1=4(2T(n/23)+n/4-1)+n-2+n-1 =23T(n/23)+n-4+n-2+n-1

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

风吹落叶花飘荡

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值