草庐IT

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

zhuzhucheng 2023-03-28 原文

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

时间限制: 1S类别: DS:线性表->线性表应用

题目描述:

 

 

 

 

 

 

 

 

输入范例:

-534564675768465476586798709880985345646757684654765867987098809853456467576846547658679870988098534564675768465476586798709880985345646757684654765867987098809853456467576846547658679870988098534564675768465476586798709880985345646757684654765867987098809853456467576846547658679870988098534564675768465476586798709880985345646757684654765867987098809853456467576846547658679870988098
435643754856985679435643754856985679435643754856985679435643754856985679435643754856985679435643754856985679435643754856985679435643754856985679435643754856985679435643754856985679435643754856985679435643754856985679435643754856985679435643754856985679


输出范例 :

-5345,6467,5768,4654,7658,6798,7098,8098,5345,6467,5768,4654,7658,6798,7098,8098,5345,6467,5768,4654,7658,6798,7098,8098,5345,6467,5768,4654,7658,6798,7098,8098,5345,6467,5768,4654,7658,6798,7098,8098,5345,6467,5768,4654,7658,6798,7098,8098,5345,6467,5768,4654,7658,6798,7098,8098,5345,6467,5768,4654,7658,6798,7098,8098,5345,6467,5768,4654,7658,6798,7098,8098,5345,6467,5768,4654,7658,6798,7098,8098,5345,6467,5768,4654,7658,6798,7098,8098,5345,6467,5768,4654,7658,6798,7098,8098
4356,4375,4856,9856,7943,5643,7548,5698,5679,4356,4375,4856,9856,7943,5643,7548,5698,5679,4356,4375,4856,9856,7943,5643,7548,5698,5679,4356,4375,4856,9856,7943,5643,7548,5698,5679,4356,4375,4856,9856,7943,5643,7548,5698,5679,4356,4375,4856,9856,7943,5643,7548,5698,5679,4356,4375,4856,9856,7943,5643,7548,5698,5679

-5345,6467,5768,4654,7658,6798,7098,8098,5345,6467,5768,4654,7658,6798,7098,8098,5345,6467,5768,4654,7658,6798,7098,8098,5345,6467,5768,4654,7658,6798,7098,8098,5345,2111,1392,9797,7801,8855,1455,0549,9647,0788,1412,0279,2801,6941,9155,2454,7797,0769,0089,0298,3283,1941,7242,0154,9701,8919,0069,8975,3302,2423,2241,8241,7402,0823,8219,8956,1979,2442,2723,3241,5488,8524,0124,7106,1960,1119,2742,3723,0488,6610,7824,9011,0110,1100,1419,3742,0970,1610,5911,6711,2014,9250,1400,2419

 

这里利用了几个关键函数:链表的逆置 比较两个链表的绝对值大小 链表的相加 输出链表

 

我的题解:

