长整数加法运算(双向链表)

长整数加法运算

问题描述

假设2个任意长度的整数x、y分别由双向链表A和B存储,现要求设计一个算法,实现x+y。计算结果存储在链表C中。

说明:

由于A和B输出时需要从头至尾遍历,而做加法时需要从尾至头遍历,因此使用双向链表存储。

可以从长整数的低位开始拆分(4位为一组,即不超过9999的非负整数),依次存放在链表的每个结点的数据域中;头结点的数据域存放正负数标志(正数或0:1,负数:-1)。

输入说明

第一行:长整数x

第二行:长整数y

输出说明

第一行:格式化后的长整数x(从低位到高位每4位用","分开)

第二行:格式化后的长整数y(从低位到高位每4位用","分开)

第三行:空行

第四行:单链表C的遍历结果

第五行:格式化后的计算结果(从低位到高位每4位用","分开)

(输入与输出之间用一空行分隔)

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

struct node{         //num ºÍ next
   int num;
   struct node* next;
   struct node* pre;
};

struct node* create(string s){   //采用头插法插入

   struct node* head = new node;
   head->next = NULL;
   head->pre = NULL;
   int l;
   if(s[s.length() - 1] == '-'){
    l = s.length()-1;
    head->num = -1;
   }
   else{
    l = s.length();
    head->num = 1;
   }

   int f = 0;
   int num = 0;
   for(int i = 0;i < l;i++){

    num += (int)(s[i]-'0') * (pow(10,f)+0.1);
    f++;

    if(f == 4 || i == l-1){    //当读取4个数时重置

        //cout<<"*****"<<num<<"******"<<endl;
        struct node* p = new node;
        p->num = num;
        struct node* q = head->next;

        head->next = p;
        p->pre = head;
        p->next = q;
        if(q)
            q->pre = p;

        f = 0;
        num = 0;
    }

   }   //for
   return head;
}
void display(struct node* num){

   if(num->next){

   if(num->num == -1)
    cout<<'-';
   struct node* p = num->next;
   cout<<p->num;
   p = p->next;
   while(p){
    if(p == num->next)
        printf("%04d",p->num);
        //cout<<abs(p->num);
    else
        printf(",%04d",p->num);

    p = p->next;
   }

   }
   else
    cout<<0;
}

struct node* add(struct node* num1,struct node* num2){

    struct node* head = new node;
    head->next = NULL;
    head->pre = NULL;
    //cout<<"1";
    struct node* p = num1;
    struct node* q = num2;
    //cout<<"2";
    while(p->next)
        p = p->next;
    //cout<<"3";
    while(q->next)
        q = q->next;


    //cout<<"4";

    while(p != num1 && q != num2){          //从尾部到头部进行加遍历

        struct node* t = new node;
        //cout<<"111";
        struct node* o = head->next;
        //cout<<"2222";
        t->num = num1->num*p->num + num2->num*q->num;

        head->next = t;
        t->pre = head;
        t->next = o;
        if(o)
            o->pre = t;

        p = p->pre;
        q = q->pre;
    }

    while(p != num1){     //类似于合并有序表,对没有运算的结点采用头部插入的方法

        struct node* t = new node;
        struct node* o = head->next;

        t->num = num1->num * p->num;

        head->next = t;
        t->pre = head;
        t->next = o;
        if(o)
            o->pre = t;
        p = p->pre;
    }

    while(q != num2){

        struct node* t = new node;
        struct node* o = head->next;

        t->num = num2->num * q->num;

        head->next = t;
        t->pre = head;
        t->next = o;
        if(o)
            o->pre = t;
        q = q->pre;
    }

    //display(head);
    if(head->next->num > 0)    //判断最后的取值是正是负
        head->num = 1;
    else
        head->num = -1;

    p = head;
    while(p->next)
        p = p->next;
    q = p;

    while(p != head){                 //对结果进行处理

        if(p->num * head->num < 0){  //正数借位减一,负数借位加1
            if(head->num > 0){
                p->num += 10000;
                p->pre->num -= 1;
            }
            else{
                p->num -= 10000;
                p->pre->num += 1;
            }
        }

        p = p->pre;
    }
    //cout<<5;
    p = head->next;

    while(p){
        p->num = abs(p->num);
        p = p->next;
        }
    //cout<<6<<endl;
    while(q != head->next){          //进行进位处理
        if(q->num >= 10000){
            q->num -= 10000;
            q->pre->num += 1;
        }
        q = q->pre;
    }

    if(q && q->num >= 10000){

        struct node* t = new node;
        t->next = q;
        q->pre = t;
        head->next = t;
        t->pre = head;
        t->num = q->num / 10000;
        q->num = q->num % 10000;
    }

    p = head->next;  //当前边出现0时删除该结点
    while(p && p->num == 0){
       p->pre->next = p->next;

       if(p->next)
         p->next->pre = p->pre;
       p = p->next;
    }
    return head;
};
void display_2(struct node* head){

   if(head->next){
      struct node* p = head->next;

      cout<<p->num;
      p = p->next;
      while(p){
        printf("->%04d",p->num);
        p = p->next;
      }
      cout<<endl;
      }
   else
    cout<<0<<endl;
}
/*
测试用例
-109921335327
74111423
-1099 5278 -3904

-  1098 4722 3904
*/
int main(){

   //cout<<8*pow(10,0);
   string s1,s2;
   struct node *num1,*num2,*c;

   cin>>s1;
   cin>>s2;


   reverse(s1.begin(),s1.end());
   num1 = create(s1);
   display(num1);
   cout<<endl;

   reverse(s2.begin(),s2.end());
   num2 = create(s2);
   display(num2);
   cout<<endl<<endl;

   c = add(num1,num2);

   display_2(c);
   display(c);

   return 0;
}

  • 5
    点赞
  • 65
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

墨痕吖~

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

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

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

打赏作者

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

抵扣说明:

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

余额充值