数据结构 双向链表的应用之大整数运算

/ 好叫你见识见识,什么叫做又臭又长的裹脚布代码,这篇帖子也是 /

题目

(大数运算)
long long类型一般占8个字节是C/C++中的精度最高的整数类型,取值范围在 -9223372036854775808~+9223372036854775807。在很多场景中,整数范围超出了long long的最值,例如在非对称加密中密钥长度一般为1024bit,转换为十进制数将超过300位,因此不能直接用内置的整数类型来运算。请编写大数运算类型MyBigInteger,使其支持大数据的加法,减法,乘法的运算。
(除法为选做功能,除法运算符合C/C++中的整数除法运算的规则,有20%的测试用例包含除法运算)

【输入】
大整数n,n的位数<=200
大整数m,m的位数<=200
运算符(+,-,*, /)

【输出】n和m的运算结果

例如:
【输入】
56891237265
32156789215
-

【输出】
24734448050

思路

非常懒惰没有去写BigInt的类,直接用的自定义的双向链表,解题分为五部:写双向链表类,输入,判断,计算,输出。

定义类

基本都是书上那一套,没啥好说的,多加了一个倒序遍历,头插和尾插,用起来会顺手些。

enum Error_code{underflow,overflow,success,Range_error};
typedef int Target;
struct Node
{
	Target entry;
	Node* next;
	Node* back;
	Node(); 
	Node(Target item,Node *link_back=NULL,Node *link_next=NULL);
};

Node::Node()
{
	next=NULL;
	back=NULL;
}

Node::Node(Target item,Node *link_back,Node *link_next)
{
	entry=item;
	next=link_next;
	back=link_back;
}

class List
{
	public:
		List();
		~List();
		List(const List &copy);
		void operator= (const List &copy);
		int size( ) const;
		bool is_full( ) const;
		bool is_empty( ) const;
		void clear( );
		void traverse(void (*visit)(Target &));
		void antitraverse(void (*visit)(Target &));
		Error_code retrieve(int position, Target &x) const;
		Error_code replace(int position, const Target &x);
		Error_code remove(int position, Target &x);
		Error_code insert(int position, const Target &x);
		Error_code back_insert(const Target &x);
		Error_code front_insert(const Target &x);
		
	protected:
		int count;
		mutable int current_position;
		mutable Node *current;
		void set_position(int position) const;
};

List::List()
{
	count = 0;
	current_position = -1;
	current = NULL;
}

List::List(const List &copy)
{
	count=copy.count;
	current_position=copy.current_position;
	Node *new_node,*old_node=copy.current;
	if(old_node==NULL)
		current=NULL;
	else
	{
		new_node=current=new Node(old_node->entry);
		while(old_node->next!=NULL)
		{
			old_node=old_node->next;
			new_node->next=new Node(old_node->entry,new_node);
			new_node=new_node->next;
		}
		old_node=copy.current;
		new_node=current;
		while(old_node->back!=NULL)
		{
			old_node=old_node->back;
			new_node->back=new Node(old_node->entry,NULL,new_node);
			new_node=new_node->back;
		}
	}
}

void List::operator= (const List &copy)
{
	List new_copy(copy);
	clear();
	count=new_copy.count;
	current_position=new_copy.current_position;
	current=new_copy.current;
	new_copy.current=NULL;
	new_copy.current_position=0;
	new_copy.count=0;
}

List::~List()
{
	clear();
}

void List::clear()
{
	Node *p,*q;
	if(current==NULL)
		return;
	for(p=current->back;p;p=q)
	{
		q=p->back;
		delete p;
	}
	for(p=current;p;p=q)
	{
		q=p->next;
		delete p;
	}
	count=0;
	current=NULL;
	current_position=-1;
}

int List::size() const
{
	return count;
}

bool List::is_empty() const
{
	return count==0;
}

bool List::is_full() const
{
	Node *new_node;
	new_node=new Node;
	if(new_node==NULL)
		return true;
	else
	{
		delete new_node;
		return false;
	}
}

void List::set_position(int position) const
{
	if (position>=current_position) 
		for ( ; current_position != position; current_position++)
			current=current->next;
	else
		for ( ; current_position != position; current_position--)
			current=current->back;
}