//DHUOJ 单链表ADT模板应用算法设计:长整数加法运算(使用单链表存储计算结果)
#include<iostream>
#include<cstring>using namespace std;
template<class ElemType>
struct Node
{
    ElemType data;
    Node<ElemType>* next;
    //构造函数1 用于node构造头结点
    Node(Node<ElemType>* ptr = NULL)
    {
        next = ptr;
    }
    //构造函数2 用于构造其他结点
    Node(const ElemType& item, Node<ElemType>* ptr = NULL)
    {
        next = ptr;
        data = item;
    }

public:
    ElemType getdata()
    {
        return data;
    }
    Node<ElemType>* getnext()
    {
        return next;
    }
    void set_next(Node<ElemType>* p)
    {
        this->next = p;
    }
    void set_date(ElemType num)
    {
        this->data = num;
    }
};
template<class ElemType>
class  LinkList {
private:
    Node<ElemType>* head;//头指针
    Node<ElemType>* tail;//尾指针

public:
    //无参构造函数
    LinkList()
    {
        head = new Node<ElemType>;
        head->next = NULL;
        tail = head->next;//头尾指针指向同一个内存
    }
    //有参构造
    LinkList(const ElemType& item)
    {
        head = new Node<ElemType>;
        tail = new Node<ElemType>;
        head->next = tail = new Node<ElemType>(item);//有参构造node
    }
    void display()
    {
        
       //避免出现以下情况 所以我们先判断是不是就一个单0
      if(head->getnext()->getdata()==0&&head->getnext()->getnext()==NULL)
         {
               cout<<"0";
                return ;
       }
         if (head->getdata() == -1)
            cout << "-";//如果是0就不能输出负号 
           //其实这样写也有问题 如果-0000 0005的就无法判断 所以我们上面解决了单0的情况
        Node<ElemType>* q = head->next;
        bool zeroflag = 0;
        bool firstflag = 0;
        //0要先特判 避免出现0 0000 0000的情况 也不行 会出现0 0000 0005 的情况无法输出
            while (q->next)
            {    
                if (q->getdata() == 0 && !zeroflag)
                {
                    q = q->next;
                    continue;
                }
                else if(q->getdata()!=0&&!zeroflag)
                {
                    zeroflag = 1;

                }
                if (!firstflag)
                {
                    cout << abs(q->data) << ",";
                    firstflag = 1;
                }
                else
                    printf("%04d,", abs(q->data));
                q = q->next;
            
            }
        if (q == head->next)//只有一位特判
            cout << abs(q->data);
        else
        {
            if (!firstflag)
            {
                cout << abs(q->data);

            }
            else
            {
                if (!zeroflag)
                {
                    cout << abs(q->data);

                }
                else
                {
                    printf("%04d", abs(q->data));
                }
                
            }
                
        }
            
        cout << endl;
    }
    int size()
    {
        if (head->next == NULL)
            return 0;
        int len = 0;
        Node<ElemType>* q;
        q = head->next;
        while (q)
        {
            len++;
            q = q->next;
        }
        return len;
    }
    void push_back(ElemType x)
    {
        Node<ElemType>* q = new Node<ElemType>;//新建结点
        q->data = x;
        q->next = NULL;
        if (size() == 0)
        {
            head->next = q;

        }
        else
        {
            tail->next = q;

        }
        tail = q;

    }
    Node<ElemType>* get_front(Node<ElemType>* p)
    {//获取一个指针的上一个,头指针和非法指针会报错.
        Node<ElemType>* q;
        q = head->next;
        while (q->next != NULL)
        {
            if (q->next == p)
                return q;
            q = q->next;
        }
    }
    Node<ElemType>* get_next(Node<ElemType>* p)
    {
        return p->next;
    }
    Node<ElemType>* get_address(int i)//获取指定下标的地址
    {
        Node<ElemType>* q;
        q = head->next;
        while (i--)
            q = q->next;
        return q;
    }
    ElemType at(int i)
    {
        Node<ElemType>* q = get_address(i);
        return q->data;
    }
    bool del_p(Node<ElemType>* p)//传入一个指针 删除
    {
        if (size() == 0)
            return false;
        if (tail->next == NULL)//如果只有一个元素
        {
            if (p == tail)//如果这个指针是那个唯一的指针
            {
                delete tail;
                tail = NULL;
                return true;
            }
            else
                return false;//如果不是

        }
        if (p == tail)//如果删除的是尾指针 
        {
            Node<ElemType>* q = get_front(p);
            q->next = NULL;
            tail = q;
            delete p;
            return true;
        }
        //其他的
        Node<ElemType>* q = get_front(p);
        q->next = p->next;
        delete p;
        return true;

    }
    bool del(int i)//删除指定位置的元素
    {
        return del_p(get_address(i));
    }
    Node<ElemType>* get_head()
    {
        return head;
    }
    Node<ElemType>* get_tail()
    {
        return tail;
    }
    void set_head(Node<ElemType>* p)
    {

        head = p;
    }
    void set_tail(Node<ElemType>* p)
    {
        tail = p;
    }
    void ListReverse()
    {
        Node<ElemType>* a, * b, * temp;
        a = head->getnext();
        ElemType datas = head->getdata();
        temp = NULL;
        b = NULL;
        bool flag = 0;//设置尾指针的标志
        while (a)
        {
            b = a;
            a = a->getnext();
            b->set_next(temp);
            if (!flag)
            {
                tail = b;
                flag = 1;
            }
            temp = b;
        }
        Node<ElemType>* newhead = new Node<ElemType>;
        newhead->set_next(b);
        newhead->set_date(datas);
        head = newhead;

    }
};


