长整数加法运算

27 单链表ADT模板应用算法设计:长整数加法运算(不使用单链表存储计算结果)

									作者: 冯向阳时间限制: 1S章节: DS:线性表
									
									晚于: 2021-04-18 23:55:00后提交分数乘系数50%
									
									截止日期: 2021-04-18 23:55:00

问题描述 :

		目的:使用C++模板设计单链表的抽象数据类型(ADT)。并在此基础上,使用单链表ADT的基本操作,设计并实现单链表的应用算法设计。
		
		内容:(1)请使用模板设计单链表的抽象数据类型。(由于该环境目前仅支持单文件的编译,故将所有内容都集中在一个源文件内。在实际的设计中,推荐将抽象类及对应的派生类分别放在单独的头文件中。参考网盘中的ADT原型文件。)

 

(2)ADT的应用:使用该ADT设计并实现单链表应用场合的算法设计。

 
		
		应用:假设2个任意长度的整数x、y分别由带头结点的单链表A和B存储,现要求设计一个算法,实现任意长的整数进行加法运算。

		参考函数原型:
		
		template<class ElemType>
		
		void Long_Int_Add( LinkList<ElemType> &A, LinkList<ElemType> &B, string &result, const int &len_A, const int &len_B );



辅助函数原型:

		(1)从长整数的低位开始拆分(4位为一组,即不超过9999的非负整数),依次存放在单链表的每个结点的数据域中;头结点的数据域存放正负数标志(正数或0:1,负数:-1)。
		
		template<class ElemType> 
		
		void Input_Int_Division( LinkList<ElemType> &L, string &str, int &length );  (length:长整数分割后的block数,恰为存储用单链表的长度)
		
		(2)计算结果中间位格式控制
		
		string Int_String( int result );
		
		(3)两个长整数的绝对值大小比较(x>y 返回值为1;x<y 返回值为2;x=y 返回值为0;)
		
		template<class ElemType>
		
		int Two_LongNum_Compare( LinkList<ElemType> &A, LinkList<ElemType> &B, const int &len_A, const int &len_B );
		
		(4)单链表ADT基本操作:单链表的逆置(实际计算时,鉴于单链表的顺序查找的特性,存储在单链表中的长整数需逆置,由原始的高位到低位排列,逆置为低位到高位降序排列。)
		
		template<class ElemType>
		
		void LinkList<ElemType>::ListReverse();

string 基本操作复习

//  str.substr(int pos,int length);不修改原始字符串;
//  string str1(string str0,int pos,int length);注意这里的length都是所需要赋值的长度;
// string& erase (size_t pos = 0, size_t len = npos);//仍然是从下标为零开始//
//#include<algorithm>.......reverse(str.begin(),str.end());
//str.insert(str.begin()+i,char c);
#include<iostream>
#include<string>
using namespace std;
int main()
{
    string str;
    cin>>str;
    cout<<str.substr(1,str.length()-1);
    string str1(str,1,str.length()-1);//注意这里'1',是数组下标哦//
    cout<<str1<<endl;
    str1.erase(0,str1.length());
    cout<<str1<<endl;
    str1=str1.erase(0,str1.length());
}

2.两个字符串自左向右逐个字符相比(按ASCII值大小相比较),直到出现不同的字符或遇’\0’为止。(string的大小比较),和数字的大小比较不一样

基本思路

具体代码

(如果您想优化我提供的代码块可以直接复制,修改后运行程序,看一看修改是否正确,方便最后的大程序调试的时候排除肯定正确的部分)

1. 函数实现之字符串格式化输出
#include<string>
#include<iostream>
using namespace std;
void show2( string str) //单纯只是格式化并且输出结果,值传递保证函数中的str不会影响到调用函数的地方//
{
    if(str[0]=='-')
    {
          cout<<'-';
          str.erase(0,1);
    }
    int len_str=str.length();
    int yushu=len_str%4;
    if(yushu==0)
        yushu=4;
    int flag=0;//标记是否是第一个输出的部分,来控制逗号输出格式//
    for(;str[0];)
    {    if(!flag)
        {
            cout<<str.substr(0,yushu);
            str.erase(0,yushu);
            flag=1;
        }
        else//避免str[i]==0问题,每次循环只进行一次输出//
        {
            cout<<","<<str.substr(0,4);
            str=str.erase(0,4);
        }

    }
}
int main()
{
    string str;
    cin>>str;
    show2(str);
}