void List::traverse(void (*visit)(Target &))
{
	Node *q=current;
	if(q!=NULL)
		for(;q->back;q=q->back) ;
	for(;q;q=q->next)
		(*visit)(q->entry);
}

void List::antitraverse(void (*visit)(Target &))
{
	Node *p=current;
	if(p!=NULL)
		for(;p->next;p=p->next);
	for(;p;p=p->back)
		(*visit)(p->entry);
}

Error_code List::replace(int position,const Target &x)
{
	if (position < 0 || position > count)
		return Range_error;
	set_position(position);
	current->entry=x;
	return success;
}

Error_code List::insert(int position, const Target &x)
{
	if (position < 0 || position > count)
		return Range_error;
	Node *new_node, *preceding, *following;
	if (position==0) 
	{
		if(count==0)
			following=NULL;
		else
		{
			set_position(0);
			following=current;
		}
		preceding=NULL;
	}
	else
	{
		set_position(position-1);
		preceding=current;
		following=preceding->next;
	}

	new_node=new Node(x,preceding,following);
	if(new_node==NULL) return overflow;
	if(preceding!=NULL)
		preceding->next=new_node;
	if(following!=NULL)
		following->back=new_node;
	current=new_node;
	current_position=position;
	count++;
	return success;
}

Error_code List::remove(int position,Target &x)
{
	if (position<0||position>=count)
		return Range_error;
	Node *old_node, *neighbor;
	set_position(position); 
	old_node=current; 
	if (neighbor=current->back) 
	{	
		neighbor->next=current->next; 
	}
	
	if (neighbor=current->next) 
	{ 
		neighbor->back=current->back; 
		current=neighbor; 
	} 
	else 
	{ 
		current=current->back; 
		current_position--; 
	} 
	x=old_node->entry; 
	delete old_node; 
	count--; 
	return success;
}

Error_code List::back_insert(const Target &x)
{
	insert(count,x);
	return success;
}

Error_code List::front_insert(const Target &x)
{
	insert(0,x);
	return success;
}

Error_code List::retrieve(int position, Target &x) const
{
	if (position < 0 || position >= count)
		return Range_error;
	set_position(position);
	x=current->entry;
	return success;
}

void print(Target &x)
{
	cout << x ;
}

输入

大数作为字符串被读入,然后逐位放进 list 中,考虑到进位,我们将其倒序存放(头插),同时定义一个符号位sym,后面用得上。

void input(List &info,int &sym)
{
	string s;
	cin >> s;
	if(s[0]=='-')
	{
		sym=-1;
		for(int i=1;i<s.size();i++)
		{
			info.front_insert(s[i]-'0');
		}
	}
	else
	{
		sym=0;
		for(int i=0;i<s.size();i++)
		{
			info.front_insert(s[i]-'0');
		}
	}
		
}	

判断

在进行减法和除法运算的时候,我需要判断两个数的大小关系,有时还需要将他们交换。
比较大小时先比较位数长短关系,位数相同时就从高位开始比较,直到出现不同。
非交换的判断函数和判断交换函数只有最后几行不同。

void judge_and_swap(List &p,List &a,int &flag)
{
	flag=0;
	int lenp=p.size(),lena=a.size();
	if(lenp>lena)
		flag=1;
	else if(lenp<lena)
		flag=-1;
	else
	{
		int cnt=lenp-1;
		while(cnt>=0)
		{
			Target np,na;
			p.retrieve(cnt,np);
			a.retrieve(cnt,na);
			if(np>na)
			{
				flag=1;
				break;
			}
			else if(na>np)
			{
				flag=-1;
				break;
			}
			cnt--;
		}
	}
	if(flag==-1)
	{
		List temp;
		temp=p;
		p=a;
		a=temp;
	}
}

计算

加法

纯模拟,从低位开始两两相加,只留个位,十位作为进位参与到下次计算,两个list的所有结点都参与过运算之后进位如果大于0,则再进位。
感觉这里对于两个加数不同长度的处理还是蛮妙的。

List bigintadd (List pre,List aft)
{
	List res;
	Target pret,aftt;
	int carry=0,cntp=0,cnta=0;
	while(cntp<pre.size()||cnta<aft.size())
	{
		int sum=carry;
		if(cntp<pre.size())
		{
			pre.retrieve(cntp,pret); 
			sum+=pret;
			cntp++;
		}
		if(cnta<aft.size())
		{
			aft.retrieve(cnta,aftt); 
			sum+=aftt;
			cnta++;
		}
		carry=sum/10;
		res.back_insert(sum%10);
	}
	if(carry>0)
		res.back_insert(carry);
	return res;
}
减法