//从长整数的低位开始拆分(4位为一组,即不超过9999的非负整数),依次存放在单链表的每个结点的数据域中;
//头结点的数据域存放正负数标志(正数或0:1,负数:-1)。
template<class ElemType>
void Input_Int_Division(LinkList<ElemType>& L, string& str, int& length)
{
    Node<ElemType>* head = L.get_head();
    bool zhengfu_flag = 0;//记录正负的flag
    int l = str.length();
    if (str[0] == '-')//先特判正负数    
    {

        zhengfu_flag = 1;
        head->set_date(-1);

    }
    else
    {
        head->set_date(1);
    }
    int i = 0;
    if (zhengfu_flag)
        i = 1;
    int t0 = l % 4;
    if (t0 == 0)
        t0 = 4;
    int t = 0;//记录位数
    int num = 0;//存四位数
    bool changeflag = 0;//判断标志 判断是否有进行第一次
    for (; i < t0; ++i)
    {
        num = num * 10 + (str[i] - '0');
        changeflag = 1;
    }
    if (changeflag)
    {
        length++;//记录长度
        L.push_back(num);
        num = 0;
    }

    for (; i < str.length(); ++i)
    {

        num = num * 10 + (str[i] - '0');
        t++;
        if (t == 4)
        {
            length++;//记录长度
            L.push_back(num);
            t = 0;
            num = 0;
        }
    }
    //L.display();
}
//两个长整数的 绝对值 大小比较
//(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)
{
    Node<ElemType>* head1 = A.get_head();
    Node<ElemType>* head2 = B.get_head();

    //正数的情况 先看长度 
    if (len_A > len_B)
    {
        return 1;
    }
    else if (len_A < len_B)
    {
        return 2;
    }
    else if (len_A == len_B)
    {
        Node<ElemType>* a, * b;
        a = head1->getnext();
        b = head2->getnext();
        while (a)
        {
            if (a->getdata() > b->getdata())
                return 1;
            else if (a->getdata() < b->getdata())
                return 2;
            else
                a = a->getnext(), b = b->getnext();
        }
        return 0;
    }


}
template<class ElemType>
void swaps(LinkList<ElemType>& a, LinkList<ElemType>& b)
{
    LinkList<ElemType>temp = a;
    a = b;
    b = temp;
}
template<class ElemType>
void Listadds(LinkList<ElemType>& a, LinkList<ElemType>& b, int& la, int& lb)
{
    Node<ElemType>* x, * y;

    int ans = 0;
    if (la < lb)
    {
        //swap一下两个
        swaps(a, b);
        int temp = la;
        la = lb;
        lb = temp;
    }
    x = a.get_head()->getnext();
    y = b.get_head()->getnext();//两个指针的创建必须放在 交换判断之后
    int m = a.get_head()->getdata();//m n 存储符号
    int n = b.get_head()->getdata();//存储符号也必须放在交换判断之后

    //第一步 判断结果的最高位//!必须再加法前进行 !!因为a会随着加法而改变 引用传递
    bool flag = 0;//标记元素
    int comp = Two_LongNum_Compare(a, b, la, lb);


    while (y)//先把每一位结点的数值加起来
    {
        ans = x->getdata() * m + y->getdata() * n;
        x->set_date(ans);
        x = x->getnext();
        y = y->getnext();
    }
    //把长的位都化成同号的 不然接下来进位会出问题
    while (x)
    {
        x->set_date(x->getdata() * m);
        x = x->getnext();
    }
    //再做进位处理
    
    if (comp == 1)
    {
        flag = 1;
    }
    //第二步 开始逐位遍历
    x = a.get_head()->getnext();
    int zheng_fu = 0;//判断正负的符号
    if (flag)
        zheng_fu = a.get_head()->getdata();
    else
        zheng_fu = b.get_head()->getdata();
    if (zheng_fu > 0)//分正负两种情况 先看是正的    
    {
        a.get_head()->set_date(1);//定最高位符号
        while (x->getnext())//最后一个结点先不遍历 最后单独讨论
        {
            if (x->getdata() > 9999)
            {
                x->set_date(x->getdata() - 10000);
                x->getnext()->set_date(x->getnext()->getdata() + 1);
                //下一位就加一
            }
            else if (x->getdata() < 0)
            {
                x->set_date(x->getdata() + 10000);
                x->getnext()->set_date(x->getnext()->getdata() - 1);
            }
            x = x->getnext();
        }
        //讨论最后一位 是否要进位
        if (x->getdata() > 9999)
        {
            x->set_date(x->getdata() - 10000);
            a.push_back(1);
        }
    }
    else //讨论负数的情况
    {
        a.get_head()->set_date(-1);//定最高位符号
        while (x->getnext())//最后一个结点先不遍历 最后单独讨论
        {
            if (x->getdata() < -9999)
            {
                x->set_date(x->getdata() + 10000);
                x->getnext()->set_date(x->getnext()->getdata() - 1);
                //下一位就加一
            }
            else if (x->getdata() > 0)
            {
                x->set_date(x->getdata() - 10000);
                x->getnext()->set_date(x->getnext()->getdata() + 1);
            }
            x = x->getnext();
        }
        //讨论最后一位 是否要进位
        if (x->getdata() < -9999)
        {
            x->set_date(x->getdata() + 10000);
            a.push_back(1);
        }
    }
}