2.函数实现之string转化成int(保证string没有负号的前提下)
#include<iostream>
using namespace std;
int str_int(const string &str)//将str按照它的正序转化为int类型//
{
    int wei=1,result=0;;
    for(int i=str.length()-1;i>=0;i--)//注意,str.length()==3,意味着最后面一个字符下标是2//
    {
        result+=(str[i]-'0')*wei;
        wei=wei*10;
    }
    return result;
}
int main()
{
    string str;
    cin>>str;
    cout<<str_int(str);
}

3.模板类实现,并且测试所有功能
#include<iostream>
using namespace std;
template<class ElemType>
struct Node
{
    int data;
    Node <ElemType>*next;
};
template<class ElemType>
class list_
{
private :
    Node<ElemType>* head;
    Node<ElemType>* tail;
public:
    list_()//构造函数初始化头结点//
    {
        head=tail=new Node<ElemType>;
        tail->next=NULL;
    }
    void set_(int num)//输入该链表正负信息//
    {
        head->data=num;
    }
    int Get_Set()//输出该链表正负信息//
    {
        return head->data;
    }
    void push_back_(ElemType data)//尾插(正序插入)//
    {
        Node<ElemType>* node=new Node<ElemType>;
        node->data=data;
        tail->next=node;
        tail=node;
        tail->next=NULL;
    }
    void push_front_(ElemType data)//头插(逆序插入)//
    {
        Node<ElemType>* node=new Node<ElemType>;
        node->data=data;
        node->next=head->next;
        head->next=node;
        if(node->next==NULL)//注意修改尾指针和把尾指针后面的指针域设置为空//
            tail=node;
    }
    Node<ElemType>* NextPos_(Node<ElemType> *node)//获得下一个结点,保证node非空才可调用//
    {
        return node->next;
    }
    ElemType GetData_(Node<ElemType>* node)//获得节点的数据,保证node非空才可调用//
    {
        return node->data;
    }
    Node<ElemType>* GetHead_()//获得头结点//
    {
        return head;
    }
};
template<class ElemType>
void display(list_<ElemType> L)
{
    Node<ElemType>*node=L.GetHead_();
    node=L.NextPos_(node);
    cout<<"--正序输出链表--"<<endl;
    while(node)
    {
        cout<<L.GetData_(node)<<endl;
        node=L.NextPos_(node);
    }
    cout<<endl;
}

int main()
{
    list_ <int>L;
    L.push_front_(1);
    L.push_front_(2);
    L.push_front_(3);
    L.set_(1314521);
    cout<<"L.set_ "<<L.Get_Set()<<endl;
    display<int>(L);
    L.push_back_(1);
    L.push_back_(2);
    L.push_back_(3);
    display<int>(L);
    return 0;
}

4.函数实现之比较去掉正负号的string代表的int(也就是初始数据绝对值的大小)比较
#include<iostream>
using namespace std;
int setdaxiao(string a,string b)  //a比b大应该是1,等于0,小于-1*这里的字符串是处理过没有负号的字符串//
{
    int len_a=a.length();
    int len_b=b.length();
    if(len_a>len_b)
        return 1;
    else if(len_a<len_b)
        return -1;
    else//长度相同则可以逐个字符从前往后开始比较,符合string里面大于小于号的含义//
    {
        if(a>b)
            return 1;
        else if(a<b)
            return -1;
        else
            return 0;
    }
}
int main()
{
    string str1,str2;//一定要输入正数,兄弟萌//
    cin>>str1;
    cin>>str2;
    int daxiao=setdaxiao(str1,str2);
    cout<<daxiao;
}