减法比加法啰嗦一步,为了保证 bigintsub 函数执行完之后结果 list 中每一位都大于零,我们调用比较交换函数,确保大数减小数。
之后还是模拟,被减数的位减去减数的位,如果结果小于零就加十,然后进位设置为-1参与下次运算。接着根据比较函数得到的两数大小给数据加符号,最后再剔除一手高位退位产生的前导0。

List bigintsub (List pre,List aft)
{
	List res;
	Target pret,aftt;
	int flag1;
	judge_and_swap(pre,aft,flag1);
	if(flag1==0)
		res.back_insert(0);
	else
	{
		int carry=0,cntp=0,cnta=0;
		while(cntp<pre.size()||cnta<aft.size())
		{
			int sum=carry;
			if(cntp<pre.size())
			{
				pre.retrieve(cntp,pret); 
				sum+=pret;
				cntp++;
			}
			if(cnta<aft.size())
			{
				aft.retrieve(cnta,aftt); 
				sum-=aftt;
				cnta++;
			}
			if(sum<0) 
			{
				sum+=10;
				carry=-1;
			}
			else
			{
				carry=0;
			}
			res.back_insert(sum%10);
		}
		if(flag1==-1)
		{
			int rest;
			res.retrieve(res.size()-1,rest);
			rest*=-1;
			res.replace(res.size()-1,rest);
		}
	}
	int rest;
	res.retrieve(res.size()-1,rest);
	while(rest==0&&(!res.is_empty()))
	{
		res.remove(res.size()-1,rest);
		res.retrieve(res.size()-1,rest);
	}
	return res;
}

乘法

每次从乘数的低位取一个数字,和另一个乘数的每一位数字相乘,还是进位那一套,最后根据一开始取的数字的位数,在每次乘积的低位补上相应个数的0,最后把这些乘积加起来就可以了。

List bigintmult(List pre,List aft)
{
	List res;
	Target pret,aftt;
	int flag1;
	judge_and_swap(pre,aft,flag1);
	Target i2;
	int cnt=0;
	while(!aft.is_empty())
	{
		List temps,tempr;
		aft.remove(0,i2);
		temps=pre;
		if(!temps.is_empty())
		{
			int sum=0,carry=0;
			while(!temps.is_empty())
			{
				Target i1;
				temps.remove(0,i1);
				sum=i1*i2+carry;
				carry=sum/10;
				sum%=10;
				tempr.back_insert(sum);
			}
			if(carry>0)
				tempr.back_insert(carry);
		}
		for(int i=0;i<cnt;i++)
			tempr.front_insert(0);
		cnt++;
		res=bigintadd(res,tempr);
	}
	return res;
}

除法

除法是折磨我时间最长的,一开始想到的思路是用被除数减除数,直到被减数小于减数,计算减的次数,但是这样做毫无疑问会超时,于是换了思路,本质也是做减法,但是最开始给减数补上0,0的个数为二者位数差,然后每次补零的个数递减。
举个栗子:6666 / 23 。按照一开始的思路是 6666 = 23*289+19 ,需要计算 289 次,结果为 289,改良之后为 6666=2300*2+230*8+23*9+19,只需要计算19次,结果为 200+80+9=289,完全一致嘛。
一些特殊情况就是被除数小于除数或者有0存在,就直接将结果返回为0。

List bigintdiv(List pre,List aft)
{
	List res;
	Target pret,aftt;
	int flag1;
	judge_and_swap(pre,aft,flag1);
	pre.retrieve(pre.size()-1,pret);
	aft.retrieve(aft.size()-1,aftt);
	if(flag1==-1||pret==0||aftt==0)
	{
		res.back_insert(0);
		return res;
	}
	else
	{
		List temp;
		int cnt=pre.size()-aft.size();
		temp.back_insert(1);
		res.back_insert(0);
		for(int i=0;i<cnt;i++) //补零
		{
			temp.front_insert(0);
			aft.front_insert(0);
		}
		while(cnt>=0)
		{
			int flag2;
			judge(pre,aft,flag2);
			while(flag2!=-1)
			{
				pre=bigintsub(pre,aft);
				int t;
				pre.retrieve(pre.size()-1,t);
				while(t==0&&(!pre.is_empty()))
				{
					pre.remove(pre.size()-1,t);
					pre.retrieve(pre.size()-1,t);
				}
				judge(pre,aft,flag2);
				res=bigintadd(res,temp);
			}
			cnt--;
			Target tmp;
			temp.remove(0,tmp);   //去零
			aft.remove(0,tmp);
		}
	}
	return res;
}

