有链表实现长整数的加法

来源:互联网 发布:淘宝导入视频 编辑:程序博客网 时间:2024/05/18 12:01
课程题目:
          设计一个程序实现两个任意长的整数求和运算。


要求:
          利用双向循环链表实现长整数的存储,每个节点含有一个整型变量。 输入形式按照中国对于长整数的表示习惯,没四位一组,组间用逗号隔开。

思路:
         为了达到上面的要求,我使用链表将长整数按照四位一组进行输入(每组用一个int表示就可以了)。然后对链表中的数字进行加法运算。
        加法运算中心思想:先比较长度,以确定哪个数减去哪个数。组与组之间采用万进制,并且设立进位数,借位数,从而实现以上要求。

代码如下:
#include <stdio.h>
#include <malloc.h>
#include <stdlib.h>
#include <math.h>
typedef int DataType;
//------------------
/*定义节点*/
typedef struct Node
{
 int data;
 struct Node* prior;
 struct Node* next;
}DSLNode;
//------------------
/*循环双向链表的初始化*/
void ListInisiate(DSLNode **head)
{
 if((*head=(DSLNode *)malloc(sizeof(DSLNode)))==NULL)exit(0);
 (*head)->prior=*head;
 (*head)->next=*head;
 //return 1;
}
//------------------
/*插入运算*/
int ListInsert(DSLNode *head,int i,DataType x)
{
 DSLNode *p,*s;
 int j;
 p=head->next;
 j=0;
 while(p!=head&&j<i)
 {
  p=p->next;
  j++;
 }
 if(j!=i)
 {
  printf("插入位置参数不合法/n");
  return 0;
 }
 if((s=(DSLNode *)malloc(sizeof(DSLNode)))==NULL)exit(0);
 s->data=x;
 s->prior=p->prior;
 p->prior->next=s;
 s->next=p;
 p->prior=s;
 return 1;
}
//--------------------------
/*求当前循环双向链表的长度*/
int ListLength(DSLNode *head)
{
 DSLNode *p=head;
 int length=0;
 while(p->next!=head)
 {
  length++;
  p=p->next;
 }
 return length;
}
//-------------------
/*读取输入的数字*/
int InputNumber(DSLNode *head)
{
 int input,i=0;
 char c;
 //读入数据时负数用0表示符号,正数用1表示符号
 scanf("%d%c",&input,&c);
 while(1)
 { 
  if(input<0&&i==0)
  {
   head->data=0;
   input=fabs(input);
   ListInsert(head,i,input);
  }
  else if(input>=0&&i==0)
  {
   head->data=1;
   ListInsert(head,i,input);
  }
  else ListInsert(head,i,input);
  i++;
  if(c==';')break;
  scanf("%d%c",&input,&c);
 }
 return 1;
}
//-------------------
/*从表尾输出数据元素*/
void OutPutNumber(DSLNode *head,int sign)
{
 DSLNode *head_3=head->prior;
 //下面的if else是为了判断输出的正负号
 if(sign==1)
  printf("The result is:");
 else
  printf("The result is:-");
 printf("%d",head_3->data);
 head_3=head_3->prior;
 while(head_3!=head)
 {
  if(head_3->data<10)
  {
   printf(",000");
   printf("%d",head_3->data);
  }
  else if(head_3->data<100)
  {
   printf(",00");
   printf("%d",head_3->data);
  }
  else if(head_3->data<1000)
  {
   printf(",0");
   printf("%d",head_3->data);
  }
  else
   printf(",%d",head_3->data);
  head_3=head_3->prior;
 }
 printf("/n/n");
}
//------------------
/*长整数的加运算*/
int LongIntAdd(DSLNode *head1,DSLNode *head2,DSLNode *head3)
{
 int data,i=0,length1,length2,mark,carry=0,brrow=0;//mark用于标记在异号情况下哪个一个更长些,carry用于标记进位
 DSLNode *p=head1->next,*q=head2->next,*head_3=head3->prior,*notsame;
 if(head1->data!=head2->data)//异号的运算
 {
  i=0;
  length1=ListLength(head1);
  length2=ListLength(head2);
  if(length1==length2)
  {//p和q节点个数相同的情况
   while(p!=head1)
   {//找出p和q中第一个节点数据不相同的节点
    if(p->data>q->data)
    {//p的值大于q的值
     mark=1;
     notsame=p->prior;
     break;
    }
    else if(p->data<q->data)
    {//q的值大于的p值
     mark=2;
     notsame=q->prior;
     break;
    }
    else{//q->data等于p->data,指针继续往下移
     p=p->next;
     q=q->next;
    }
   }
   if(p==head1)//一直到了表尾还是相同,则说明这两个数相同
   {
    printf("The result is:0/n");
    return 0;
   }
   else if(mark==1)
   {//p的值大于q的值
    while(q->next!=head2)
     q=q->next;//将链表的当前指针指到表尾
    while(p->next!=head1)
     p=p->next;//将链表的当前指针指到表尾
    while(p!=notsame)
    {//将p和q相应节点上的数相减
     data=p->data-q->data+brrow;
     brrow=0;
     if(data<0)
     {
      data+=10000;
      brrow=-1;
     }
     ListInsert(head3,i,data);
     i++;
     p=p->prior;
     q=q->prior;
    }
    OutPutNumber(head3,head1->data);
   }
   else if(mark==2)
   {//q的值大于p的值
    while(q->next!=head2)
     q=q->next;//将链表的当前指针指到表尾
    while(p->next!=head1)
     p=p->next;//将链表的当前指针指到表尾
    while(q!=notsame)
    {//将p和q相应节点上的数相减
     data=q->data-p->data+brrow;
     brrow=0;
     if(data<0)
     {
      data+=10000;
      brrow=-1;
     }
     ListInsert(head3,i,data);
     i++;
     q=q->prior;
     p=p->prior;
    }
    OutPutNumber(head3,head2->data);
   }
  }
  else if(length1>length2)
  {//p的值比q的值大
   while(q->next!=head2)
    q=q->next;//将链表的当前指针指到表尾
   while(p->next!=head1)
    p=p->next;//将链表的当前指针指到表尾
   while(q!=head2)
    {//将p和q相应节点上的数相减
     data=p->data-q->data+brrow;
     brrow=0;
     if(data<0)
     {
      data+=10000;
      brrow=-1;
     }
     ListInsert(head3,i,data);
     i++;
     p=p->prior;
     q=q->prior;
    }
   while(p!=head1)
   {
    data=p->data+brrow;
    brrow=0;
    if(data<0)
    {
     data+=10000;
     brrow=-1;
    }
    if(p==head1->next)
    {
     if(data!=0)
      ListInsert(head3,i,data);
    }
    else
     ListInsert(head3,i,data);
    p=p->prior;
    i++;
   }
   OutPutNumber(head3,head1->data);
  }
  else if(length1<length2)
  {//q的值比p的值大
   while(q->next!=head2)
    q=q->next;//将链表的当前指针指到表尾
   while(p->next!=head1)
    p=p->next;//将链表的当前指针指到表尾
   while(p!=head1)
    {//将p和q相应节点上的数相减
     data=q->data-p->data+brrow;
     brrow=0;
     if(data<0)
     {
      data+=10000;
      brrow=-1;
     }
     ListInsert(head3,i,data);
     i++;
     p=p->prior;
     q=q->prior;
    }
   while(q!=head2)
   {
    data=q->data+brrow;
    brrow=0;
    if(data<0)
    {
     data+=10000;
     brrow=-1;
    }
    if(q==head2->next)
    {
     if(data!=0)
      ListInsert(head3,i,data);
    }
    else
     ListInsert(head3,i,data);
    q=q->prior;
    i++;
   }
   OutPutNumber(head3,head2->data);
  }
 }
 else //同号的情况
 {
  while(q->next!=head2)
   q=q->next;//将链表的当前指针指到表尾
  while(p->next!=head1)
   p=p->next;//将链表的当前指针指到表尾
  while(p!=head1&&q!=head2)
  {
   data=p->data+q->data+carry;
   carry=0;//用完进位后要及时清零
   if(data>9999)
   {
    carry=data/10000;
    data%=10000;
   }
   ListInsert(head3,i,data);
   i++;
   p=p->prior;
   q=q->prior;
  }
  if(p==head1&&q==head2)//等长的情况
  {
   if(carry!=0)//有进位
   {
    ListInsert(head3,i,carry);
    carry=0;
    i++;
   }
   OutPutNumber(head3,head2->data);
  }
  else if(p==head1) //q的长度大于p的长度
  {
   if(carry!=0)//有进位
   {
    while(q!=head2)
    {
     data=q->data+carry;
     carry=0;//用完进位后要及时清零
     if(data>9999)
     {
      carry=data/10000;
      data%=10000;
     }
     ListInsert(head3,i,data);
     i++;
     q=q->prior;
    }
    if(carry!=0)//有进位
    {
     ListInsert(head3,i,carry);
     carry=0;
     i++;
    }
    OutPutNumber(head3,head2->data);
   }
   else//无进位
   {
    while(q!=head2)
    {
     ListInsert(head3,i,q->data);
     i++;
     q=q->prior;
    }
    OutPutNumber(head3,head2->data);
   }
  }
  else//p的长度大于q的长度
  {
   if(carry!=0)//有进位
   {
    while(p!=head1)
    {
     data=p->data+carry;
     carry=0;
     if(data>9999)
     {
      carry=data/10000;
      data%=10000;
     }
     ListInsert(head3,i,data);
     i++;
     p=p->prior;
    }
    if(carry!=0)//有进位
    {
     ListInsert(head3,i,carry);
     carry=0;
     i++;
    }
    OutPutNumber(head3,head2->data);
   }
   else//没有进位
   {
    while(p!=head1)
    {
     ListInsert(head3,i,p->data);
     i++;
     p=p->prior;
    }
    OutPutNumber(head3,head1->data);
   }
  }
 }
 return 1;
}

int main()
{
 int i=0;
 DSLNode *head1,*head2,*head3;
 for(i=0;i<10;i++)
 {
  ListInisiate(&head1);
  ListInisiate(&head2);
  ListInisiate(&head3);
  printf("Please input the numbers:/n");
  InputNumber(head1);
  InputNumber(head2);
  LongIntAdd(head1,head2,head3);
 }
}