5.函数之输出符号与做加减法(具体逻辑和最后的程序一样,但是最后程序的简化版)
//特判: -100,100  ;0,0;0,100;100,0;0,-100;-100,0;-1,12;-12,13;-13,12;.....(关键注意最后是否需要输出负号也就是fuhao为负一)
#include<iostream>
using namespace std;
void SET_FF(int &fuhao,int &flag,int zf1,int zf2,int note)//结果为负,符号为负1,意味着要多输出一个负号,flag=2的时候做减法,flag=1的时候做加法//
{
    if(zf1*zf2>0)
    {
        if(zf1<0)//两个均为负数//
            {
                fuhao=-1;
            }
    }
    if(zf1*zf2<0)
    {
        flag=2;
        if(zf1<0&&note>0||zf2<0&&note<0)//a,b异号但是不相等//
            fuhao=-1;
    }
}
int bijiao(string a,string b)  //a比b大应该是1,等于为0,小于为-1*这里的字符串是处理过没有负号的字符串//
{
    int len_a=a.length();
    int len_b=b.length();
    if(len_a>len_b)
        return 1;
    else if(len_a<len_b)
        return -1;
    else//长度相同则可以逐个字符从前往后开始比较,符合string里面大于小于号的含义//
    {
        if(a>b)
            return 1;
        else if(a<b)
            return -1;
        else
            return 0;
    }
}
int main()
{
    string str1,str2;
    getline(cin,str1);
    getline(cin,str2);
    int zf1=1;int zf2=1;
    if(str1[0]=='-')
    {
        zf1=-1;
        cout<<"zf1 "<<zf1<<endl;
        str1.erase(0,1);
    }
    if(str2[0]=='-')
    {
        zf2=-1;
        cout<<"zf2 "<<zf2<<endl;
        str2.erase(0,1);
    }
    int note=bijiao(str1,str2);
    cout<<"note "<<note<<endl;
    int flag=1,fuhao=1;
    SET_FF(fuhao,flag,zf1, zf2,note);
    cout<<fuhao<<flag;
}
6.函数之将正数int->string
#include<iostream>
#include<algorithm>
using namespace std;
string int_str(int num)
{
    string temp;
    int i=0;
    while(num)
    {
        char c=num%10-0+'0';
        temp.insert(temp.begin(),c);//注意temp.insert(0,c)是错误的//
        num=num/10;
        i++;
    }
    return temp;
}
int main()
{
    int num;
    cin>>num;
    string str=int_str(num);
    cout<<str<<endl;
}

易错细节

1.做减法应该保证结果最前面不是零;
2.做加法应该考虑是否进位;

具体代码

	里面的注释去掉后可以方便您查看到底程序处于什么位置
#include<iostream>
#include<string>
using namespace std;
template<class ElemType>
struct Node
{
    int data;
    Node <ElemType>*next;
};
template<class ElemType>
class list_
{
private :
    Node<ElemType>* head;
    Node<ElemType>* tail;
public:
    list_()//构造函数初始化头结点//
    {
        head=tail=new Node<ElemType>;
        tail->next=NULL;
    }
    void set_(int num)//输入该链表正负信息//
    {
        head->data=num;
    }
    int Get_Set()//输出该链表正负信息//
    {
        return head->data;
    }
    void push_back_(ElemType data)//尾插(正序插入)//
    {
        Node<ElemType>* node=new Node<ElemType>;
        node->data=data;
        tail->next=node;
        tail=node;
        tail->next=NULL;
    }
    void push_front_(ElemType data)//头插(逆序插入)//
    {
        Node<ElemType>* node=new Node<ElemType>;
        node->data=data;
        node->next=head->next;
        head->next=node;
        if(node->next==NULL)//注意修改尾指针和把尾指针后面的指针域设置为空//
            tail=node;
    }
    Node<ElemType>* NextPos_(Node<ElemType> *node)//获得下一个结点,保证node非空才可调用//
    {
        return node->next;
    }
    ElemType GetData_(Node<ElemType>* node)//获得节点的数据,保证node非空才可调用//
    {
        return node->data;
    }
    Node<ElemType>* GetHead_()//获得头结点//
    {
        return head;
    }
};
string int_str(int );
void reduce(string);
void fun(string&,string&,string&);
int bijiao(string a,string b) ;
int str_int(const string &str) ;
void show( string str);
void fun(string &a,string &b,string& result) ;