符号判断

之前的计算函数都是默认输入为两个整数,但是实际情况更加复杂,在运用时需要对具体情况,比如数据的正负,数据的长度等进行判断,比如“-” + “-” , “+” - “-”……
好叭我承认这样处理确实是因为我很愚蠢很笨蛋。

void solve(List &a,List &b,List &res,char s,int flaga,int flagb)
{
	int flag=flaga+flagb;
	if(s=='+'&&flag==0)
		res=bigintadd(a,b);
	else if(s=='+'&&flag==-2)
	{
		res=bigintadd(a,b);
		int rest;
		res.retrieve(res.size()-1,rest);
		rest*=-1;
		res.replace(res.size()-1,rest);
	}
	else if((s=='+'&&flag==-1))
	{
		int cnt;
		judge_and_swap(a,b,cnt);
		res=bigintsub(a,b);
		if((cnt==1&&flaga==-1)||(cnt==-1&&flagb==-1))
		{
			int rest;
			res.retrieve(res.size()-1,rest);
			rest*=-1;
			res.replace(res.size()-1,rest);
		}
	}
	else if(s=='-'&&flaga==-1&&flagb==0)
	{
		res=bigintadd(a,b);
		int rest;
		res.retrieve(res.size()-1,rest);
		rest*=-1;
		res.replace(res.size()-1,rest);
	}
	else if(s=='-'&&flaga==0&&flagb==-1)
	{
		res=bigintadd(a,b);
	}
	else if(s=='-')
		res=bigintsub(a,b);
	else if(s=='*')
	{
		res=bigintmult(a,b);
		if(flag==-1)
		{
			int rest;
			res.retrieve(res.size()-1,rest);
			rest*=-1;
			res.replace(res.size()-1,rest);
		}
	}
	else if(s=='/')
	{
		res=bigintdiv(a,b);	
		if(flag==-1)
		{		
			int rest;
			res.retrieve(res.size()-1,rest);
			rest*=-1;
			res.replace(res.size()-1,rest);
		}
	}	
	int rest;
	res.retrieve(res.size()-1,rest);
	while(rest==0&&(!res.is_empty()))
	{
		res.remove(res.size()-1,rest);
		res.retrieve(res.size()-1,rest);
	}
	if(!res.is_empty())
		res.antitraverse(print);
	else
		cout << 0;
}

输出

具体代码写在上面的solve函数里了,就是再判断一次前导0,然后把 list 里的内容逆序输出即可。

完整代码

#include <bits/stdc++.h>
using namespace std;
/* run this program using the console pauser or add your own getch, system("pause") or input loop */

enum Error_code{underflow,overflow,success,Range_error};
typedef int Target;
struct Node
{
	Target entry;
	Node* next;
	Node* back;
	Node(); 
	Node(Target item,Node *link_back=NULL,Node *link_next=NULL);
};

Node::Node()
{
	next=NULL;
	back=NULL;
}

Node::Node(Target item,Node *link_back,Node *link_next)
{
	entry=item;
	next=link_next;
	back=link_back;
}

class List
{
	public:
		List();
		~List();
		List(const List &copy);
		void operator= (const List &copy);
		int size( ) const;
		bool is_full( ) const;
		bool is_empty( ) const;
		void clear( );
		void traverse(void (*visit)(Target &));
		void antitraverse(void (*visit)(Target &));
		Error_code retrieve(int position, Target &x) const;
		Error_code replace(int position, const Target &x);
		Error_code remove(int position, Target &x);
		Error_code insert(int position, const Target &x);
		Error_code back_insert(const Target &x);
		Error_code front_insert(const Target &x);
		
	protected:
		int count;
		mutable int current_position;
		mutable Node *current;
		void set_position(int position) const;
};

