分析
题目考查对链表数据结构的理解,和对加法的操作的理解
链表经常要遍历,所以遍历的框架很重要,接着就是加法的进位了,关键在与进位信号要与每一位相加,若最高位进位信号为1,则新的最高位为1;
实现
#include <stdio.h>
#include <stdlib.h>
struct ListNode
{
int val;
struct ListNode *next;
};
struct ListNode* addTwoNumbers(struct ListNode* l1, struct ListNode* l2) {
struct ListNode *Ans,*p,*q,*tmp;
int c=0;
Ans=NULL;//初始化
p=l1;//用来遍历
q=l2;//同上
while(1)
{
if(p==NULL)//用p存储较长链表的多余部分
{
p=q;
break;
}
if(q==NULL)//还是p
{
break;
}
tmp=(struct ListNode*)malloc(sizeof(struct ListNode));//可以相加,申请一位
tmp->val=(p->val+q->val+c)%10;//进位信号放里面才合理,例如p->val=4,q->val5,c=1;
tmp->next=Ans;
Ans=tmp;
c=(p->val+q->val+c)/10;//道理同上
p=p->next;
q=q->next;
}
while(p!=NULL)//较长链表的剩余部分
{
tmp=(struct ListNode*)malloc(sizeof(struct ListNode));
tmp->val=(p->val+c)%10;
tmp->next=Ans;
Ans=tmp;
c=(p->val+c)/10;//其实c在这一过程加一遍就够了,可以改进;
p=p->next;
}
if(c!=0)//最高位是否进位1
{
tmp=(struct ListNode*)malloc(sizeof(struct ListNode));
tmp->val=1;
tmp->next=Ans;
Ans=tmp;
c=0;//这句没什么用;
}
p=Ans;//因为结果为头插法,所以就地逆置链表各元素以满足题意
Ans=NULL;
while(p!=NULL)
{
q=p->next;
p->next=Ans;
Ans=p;
p=q;
}
return Ans;
}
void show(struct ListNode* A)//输出链表A
{
struct ListNode* p=A;
while(p!=NULL)
{
printf("%d\t",p->val);
p=p->next;
}
printf("\n");
}
struct ListNode* getone(int k)//造一个位数为n的链表,可能有bug,按常理出牌应该没问题;
{
struct ListNode* A=NULL;
struct ListNode* tmp=NULL;
int n;
while(k--)
{
scanf("%d",&n);
tmp=(struct ListNode*)malloc(sizeof(struct ListNode));
tmp->val=n;
tmp->next=A;
A=tmp;
}
return A;
};
int main()//测试
{
struct ListNode *l1,*l2;
l1=getone(1);
//show(l1);
l2=getone(1);
//show(l2);
l1=addTwoNumbers(l1,l2);
show(l1);
return 0;
}
学习与思考
- 链表的就地逆置;
- 链表的遍历;
- 链表元素的增删查改;
- 参考答案中的拓展问:如果链表正序存数字呢?(3→4→2)+(4→6→5)=8→0→7 加数逆置就转换为本题了,结果就是头插的结果;
- 代码中还有许多可以改进的地方,希望有想法的朋友留言交流。