用双向链表实现超长整数加减法

学校数据结构的课程实验之一。

用到的数据结构:双向链表

主要功能:对由用户输入的两个任意长的整数进行加减运算

主函数:

 1 int main()
 2 {
 3
 4     short num;//临时数据段
 5     char optr;//运算符
 6     char ch;//临时字符接收
 7     char choice = ‘y‘;
 8
 9     while (choice == ‘y‘)
10     {
11         List<List_entry> *list1 = new List<List_entry>();
12         List<List_entry> *list2 = new List<List_entry>();
13         cout << "请输入第一个运算数,每三位用逗号分隔,以#结束:" << endl;
14         cin >> ch;
15         if (ch == ‘-‘) list1->sign = 1;
16         else cin.putback(ch);
17         while (ch != ‘#‘)
18         {
19             cin >> num;//读入一段(3位)整数
20             list1->insert_tail(num);//构建第一个运算数的链表
21             cin >> ch;//吸收用于分隔的逗号
22         }
23
24         cout << "第一个运算数已保存,请输入第二个运算数:" << endl;
25         cin >> ch;
26         if (ch == ‘-‘) list2->sign = 1;
27         else cin.putback(ch);
28         while (ch != ‘#‘)
29         {
30             cin >> num;
31             list2->insert_tail(num);
32             cin >> ch;
33         }
34
35         cout << "第二个运算数已保存,请输入运算符(+或-):" << endl;
36         cin >> optr;
37
38         cout << "运算表达式为:" << endl;
39          list1->print();cout << endl;
40         cout << optr;
41         list2->print();
42         cout << endl;
43
44         List<List_entry>* result = operate(list1, list2, optr);
45         cout << "运算结果为:" << endl;
46         result->print();
47         cout << endl;
48         delete result, list1, list2;
49         cout << "是否继续?[y/n]";
50         cin >> choice;
51     }
52
53 }

链表结点定义

 1 template<class Node_entry>//结点定义
 2 struct Node
 3 {
 4     //数据成员
 5     Node_entry entry;
 6     Node<Node_entry> *back;
 7     Node<Node_entry> *next;
 8
 9     //构造函数
10     Node(){}
11     Node(Node_entry new_entry,
12         Node<Node_entry> *new_back=NULL, Node<Node_entry> *new_next=NULL)
13     :entry(new_entry), back(new_back), next(new_next){}
14 };

双链表的定义

 1 template<class List_entry>
 2 class List
 3 {
 4 public:
 5     unsigned int count;//结点个数
 6     Node<List_entry> *head, *tail;//链表头、尾结点
 7     short sign;//符号
 8
 9     List()//构造函数
10     {
11         count=0;
12         head=tail=NULL;
13         sign=0;
14     }
15     Error_code insert_tail(const List_entry x)//插在末尾
16     {
17         Node<List_entry> *new_node=new Node<List_entry>(x);
18         if(head==NULL) head=tail=new_node;//第一个结点
19         else
20         {
21             tail->next = new_node;
22             new_node->back = tail;
23             tail = new_node;
24         }
25         count++;
26         return success;
27     }
28     Error_code insert_head(const List_entry x)//插在开头
29     {
30         Node<List_entry> *new_node=new Node<List_entry>(x);
31         if (head == NULL) head = tail = new_node;//第一个结点
32         else
33         {
34             head->back=new_node;
35             new_node->next=head;
36             head=new_node;
37         }
38         count++;
39         return success;
40     }
41     Error_code delete_head()
42     {
43         Node<List_entry> *out = head;
44         head = head->next;
45         delete out;
46         count--;
47         return success;
48     }
49     Error_code print()
50     {
51         if(sign==1) cout<<‘-‘;//打印负号
52         if(count==0) return fail;
53         if (count==1 && head->entry == 0)//头结点为0且只有这一个结点,直接输出
54         {
55             cout << head->entry;
56             return success;
57         }
58
59         while (head->entry == 0)//头结点为0,删除,直至遇到第一个不为0的头结点为止
60         {
61             delete_head();
62         }
63         Node<List_entry> *current=head;
64         if (count == 1)//只有一个结点,正常打印
65         {
66             cout << head->entry;
67             return success;
68         }
69         cout << current->entry << ‘,‘;//打印第一个结点,不做补位处理
70         current = current->next;
71         while(current != NULL && current != tail)
72         {
73             if (current->entry / 10 == 0) cout << "00";//结点为一位数时补齐三位
74             else if (current->entry / 100 == 0) cout << ‘0‘;//结点为两位数时补齐三位
75             cout<<current->entry<<‘,‘;
76             current=current->next;
77         }
78         //最后一段结尾没有逗号,所以单独处理
79         if (current->entry / 10 == 0) cout << "00";//结点为一位数时补齐三位
80         else if (current->entry / 100 == 0) cout << ‘0‘;//结点为两位数时补齐三位
81         cout<<current->entry;
82         return success;
83     }
84 };

List.h

用于比较链表值的大小的函数

 1 template<class List_entry>//比较链表的绝对值
 2 Compare_result compare(List<List_entry> *l1, List<List_entry> *l2)
 3 {
 4     if (l1->count > l2->count) return Greater;//结点数多,一定大
 5     else if (l1->count < l2->count) return Less;//结点数少,一定小
 6     else//结点数一致,从头结点开始比
 7     {
 8         Node<List_entry> *temp1, *temp2;
 9         temp1 = l1->head;
10         temp2 = l2->head;
11         for (unsigned int i = 0; i < l1->count; i++)
12         {
13             if (temp1->entry > temp2->entry) return Greater;
14             else if (temp1->entry < temp2->entry) return Less;
15             temp1 = temp1->next;
16             temp2 = temp2->next;
17         }
18         return Equal;
19     }
20 }

进行加减运算的函数流程图:

链表的成员函数----运算函数

 1 template<class List_entry>//运算
 2 List<List_entry>* operate(List<List_entry> *list1, List<List_entry> *list2, char optr)
 3 {
 4     List<List_entry> *result = new List<List_entry>();
 5     if (optr == ‘+‘)//输入了加法
 6     {
 7         if (list1->sign == 0 && list2->sign == 0)//a+b,两个正数相加
 8             result = Plus(list1, list2);
 9         else if (list1->sign == 0 && list2->sign == 1)//a+(-b)
10         {
11             if (compare(list1, list2) == Greater)//|a|>|b|时,将a+(-b)转为a-b
12                 result = Minus(list1, list2);//a-b
13             else if (compare(list1,list2)==Less)//|a|<|b|时,转为-(b-a)
14             {
15                 result = Minus(list2, list1);
16                 result->sign = 1;//-(b-a)
17             }
18             else if (compare(list1, list2) == Equal) result->insert_head(0);//相等,差直接等于0
19         }
20         else if (list1->sign == 1 && list2->sign == 0)//(-a)+b
21         {
22             if (compare(list2, list1) == Greater)//|b|>|a|时,转为b-a
23                 result = Minus(list2, list1);//b-a
24             else if (compare(list2,list1)==Less) //|b|<|a|时,转为-(a-b)
25             {
26                 result = Minus(list1, list2);//-(a-b)
27                 result->sign = 1;
28             }
29             else if (compare(list2, list1) == Equal) result->insert_head(0);//相等,差直接等于0
30         }
31         else //(-a)+(-b),转为-(a+b)
32         {
33             result = Plus(list1, list2);//-(a+b)
34             result->sign = 1;
35         }
36     }
37     else if (optr == ‘-‘)//输入了减法
38     {
39         if (list1->sign == 0 && list2->sign == 0)//a-b,需比较大小
40         {
41             if (compare(list1,list2)==Greater)
42                 result = Minus(list1, list2);//|a|>|b|时,a-b
43             else if (compare(list1,list2)==Less)//|a|<|b|时,转为-(b-a)
44             {
45                 result = Minus(list2, list1);//-(b-a)
46                 result->sign = 1;
47             }
48             else if (compare(list1, list2) == Equal) result->insert_head(0);//相等,差直接等于0
49         }
50         else if (list1->sign == 0 && list2->sign == 1)//a+b,两个正数相加
51             result = Plus(list1, list2);
52         else if (list1->sign == 1 && list2->sign == 0)//(-a)-b,转为-(a+b)
53         {
54             result = Plus(list1, list2);//-(a+b)
55             result->sign = 1;
56         }
57         else//(-a)-(-b),即为b-a
58         {
59             if (compare(list2,list1)==Greater) result = Minus(list2, list1);//|b|>|a|时,转为b-a
60             else if (compare(list2,list1)==Less) //|b|<|a|时,转为-(a-b)
61             {
62                 result = Minus(list1, list2);//-(a-b)
63                 result->sign = 1;
64             }
65             else if (compare(list2, list1) == Equal) result->insert_head(0);//相等,差直接等于0
66         }
67     }
68     return result;
69 }

operate

运算函数的辅助函数----加法

 1 template<class List_entry>
 2 List<List_entry>* Plus(List<List_entry>* list1, List<List_entry>* list2)
 3 {
 4     List<List_entry> *result = new List<List_entry>();//存放结果的链表
 5     Node<List_entry> *current1 = list1->tail;//初始化操作数
 6     Node<List_entry> *current2 = list2->tail;
 7     int carry = 0;//进位标记
 8     List_entry tempResult;//每段的结果
 9     int maxCount = list1->count>list2->count ? list1->count : list2->count;//最多的结点个数
10     Node<List_entry> *zero = new Node<List_entry>(0);//值为0的结点,用于处理早到head的那个链表
11     for (int i = 0; i<maxCount; i++)
12     {
13         if (current1 == NULL) current1 = zero;
14         if (current2 == NULL) current2 = zero;//早到的原地循环
15         tempResult = current1->entry + current2->entry + carry;
16         carry = 0;//加完进位后将carry置1
17         if (tempResult > limitedNum || tempResult==limitedNum)
18         {
19             carry = 1;//有进位
20             tempResult = tempResult % limitedNum;//取余数
21         }
22         result->insert_head(tempResult);//插入结果链表
23         current1 = current1->back;//向高位走
24         current2 = current2->back;
25     }
26     if (carry == 1) result->insert_head(1);
27     return result;
28 }

运算函数的辅助函数----减法

 1 template<class List_entry>
 2 List<List_entry>* Minus(List<List_entry> *list1, List<List_entry> *list2)
 3 {
 4     List<List_entry> *result = new List<List_entry>();//存放结果的链表
 5     Node<List_entry> *current1 = list1->tail;//初始化操作数
 6     Node<List_entry> *current2 = list2->tail;
 7     int borrow = 0;//借位标记
 8     List_entry tempResult;//每段的结果
 9     int maxCount = list1->count;//最多的结点个数(一定是大数减小数)
10     Node<List_entry> *zero = new Node<List_entry>(0);//值为0的结点,用于处理早到head的那个链表
11     List_entry first;//被减数
12     List_entry second;//减数
13     for (int i = 0; i<maxCount; i++)
14     {
15         if (current2 == NULL) current2 = zero;//早到的原地循环
16         first = current1->entry;
17         second = current2->entry;
18         first += borrow;//被减数减去借位
19         borrow = 0;
20         if (first<second)
21         {
22             borrow = -1;//有借位
23             first += limitedNum;
24         }
25         tempResult = first - second;
26         if (i == maxCount - 1 && tempResult==0) return result;//头结点为0,舍弃,直接返回
27         result->insert_head(tempResult);//插入结果链表
28         current1 = current1->back;
29         current2 = current2->back;
30     }
31     return result;
32 }

运行结果:

时间: 2024-10-17 18:25:26

用双向链表实现超长整数加减法的相关文章

整数加减法练习

程序自动产生随机数(srand 设置种子为系统时间,以保证每次运行程序产生的随机数有差别 ),然后用户输入结果,程序判断用户输入是否正确 减法运算时要保证随机产生的a要大于b(用while循环判断,当然前提条件是用户选择的为减法运算,这里只保证式子产生的结果为非负整数). #include <stdio.h> #include <stdlib.h> #include <time.h> int main() { int a,b,c,sign,max; char sign1

华为测试 超长整数相加

请设计一个算法完成两个超长正整数的加法. 输入两个字符串数字 输出相加后的结果,string型 样例输入:99999999999999999999999999999999999999999999999999 1 样例输出:100000000000000000000000000000000000000000000000000 #include<iostream> #include<string> using namespace std; string add(string num1,

超长整数的基础运算 算法实现之进制转换篇

十进制转二进制 由于单个"位"采用的是216-1作为理论最大值,因此在本次大整数的表示过程中每个类似"十进制"位可采用16位的二进制来表示,符号位单独表示. "十"进制转换成二进制,实际上是经过中间状态(即大整数的逻辑存储表示)转化.在转换过程中大整数的每个"位"无耦合,不存在依赖关系,因此实现方式较为单一,即采用十进制数进行不断除2得余数的方式组成二进制的结果.需要特别注意的是二进制字符串不足16位的需要在高位用"

超长整数的基础运算 算法实现自平方篇

在<乘.除篇>中提到过一类特殊的乘法--自平方.之所以特殊是因为两个相乘的数是相同的,在进行每一位遍历的时候其实知道的是两个数的信息. 其实乘法之所以需要O(n^2)的复杂度就是因为需要内嵌两层循环来得出两数的全部信息,所以如果仅需遍历一次即可获取信息的话那么在处理自平方的时候即可达到O(n^2/4)级别. 虽然在级别上没有质的飞跃,但是对n较大的时候,计算量的线性减少而提升的性能还是可观的,毕竟不积硅步无已成千里. 接下来我们先讨论实现思路: 1.将超长整数An (n表示整数长度)划分成两段

超长整数的基础运算 之小结

首先将之前使用的内部函数一一说明实现 输入.输出: /* 大整数扩大radix倍 大整数的每一位都要乘以radix */ int hbi_mul_radix(HBigInt *a, int radix){ <span style="white-space:pre"> </span>long i; <span style="white-space:pre"> </span>unsigned int carry=0,res

超长整数的基础运算 算法实现之乘、除篇

笔算乘法: 对于m位和n位的输入.传统的乘法须要m*n次主要的乘法,也即算法复杂度为O().我们用纸和笔做乘法运算时,用乘数的每一位乘以被乘数的每一位并加上上一列的进位而产生一行适当移位的中间结果.然后再将各行中间结果相加即得到乘法的终于结果.比如10进制下计算189*34的步骤例如以下表: 笔算乘法的运算过程 本算法依照上述过程进行计算.但在计算机上最好是把内部的乘法和加法并行的运行.即计算每一行中间结果的同一时候将该行加到终于结果上.这样既可以省去不少步骤,也避免了中间结果的空间开销和内存管

华为測试 超长整数相加

请设计一个算法完毕两个超长正整数的加法. 输入两个字符串数字 输出相加后的结果.string型 例子输入:99999999999999999999999999999999999999999999999999 1 例子输出:100000000000000000000000000000000000000000000000000 #include<iostream> #include<string> using namespace std; string add(string num1,

高精度计算-大整数加减法

问题描述 求两个不超过 200 位的非负整数的和. 输入数据 有两行,每行是一个不超过 200 位的非负整数,没有多余的前导 0. 输出要求 一行,即相加后的结果.结果里不能有多余的前导 0,即如果结果是 342,那么就不能 输出为 0342. 输入样例 22222222222222222222 33333333333333333333 输出样例 Output Sample: 55555555555555555555 解题思路 C/C++中的 int 类型能表示的范围是[?231,?231–1]

LeetCode No.2 Add Two Numbers

You are given two linked lists representing two non-negative numbers. The digits are stored in reverse order and each of their nodes contain a single digit. Add the two numbers and return it as a linked list. Input: (2 -> 4 -> 3) + (5 -> 6 ->