List::List()
{
	count = 0;
	current_position = -1;
	current = NULL;
}

List::List(const List &copy)
{
	count=copy.count;
	current_position=copy.current_position;
	Node *new_node,*old_node=copy.current;
	if(old_node==NULL)
		current=NULL;
	else
	{
		new_node=current=new Node(old_node->entry);
		while(old_node->next!=NULL)
		{
			old_node=old_node->next;
			new_node->next=new Node(old_node->entry,new_node);
			new_node=new_node->next;
		}
		old_node=copy.current;
		new_node=current;
		while(old_node->back!=NULL)
		{
			old_node=old_node->back;
			new_node->back=new Node(old_node->entry,NULL,new_node);
			new_node=new_node->back;
		}
	}
}

void List::operator= (const List &copy)
{
	List new_copy(copy);
	clear();
	count=new_copy.count;
	current_position=new_copy.current_position;
	current=new_copy.current;
	new_copy.current=NULL;
	new_copy.current_position=0;
	new_copy.count=0;
}

List::~List()
{
	clear();
}

void List::clear()
{
	Node *p,*q;
	if(current==NULL)
		return;
	for(p=current->back;p;p=q)
	{
		q=p->back;
		delete p;
	}
	for(p=current;p;p=q)
	{
		q=p->next;
		delete p;
	}
	count=0;
	current=NULL;
	current_position=-1;
}

int List::size() const
{
	return count;
}

bool List::is_empty() const
{
	return count==0;
}

bool List::is_full() const
{
	Node *new_node;
	new_node=new Node;
	if(new_node==NULL)
		return true;
	else
	{
		delete new_node;
		return false;
	}
}

void List::set_position(int position) const
{
	if (position>=current_position) 
		for ( ; current_position != position; current_position++)
			current=current->next;
	else
		for ( ; current_position != position; current_position--)
			current=current->back;
}

void List::traverse(void (*visit)(Target &))
{
	Node *q=current;
	if(q!=NULL)
		for(;q->back;q=q->back) ;
	for(;q;q=q->next)
		(*visit)(q->entry);
}

void List::antitraverse(void (*visit)(Target &))
{
	Node *p=current;
	if(p!=NULL)
		for(;p->next;p=p->next);
	for(;p;p=p->back)
		(*visit)(p->entry);
}

Error_code List::replace(int position,const Target &x)
{
	if (position < 0 || position > count)
		return Range_error;
	set_position(position);
	current->entry=x;
	return success;
}

Error_code List::insert(int position, const Target &x)
{
	if (position < 0 || position > count)
		return Range_error;
	Node *new_node, *preceding, *following;
	if (position==0) 
	{
		if(count==0)
			following=NULL;
		else
		{
			set_position(0);
			following=current;
		}
		preceding=NULL;
	}
	else
	{
		set_position(position-1);
		preceding=current;
		following=preceding->next;
	}

	new_node=new Node(x,preceding,following);
	if(new_node==NULL) return overflow;
	if(preceding!=NULL)
		preceding->next=new_node;
	if(following!=NULL)
		following->back=new_node;
	current=new_node;
	current_position=position;
	count++;
	return success;
}

Error_code List::remove(int position,Target &x)
{
	if (position<0||position>=count)
		return Range_error;
	Node *old_node, *neighbor;
	set_position(position); 
	old_node=current; 
	if (neighbor=current->back) 
	{	
		neighbor->next=current->next; 
	}
	
	if (neighbor=current->next) 
	{ 
		neighbor->back=current->back; 
		current=neighbor; 
	} 
	else 
	{ 
		current=current->back; 
		current_position--; 
	} 
	x=old_node->entry; 
	delete old_node; 
	count--; 
	return success;
}

Error_code List::back_insert(const Target &x)
{
	insert(count,x);
	return success;
}

Error_code List::front_insert(const Target &x)
{
	insert(0,x);
	return success;
}

Error_code List::retrieve(int position, Target &x) const
{
	if (position < 0 || position >= count)
		return Range_error;
	set_position(position);
	x=current->entry;
	return success;
}

void print(Target &x)
{
	cout << x ;
}

void input(List &info,int &sym)
{
	string s;
	cin >> s;
	if(s[0]=='-')
	{
		sym=-1;
		for(int i=1;i<s.size();i++)
		{
			info.front_insert(s[i]-'0');
		}
	}
	else
	{
		sym=0;
		for(int i=0;i<s.size();i++)
		{
			info.front_insert(s[i]-'0');
		}
	}
		
}	