int main()
{
    LinkList<int>head1, head2;
    string str1, str2;
    getline(cin, str1);
    getline(cin, str2);
    int la = str1.length();
    int lb = str2.length();
    if (str1[0] == '-')
        la -= 1;
    if (str2[0] == '-')
        lb -= 1;
    int length1 = 0;
    int length2 = 0;
    Input_Int_Division(head1, str1, length1);
    Input_Int_Division(head2, str2, length2);
    head1.display();
    head2.display();
    cout << endl;
    head1.ListReverse();
    head2.ListReverse();
    Listadds(head1, head2, la, lb);
    head1.ListReverse();
    head1.display();
    //swaps(head1, head2);
    //head1.display();
    //head2.display();
    //cout << endl;
    //int comp = Two_LongNum_Compare(head1, head2, length1, length2);
    //cout << comp;
    //cout << length<<endl;
    //head.ListReverse();
    //head.display();

    return 0;

}

 

有关数据结构:DHUOJ 单链表ADT模板应用算法设计:长整数加法运算(使用单链表存储计算结果)的更多相关文章

  1. ruby - 解析 RDFa、微数据等的最佳方式是什么,使用统一的模式/词汇(例如 schema.org)存储和显示信息 - 2

    我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i

  2. ruby-on-rails - 使用一系列等级计算字母等级 - 2

    这里是Ruby新手。完成一些练习后碰壁了。练习:计算一系列成绩的字母等级创建一个方法get_grade来接受测试分数数组。数组中的每个分数应介于0和100之间,其中100是最大分数。计算平均分并将字母等级作为字符串返回,即“A”、“B”、“C”、“D”、“E”或“F”。我一直返回错误:avg.rb:1:syntaxerror,unexpectedtLBRACK,expecting')'defget_grade([100,90,80])^avg.rb:1:syntaxerror,unexpected')',expecting$end这是我目前所拥有的。我想坚持使用下面的方法或.join,

  3. ruby - 触发器 ruby​​ 中 3 点范围运算符和 2 点范围运算符的区别 - 2

    请帮助我理解范围运算符...和..之间的区别,作为Ruby中使用的“触发器”。这是PragmaticProgrammersguidetoRuby中的一个示例:a=(11..20).collect{|i|(i%4==0)..(i%3==0)?i:nil}返回:[nil,12,nil,nil,nil,16,17,18,nil,20]还有:a=(11..20).collect{|i|(i%4==0)...(i%3==0)?i:nil}返回:[nil,12,13,14,15,16,17,18,nil,20] 最佳答案 触发器(又名f/f)是

  4. ruby - Ruby 有 `Pair` 数据类型吗? - 2

    有时我需要处理键/值数据。我不喜欢使用数组,因为它们在大小上没有限制(很容易不小心添加超过2个项目,而且您最终需要稍后验证大小)。此外,0和1的索引变成了魔数(MagicNumber),并且在传达含义方面做得很差(“当我说0时,我的意思是head...”)。散列也不合适,因为可能会不小心添加额外的条目。我写了下面的类来解决这个问题:classPairattr_accessor:head,:taildefinitialize(h,t)@head,@tail=h,tendend它工作得很好并且解决了问题,但我很想知道:Ruby标准库是否已经带有这样一个类? 最佳

  5. ruby - 我如何添加二进制数据来遏制 POST - 2

    我正在尝试使用Curbgem执行以下POST以解析云curl-XPOST\-H"X-Parse-Application-Id:PARSE_APP_ID"\-H"X-Parse-REST-API-Key:PARSE_API_KEY"\-H"Content-Type:image/jpeg"\--data-binary'@myPicture.jpg'\https://api.parse.com/1/files/pic.jpg用这个:curl=Curl::Easy.new("https://api.parse.com/1/files/lion.jpg")curl.multipart_form_

  6. 世界前沿3D开发引擎HOOPS全面讲解——集3D数据读取、3D图形渲染、3D数据发布于一体的全新3D应用开发工具 - 2

    无论您是想搭建桌面端、WEB端或者移动端APP应用,HOOPSPlatform组件都可以为您提供弹性的3D集成架构,同时,由工业领域3D技术专家组成的HOOPS技术团队也能为您提供技术支持服务。如果您的客户期望有一种在多个平台(桌面/WEB/APP,而且某些客户端是“瘦”客户端)快速、方便地将数据接入到3D应用系统的解决方案,并且当访问数据时,在各个平台上的性能和用户体验保持一致,HOOPSPlatform将帮助您完成。利用HOOPSPlatform,您可以开发在任何环境下的3D基础应用架构。HOOPSPlatform可以帮您打造3D创新型产品,HOOPSSDK包含的技术有:快速且准确的CAD

  7. FOHEART H1数据手套驱动Optitrack光学动捕双手运动(Unity3D) - 2

    本教程将在Unity3D中混合Optitrack与数据手套的数据流,在人体运动的基础上,添加双手手指部分的运动。双手手背的角度仍由Optitrack提供,数据手套提供双手手指的角度。 01  客户端软件分别安装MotiveBody与MotionVenus并校准人体与数据手套。MotiveBodyMotionVenus数据手套使用、校准流程参照:https://gitee.com/foheart_1/foheart-h1-data-summary.git02  数据转发打开MotiveBody软件的Streaming,开始向Unity3D广播数据;MotionVenus中设置->选项选择Unit

  8. 使用canal同步MySQL数据到ES - 2

    文章目录一、概述简介原理模块二、配置Mysql使用版本环境要求1.操作系统2.mysql要求三、配置canal-server离线下载在线下载上传解压修改配置单机配置集群配置分库分表配置1.修改全局配置2.实例配置垂直分库水平分库3.修改group-instance.xml4.启动监听四、配置canal-adapter1修改启动配置2配置映射文件3启动ES数据同步查询所有订阅同步数据同步开关启动4.验证五、配置canal-admin一、概述简介canal是Alibaba旗下的一款开源项目,Java开发。基于数据库增量日志解析,提供增量数据订阅&消费。Git地址:https://github.co

  9. ruby-on-rails - 创建 ruby​​ 数据库时惰性符号绑定(bind)失败 - 2

    我正在尝试在Rails上安装ruby​​,到目前为止一切都已安装,但是当我尝试使用rakedb:create创建数据库时,我收到一个奇怪的错误:dyld:lazysymbolbindingfailed:Symbolnotfound:_mysql_get_client_infoReferencedfrom:/Library/Ruby/Gems/1.8/gems/mysql2-0.3.11/lib/mysql2/mysql2.bundleExpectedin:flatnamespacedyld:Symbolnotfound:_mysql_get_client_infoReferencedf

  10. STM32读取串口传感器数据(颗粒物传感器,主动上传) - 2

    文章目录1.开发板选择*用到的资源2.串口通信(个人理解)3.代码分析(注释比较详细)1.主函数2.串口1配置3.串口2配置以及中断函数4.注意问题5.源码链接1.开发板选择我用的是STM32F103RCT6的板子,不过代码大概在F103系列的板子上都可以运行,我试过在野火103的霸道板上也可以,主要看一下串口对应的引脚一不一样就行了,不一样的就更改一下。*用到的资源keil5软件这里用到了两个串口资源,采集数据一个,串口通信一个,板子对应引脚如下:串口1,TX:PA9,RX:PA10串口2,TX:PA2,RX:PA32.串口通信(个人理解)我就从串口采集传感器数据这个过程说一下我自己的理解,

随机推荐