任务描述
大数就是超长位数(例如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;
}