List bigintadd (List pre,List aft)
{
	List res;
	Target pret,aftt;
	int carry=0,cntp=0,cnta=0;
	while(cntp<pre.size()||cnta<aft.size())
	{
		int sum=carry;
		if(cntp<pre.size())
		{
			pre.retrieve(cntp,pret); 
			sum+=pret;
			cntp++;
		}
		if(cnta<aft.size())
		{
			aft.retrieve(cnta,aftt); 
			sum+=aftt;
			cnta++;
		}
		carry=sum/10;
		res.back_insert(sum%10);
	}
	if(carry>0)
		res.back_insert(carry);
	return res;
}

void judge_and_swap(List &p,List &a,int &flag)
{
	flag=0;
	int lenp=p.size(),lena=a.size();
	if(lenp>lena)
		flag=1;
	else if(lenp<lena)
		flag=-1;
	else
	{
		int cnt=lenp-1;
		while(cnt>=0)
		{
			Target np,na;
			p.retrieve(cnt,np);
			a.retrieve(cnt,na);
			if(np>na)
			{
				flag=1;
				break;
			}
			else if(na>np)
			{
				flag=-1;
				break;
			}
			cnt--;
		}
	}
	if(flag==-1)
	{
		List temp;
		temp=p;
		p=a;
		a=temp;
	}
}

void judge(List p,List a,int &flag)
{
	flag=0;
	int lenp=p.size(),lena=a.size();
	if(lenp>lena)
		flag=1;
	else if(lenp<lena)
		flag=-1;
	else
	{
		int cnt=lenp-1;
		while(cnt>=0)
		{
			Target np,na;
			p.retrieve(cnt,np);
			a.retrieve(cnt,na);
			if(np>na)
			{
				flag=1;
				break;
			}
			else if(na>np)
			{
				flag=-1;
				break;
			}
			cnt--;
		}
	}
}

List bigintsub (List pre,List aft)
{
	List res;
	Target pret,aftt;
	int flag1;
	judge_and_swap(pre,aft,flag1);
	if(flag1==0)
		res.back_insert(0);
	else
	{
		int carry=0,cntp=0,cnta=0;
		while(cntp<pre.size()||cnta<aft.size())
		{
			int sum=carry;
			if(cntp<pre.size())
			{
				pre.retrieve(cntp,pret); 
				sum+=pret;
				cntp++;
			}
			if(cnta<aft.size())
			{
				aft.retrieve(cnta,aftt); 
				sum-=aftt;
				cnta++;
			}
			if(sum<0) 
			{
				sum+=10;
				carry=-1;
			}
			else
			{
				carry=0;
			}
			res.back_insert(sum%10);
		}
		if(flag1==-1)
		{
			int rest;
			res.retrieve(res.size()-1,rest);
			rest*=-1;
			res.replace(res.size()-1,rest);
		}
	}
	int rest;
	res.retrieve(res.size()-1,rest);
	while(rest==0&&(!res.is_empty()))
	{
		res.remove(res.size()-1,rest);
		res.retrieve(res.size()-1,rest);
	}
	return res;
}

List bigintmult(List pre,List aft)
{
	List res;
	Target pret,aftt;
	int flag1;
	judge_and_swap(pre,aft,flag1);
	Target i2;
	int cnt=0;
	while(!aft.is_empty())
	{
		List temps,tempr;
		aft.remove(0,i2);
		temps=pre;
		if(!temps.is_empty())
		{
			int sum=0,carry=0;
			while(!temps.is_empty())
			{
				Target i1;
				temps.remove(0,i1);
				sum=i1*i2+carry;
				carry=sum/10;
				sum%=10;
				tempr.back_insert(sum);
			}
			if(carry>0)
				tempr.back_insert(carry);
		}
		for(int i=0;i<cnt;i++)
			tempr.front_insert(0);
		cnt++;
		res=bigintadd(res,tempr);
	}
	return res;
}