template<class ElemType>
void LongIntAdd(list_<ElemType> l1,list_<ElemType> l2,int note,string &result);
template<class ElemType>
void Add(list_<ElemType> l1,list_<ElemType> l2,string &result);
template<class ElemType>
void Min(list_<ElemType> l1,list_<ElemType> l2,string &result);
template<class ElemType>
void SET_FF(int &fuhao,int &flag,int note,list_<ElemType>l1,list_<ElemType>l2,int &huan,string &result);
template<class ElemType>
void show_Init(string &str,list_ <ElemType>&L);
template<class ElemType>
void Init(string &str,list_<ElemType> &L,int &yushu);
void  reduce1(string& temp);
template<class ElemType>
void insert_(string temp,list_ <ElemType>&L);
string int_str(int num);
int bijiao(string a,string b)  //a比b大应该是1,等于0,小于-1*这里的字符串是处理过没有负号的字符串//
{
    int len_a=a.length();
    int len_b=b.length();
    if(len_a>len_b)
        return 1;
    else if(len_a<len_b)
        return -1;
    else//长度相同则可以逐个字符从前往后开始比较,符合string里面大于小于号的含义//
    {
        if(a>b)
            return 1;
        else if(a<b)
            return -1;
        else
            return 0;
    }
}
int str_int(const string &str)//将str按照它的正序转化为int类型//
{
    int wei=1,result=0;;
    for(int i=str.length()-1;i>=0;i--)//注意,str.length()==3,意味着最后面一个字符下标是2//
    {
        result+=(str[i]-'0')*wei;
        wei=wei*10;
    }
    return result;
}
void show( string str) //单纯只是格式化并且输出结果,值传递保证函数中的str不会影响到调用函数的地方//
{
    cout<<endl;
    if(str[0]=='-')
    {
          cout<<'-';
          str.erase(0,1);
    }
    int len_str=str.length();
    int yushu=len_str%4;
    if(yushu==0)
        yushu=4;
    int flag=0;//标记是否是第一个输出的部分,来控制逗号输出格式//
    for(;str[0];)
    {    if(!flag)
        {
            cout<<str.substr(0,yushu);
            str.erase(0,yushu);
            flag=1;
        }
        else//避免str[i]==0问题,每次循环只进行一次输出//
        {
            cout<<","<<str.substr(0,4);
            str=str.erase(0,4);
        }

    }
    cout<<endl;
}

template<class ElemType>
void fun(string &a,string &b,string& result)
{
    getline(cin,a);
    getline(cin,b);
    list_<ElemType>l1;
    list_<ElemType>l2;
    show_Init(a,l1);
    show_Init(b,l2);
    int note=bijiao(a,b);//最主要的函数//
   // cout<<"note  "<<note<<endl;//
    LongIntAdd(l1,l2,note,result);
}


template<class ElemType>
void LongIntAdd(list_<ElemType> l1,list_<ElemType> l2,int note,string &result)
{
    int fuhao=1,flag=1,huan=0;//符号为1为正或零,为-1为负// //flag为一表示加法,为二表示减法//

    SET_FF(fuhao,flag,note,l1,l2,huan,result);  //  cout<<"fuhao "<<fuhao<<"huan "<<huan<<endl;
    if(flag==1)
        Add(l1,l2,result);
    else
    {
        if(!huan)
        Min(l1,l2,result);
        else
        Min(l2,l1,result);
    }

}

template<class ElemType>
void Add(list_<ElemType> l1,list_<ElemType> l2,string &result)
{
     //cout<<"ADD"<<endl;//
    string temp;int flag=0;
    Node<ElemType>*node1=l1.NextPos_(l1.GetHead_());
    Node<ElemType>*node2=l2.NextPos_(l2.GetHead_());
    while(node1&&node2)
    {
        int sum=l1.GetData_(node1)+l2.GetData_(node2);
        if(flag)
            sum++;
        if(sum>=10000)
        {
            sum=sum-10000;
            flag=1;
        }
        else
            flag=0;
        string temp1=int_str(sum);
        string temp2=temp1+temp;
        temp=temp2;
        node1=l1.NextPos_(node1);
        node2=l2.NextPos_(node2);
    }

     while(node1)
    {
        int sum=l1.GetData_(node1);
        if(flag)
            sum++;
        if(sum>=10000)
        {
            sum=sum-10000;
            flag=1;
        }
        else
            flag=0;
        string temp1=int_str(sum);
        string temp2=temp1+temp;
        temp=temp2;
        node1=l1.NextPos_(node1);
    }

        while(node2)
    {
        int sum=l2.GetData_(node2);
        if(flag)
            sum++;
        if(sum>=10000)
        {
            sum=sum-10000;
            flag=1;
        }
        else
            flag=0;
        string temp1=int_str(sum);
        string temp2=temp1+temp;
        temp=temp2;
        node2=l2.NextPos_(node2);
    }
    if(flag)
    {
        string temp2="1"+temp;
        temp=temp2;
    }
    reduce1(temp);
    result=result+temp;
}

