Data structure - linked list addition (adding large numbers)

mission details

Large numbers are extremely long digits (such as a number of 1000 digits)


When adding large numbers, we can generally use the method of storing the numbers bit by bit and adding them bit by bit.

mission details

Task of this level: Give two non-empty linked lists to represent two non-negative integers. If we add these two numbers together, a new linked list will be returned representing their sum.

You can assume that except for the number 0, neither number will start with a 0.

Example:

Input: 10 1 2 3 4 5 6 7 8 9 9 2 6 5

Output: 1 2 3 4 5 6 7 9 6 4 Reason: 1234567899+ 65 = 1234567964

Input: 5 9 9 9 9 9 4 1 2 0 1

Output: 1 0 1 2 0 0 Reason: 99999 + 1201 = 101200

The number marked in red is the number of digits to be entered. For example, 520 is to be entered. 520 is a three-digit number, so the input case should be

3 5 2 0, where 3 represents the number of digits

Pay attention to the output of 1 space between each digit.


Start your mission and wish you success!

Idea:

       First, the two linked lists that need to be added are created using head interpolation, which allows us to start the operation from the low bits of the two data. (For example, 123+256, we should first calculate 3+6 = 9, then calculate 2+5 = 7, and finally calculate 1+2 = 3. The final result is 379)

        Then the two linked lists can be accessed at the same time, and then add the data fields to determine whether a carry is required (for example, 9+5 = 14, 14>10, a carry is required), store the low bit first (14%10 = 4), and then link to a new linked list that stores the result, then retains the carry value (14/10 = 1), and then sums the next bit. If no carry is required, just link directly to the end of the new linked list .

For example   

Enter 3 9 8 5 2 1 6

Linked list A:5->8->9

Linked list B:6->1

First sum = 5+6 = 11

Question: Is sum>=10?

     Yes: At this time, sum%10 = 1 is stored in the new linked list. The head of the new linked list->sum%10

        1. Update sum to get the carry value, sum = sum/10 = 11/10 = 1

        2. Then operate on the next bit at the same time, adding the carry value during the operation.

              sum += A->data + B->data = 1+8 + 1 = 10 (repeat the above operation)

    No: Store sum directly in the new linked list. The head of the new linked list->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;
}

Guess you like

Origin blog.csdn.net/qq_29992017/article/details/127024258