List bigintdiv(List pre,List aft)
{
	List res;
	Target pret,aftt;
	int flag1;
	judge_and_swap(pre,aft,flag1);
	pre.retrieve(pre.size()-1,pret);
	aft.retrieve(aft.size()-1,aftt);
	if(flag1==-1||pret==0||aftt==0)
	{
		res.back_insert(0);
		return res;
	}
	else
	{
		List temp;
		int cnt=pre.size()-aft.size();
		temp.back_insert(1);
		res.back_insert(0);
		for(int i=0;i<cnt;i++)
		{
			temp.front_insert(0);
			aft.front_insert(0);
		}
		while(cnt>=0)
		{
			int flag2;
			judge(pre,aft,flag2);
			while(flag2!=-1)
			{
				pre=bigintsub(pre,aft);
				int t;
				pre.retrieve(pre.size()-1,t);
				while(t==0&&(!pre.is_empty()))
				{
					pre.remove(pre.size()-1,t);
					pre.retrieve(pre.size()-1,t);
				}
				judge(pre,aft,flag2);
				res=bigintadd(res,temp);
			}
			cnt--;
			Target tmp;
			temp.remove(0,tmp);
			aft.remove(0,tmp);
		}
	}
	return res;
}

void solve(List &a,List &b,List &res,char s,int flaga,int flagb)
{
	int flag=flaga+flagb;
	if(s=='+'&&flag==0)
		res=bigintadd(a,b);
	else if(s=='+'&&flag==-2)
	{
		res=bigintadd(a,b);
		int rest;
		res.retrieve(res.size()-1,rest);
		rest*=-1;
		res.replace(res.size()-1,rest);
	}
	else if((s=='+'&&flag==-1))
	{
		int cnt;
		judge_and_swap(a,b,cnt);
		res=bigintsub(a,b);
		if((cnt==1&&flaga==-1)||(cnt==-1&&flagb==-1))
		{
			int rest;
			res.retrieve(res.size()-1,rest);
			rest*=-1;
			res.replace(res.size()-1,rest);
		}
	}
	else if(s=='-'&&flaga==-1&&flagb==0)
	{
		res=bigintadd(a,b);
		int rest;
		res.retrieve(res.size()-1,rest);
		rest*=-1;
		res.replace(res.size()-1,rest);
	}
	else if(s=='-'&&flaga==0&&flagb==-1)
	{
		res=bigintadd(a,b);
	}
	else if(s=='-')
		res=bigintsub(a,b);
	else if(s=='*')
	{
		res=bigintmult(a,b);
		if(flag==-1)
		{
			int rest;
			res.retrieve(res.size()-1,rest);
			rest*=-1;
			res.replace(res.size()-1,rest);
		}
	}
	else if(s=='/')
	{
		res=bigintdiv(a,b);	
		if(flag==-1)
		{		
			int rest;
			res.retrieve(res.size()-1,rest);
			rest*=-1;
			res.replace(res.size()-1,rest);
		}
	}	
	int rest;
	res.retrieve(res.size()-1,rest);
	while(rest==0&&(!res.is_empty()))
	{
		res.remove(res.size()-1,rest);
		res.retrieve(res.size()-1,rest);
	}
	if(!res.is_empty())
		res.antitraverse(print);
	else
		cout << 0;
}

int main()
{
	List pre,aft,final;
	int flaga=0,flagb=0;
	char s;
	input(pre,flaga);
	input(aft,flagb);
	cin >> s;
	solve(pre,aft,final,s,flaga,flagb);
	return 0;
}

小结

减法部分的符号判断我觉得是不全面的,ac就说明,欸题目数据很弱欸。
整个代码都透出一种不灵光,笨拙的气息,封装性和鲁棒性都很差,确实是又臭又长,要学的东西还很多啊。
因为代码里面过多的使用了传引用,静态评估分基本被扣光了,OCLint真的很严格。
在这里插入图片描述
希望以后会来更新这篇博文,把BigInt的类补上,把符号重载写一写,再封装的好一些。
最近确实太忙了,计算机系统的实验挺费时间的,但也挺有趣的,五一找时间会写一写。

推荐

这一篇是大佬室友写的,比我的简洁多了。
https://blog.csdn.net/weixin_47003107/article/details/105848624

这一篇是同学推荐的,很吊的大数模板。
https://www.cnblogs.com/feiyue-1779930274/p/11628128.html

原创文章 9 获赞 10 访问量 660

猜你喜欢

转载自blog.csdn.net/qq_45401156/article/details/105852292