template<class ElemType>
void Min(list_<ElemType> l1,list_<ElemType> l2,string &result)
{
   // cout<<"MIN"<<endl;//
    string temp;int flag=0;
    Node<ElemType>*node1=l1.NextPos_(l1.GetHead_());
    Node<ElemType>*node2=l2.NextPos_(l2.GetHead_());
    while(node1&&node2)
    {
        int sum=l1.GetData_(node1)-l2.GetData_(node2);
        if(flag)
            sum--;
        if(sum<0)
        {
            sum=sum+10000;
            flag=1;
        }
        else
            flag=0;
        string temp1=int_str(sum);
        string temp2=temp1+temp;
        temp=temp2;
        node1=l1.NextPos_(node1);
        node2=l2.NextPos_(node2);
    }
     while(node1)
    {
        int sum=l1.GetData_(node1);
        if(flag)
            sum--;
        if(sum<0)
        {
            sum=sum+10000;
            flag=1;
        }
        else
            flag=0;
        string temp1=int_str(sum);
        string temp2=temp1+temp;
        temp=temp2;
        node1=l1.NextPos_(node1);
    }
      //cout<<temp<<" temp"<<endl;//
    reduce1(temp);
    result=result+temp;
    //cout<<result<<" result"<<endl;//
}

void  reduce1(string& temp)
{
    //cout<<"&&&&"<<endl;//
    while(true)
    {
        if(temp[0]!='0')//注意temp[0]!='0'不是temp[0]!=0//
            break;
        else
            temp.erase(0,1);
        //cout<<"********"<<endl;//
    }
    if(temp[0]==0)
        temp+='0';//满足最后全为零的情况//
}

string int_str(int num)
{
    string temp;
    int i=0;
    while(num)
    {
        char c=num%10-0+'0';
        temp.insert(temp.begin(),c);//注意temp.insert(0,c)是错误的//
        num=num/10;
        i++;
    }
    int cha=4-temp.length();
    temp.insert(0,cha,'0');
    return temp;
}
template<class ElemType>
void SET_FF(int &fuhao,int &flag,int note,list_<ElemType>l1,list_<ElemType>l2,int &huan,string &result)
{
    int zf1=l1.GetData_(l1.GetHead_());
    int zf2=l2.GetData_(l2.GetHead_());
    //cout<<"zf1 "<<zf1<<"zf2 "<<zf2<<endl;//
    if(zf1*zf2>0)
    {
        if(zf1<0)
            {
                fuhao=-1;//两个都为负数//
            }
    }
    if(zf1*zf2<0)
    {
        flag=2;
        if(zf1<0&&note==1||zf2<0&&note==-1)
        {
             fuhao=-1;//一个负数比一个正数大//
        }
        if(note<0)
            huan=1;
    }
    if(fuhao==-1)
        result+="-";
}


template<class ElemType>
void show_Init(string &str,list_ <ElemType>&L)//格式化输出初始字符串并且创建链表,与函数show()唯一的区别就是增加一个insert_()函数的调用//
{
    int yushu;
    Init(str,L,yushu);//删除字符串前面的负号并且保存在头结点中并且输出,同时返回余数//
    string str1=str;//注意循环结束条件是str为空,所以不能破坏原有的string//
    for(int flag=0;str1[0];)
    {
        if(!flag)//flag标记第一个最前面的yushu个数字输出//
        {
            string temp=str1.substr(0,yushu);
            cout<<temp;
            insert_(temp,L);//将这个字符串转化成int类型整数后头插到带有头结点的单链表里//
           str1=str1.erase(0,yushu);
            flag=1;
        }
        else
        {
            string temp=str1.substr(0,4);
            cout<<","<<temp;
            insert_(temp,L);
            str1=str1.erase(0,4);
        }
    }
    cout<<endl;
}

template<class ElemType>
void Init(string &str,list_<ElemType> &L,int &yushu)//创建链表头结点并且删除本来含符号的第一项,引用类型传递余数长度等信息,注意零保存的是+1//
{
     if(str[0]=='-')
    {
        str=str.substr(1,str.length()-1);
        L.set_(-1);
         cout<<"-";
    }
    else
        L.set_(1);
    yushu=str.length()%4;
    if(!yushu)//余数为零设置为四//
        yushu=4;
    //cout<<"str is "<<str<<endl;//
}

template<class ElemType>
void insert_(string temp,list_ <ElemType>&L)//将这一小段string temp转化为int 头插入链表//
{
    int num=str_int(temp);
    L.push_front_(num);
}

int main()
{
    string a,b,result;
    fun<int>(a,b,result);
    show(result);
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值