数据结构——链表相加(大数相加)

任务描述

大数就是超长位数(例如1000位的一个数字)


在进行大数相加时,我们一般可以采用将数按位存储并按位相加的方法。

任务描述

本关任务:给出两个非空的链表用来表示两个非负的整数。 我们将这两个数相加起来,则会返回一个新的链表来表示它们的和。

您可以假设除了数字 0 之外,这两个数都不会以 0 开头。

示例:

输入:10 1 2 3 4 5 6 7 8 9 9 2 6 5

输出:1 2 3 4 5 6 7 9 6 4      原因:1234567899+ 65 = 1234567964

输入: 5 9 9 9 9 9 4 1 2 0 1

输出:1 0 1 2 0 0                  原因:99999 + 1201 = 101200

其中标红数字为要输入的数据的位数,例如要输入520,520是三位数字,所以输入案例应该是

3 5 2 0,其中的3表示位数

注意输出各位数之间1个空格


开始你的任务吧,祝你成功!

思路:

       首先两个需要相加的链表都是用头插法进行创建,这样可以使我们可以从两个数据的低位开始运算。(例如123+256,我们应该是先运算3+6 = 9,在运算2+5 = 7,最后运算1+2 = 3,最后结果就是379)

        然后两个链表可以两个同时访问,然后对数据域相加,判断是否需要进位(例如9+5 = 14,14>10,需要进位),先储存低位(14%10 = 4),然后 链接到 储存结果的新链表中,然后保留下进位值(14/10 = 1),再对下一位求和。如果不需要进位,则直接链接到新链表尾部即可

例如   

输入 3 9 8 5 2 1 6

链表A:5->8->9

链表B:6->1

首先sum = 5+6 = 11

问:sum是否>=10?

     是:此时把sum%10 = 1 储存到新链表中      新链表的头->sum%10

        1、对sum进行更新,得到进位值,sum = sum/10 = 11/10 = 1

        2、然后再同时对下一位运算,运算时要加上进位值

              sum += A->data + B->data = 1+8 + 1 = 10(再重复上边的操作即可)

    否:直接把sum储存到新链表                       新链表的头->sum

linklist.h

//
// Created by A梦同学 on 2022/9/24.
//
#ifndef MY_C_CODE_LINKLIST_H
#define MY_C_CODE_LINKLIST_H
#include <stdio.h>
#include <stdlib.h>
struct node
{//链表结点类型,包含一个存放整型数据的 data 成员,和一个指向下一个结点的next成员
    int data ;
    struct node *next ;
};

//创建空链表(带头指针的!)
struct node *mycreateList()
{//函数功能:创建一个只有一个头结点的空链表,头节点的数据域赋值为0,并将表头结点的地址返回
    struct node *head = (struct node *)malloc(sizeof(struct node));
    head->data = 0;
    head->next = NULL;
    return head;
}

//头插法
void myinsertHead(struct node * head, int insData )
{
    /*函数功能:实现在head为表头的链表中使用头插法,插入数据元素insData*/
    struct node *p ;
    p = (struct node *)malloc(sizeof(struct node));
    p->data = insData;
    p->next = head->next ;
    head->next = p ;
}


//打印链表
void myprintList(struct node *L)
{
    /*输出head为表头的链表中的数据元素,每输出一个数据空一格*/
    struct node *p = L->next ;
    while(p)
    {
        printf("%d ",p->data);
        p = p->next ;
    }
}

//得到储存大数的链表
void genNumber( struct node *A , int num)
{//本函数用于接收输入的大数的各个位,返回大数链表表头,可使用上面已实现的链表插入函数
/*------begin---------*/
A->data = num;
int i,data;
for(i = 1;i<=num;i++){
    scanf("%d",&data);
    myinsertHead(A,data);
}
/*------end---------*/
}

//实现两链表数据域相加
struct node *addNumber(struct node *A ,struct node *B)
{
    //此处实现函数求两数相加,并返回和值链表的表头;
    /*------begin---------*/
    //创建新链表来储存相加后的和
    struct node* newhead = mycreateList();

    //sum用来表示各个位数相加之后和,例如个位数相加之后
    int sum = 0;

    //跳过头指针,直接得到头结点
    A = A->next;
    B = B->next;

    //其中一个链表不为空就一直进行,因为我们要实现的是 链表相加
    while(A!=NULL||B!=NULL){

        //当两条链表都不为空(因为有两个链表数据域相加,只有两者都不为空才可以)
        if(A!=NULL&&B!=NULL){
            //位数相加
            sum += A->data+B->data;

            //如果得数大于等于10,就需要进位。
            if(sum>=10){
                //低位储存到新链表中(头插法),例如9+5 = 14,则把4先储存,其中的1还得进一步看高位是否溢出
                myinsertHead(newhead,sum%10);
                sum = sum/10;
            }

            //如果得数没有溢出
            else{
                //直接将和储存到新链表中即可
                myinsertHead(newhead,sum);
                sum = 0; //同时对溢出标志置零
            }

            //两链表向后移动一格(下一位数据)
            A = A->next;
            B = B->next;
        }
        //如果其中一条为空
        else{
            //先判断是A还是B为空,如果是A为空,则一直移动B就可以了
            if(A==NULL){
                //判断最后一次数据的相加和是否溢出
                sum += B->data;
                if(sum>=10){
                    myinsertHead(newhead,sum%10);
                    sum = sum/10;
                }
                else{//一般都是直接将B中数据域复制粘贴然后直接插入新链表(因为A为空,相加和就是B)
                    myinsertHead(newhead,sum);
                    sum = 0;
                }
                //移动B
                B->next;
            }
            else{//如果是B为空,一直移动A操作即可
                sum += A->data;
                if(sum>=10){
                    myinsertHead(newhead,sum%10);
                    sum = sum/10;
                }
                else{
                    myinsertHead(newhead,sum);
                    sum = 0;
                }
                A = A->next;
            }
        }
    }
   return newhead;
    /*------end---------*/
}
#endif //MY_C_CODE_LINKLIST_H

main.c 

#include "linklist.h"
int main(void)
{
    struct node *A ,*B ,*C ;
    int i,j;

   //创建两个空链表
    A = mycreateList();
    B = mycreateList();
 
    //输入位数,然后输入得到大数A
    scanf("%d",&i);
    genNumber(A,i);
 
    //输入位数,然后输入得到大数B
    scanf("%d",&j);
    genNumber(B,j) ;

    //大数A和大数B进行运算,储存在C中
    C = addNumber(A,B);
    myprintList(C);
    return 1;
}

猜你喜欢

转载自blog.csdn.net/qq_29992017/article/details/127024258