C++双链表设计无符号大数类

本题要求采用双链表实现无符号大数类,要求实现无符号大数类拷贝控制函数,要求支持无符号大数的加、减、比较、显示等运算,加、减结果必须返回无符号大数,便于进一步参加运算,不可存在内存泄漏。

不使用动态分配扣40%,存在内存泄漏最多扣20%,程序结构要合理,命名规范,程序结构不合理最多扣20%,课内上机没有完成扣20%。

#include<iostream>
#include<bits/stdc++.h>
using namespace std;
class Unsigned_Big_Number{
public:
	Unsigned_Big_Number(); //构造函数 
	~Unsigned_Big_Number(); //析构函数 
//	Unsigned_Big_Number & operator = (const Unsigned_Big_Number &rhs); //复制赋值
	Unsigned_Big_Number & operator = (Unsigned_Big_Number && rhs) noexcept;  //移动赋值 
//	Unsigned_Big_Number(const Unsigned_Big_Number &);  //拷贝构造 
	Unsigned_Big_Number(Unsigned_Big_Number &&)noexcept;  //移动构造 
	void read();  //读入数据 
	void display()const;  //显示并换行 
	void display(int x)const; //重载,显示不换行 
	int compare(const Unsigned_Big_Number &rhs)const;  //比较大小 
	void Compare_And_Display(const Unsigned_Big_Number &rhs);  //比较大小后显示 
	Unsigned_Big_Number plus(const Unsigned_Big_Number &rhs);  //加法 
	Unsigned_Big_Number subtraction(const Unsigned_Big_Number &rhs);  //减法 
	
private:
struct Node{
	int data;
	struct Node *pre;
	struct Node *nxt;
}*m_pHead,*m_pTail;

int m_len;   //链表长度 
};
//构造函数 
Unsigned_Big_Number::Unsigned_Big_Number(){
	m_pHead = new Node;
	m_pHead ->nxt =NULL;
}
//析构函数 
Unsigned_Big_Number::~Unsigned_Big_Number(){
	while(m_pHead){
		Node *p=m_pHead;
		m_pHead=p->nxt;
		delete p;
	} 
}
//拷贝构造
//Unsigned_Big_Number::Unsigned_Big_Number(const Unsigned_Big_Number &rhs){
//	m_pHead = new Node;
//	Node *last = m_pHead;
//	Node *p=rhs.m_pHead->nxt;
//	while(p){
//		Node*q = new Node;
//		q->data = p->data;
//		last->nxt =q;
//		q->pre = last;
//		last = q;
//		p=p->nxt;
//	}
//	last->nxt=NULL;
//}
//复制赋值 
//Unsigned_Big_Number&Unsigned_Big_Number::operator = (const Unsigned_Big_Number &rhs){
//	Unsigned_Big_Number tmp(rhs);
//	Node *t = m_pHead;
//	m_pHead = tmp.m_pHead;
//	tmp.m_pHead = t;
//	return *this;		
//}
//移动赋值
Unsigned_Big_Number & Unsigned_Big_Number::operator =(Unsigned_Big_Number &&rhs)noexcept{
	Node *p = this->m_pHead;
	this->m_pHead = rhs.m_pHead;
	rhs.m_pHead=p; 
	p = this->m_pTail; 
	this->m_pTail = rhs.m_pTail;
	rhs.m_pTail = p;
	this->m_len = rhs.m_len;
	return *this;
}  
 
//移动构造函数
Unsigned_Big_Number::Unsigned_Big_Number(Unsigned_Big_Number &&rhs)noexcept{
	m_pHead = rhs.m_pHead;
	rhs.m_pHead = NULL; 
}

//读入函数
void Unsigned_Big_Number::read(){
	string s;
	cin>>s;
	Node *p=m_pHead;
	int i =0;
	while(s[i]!='\0'){
		Node *q = new Node;
		q->data=s[i]-'0';
		p->nxt=q;
		q->pre=p;
		p=q;
		i++;
	}
	m_pTail=p;
	m_len=i; 
} 

//显示 
void Unsigned_Big_Number::display()const{
	Node *p = m_pHead->nxt;
	for(int i=0;i<m_len;i++){
		cout<<p->data;
		p=p->nxt;
 }
	cout<<endl;
}
void Unsigned_Big_Number::display(int x)const{
	Node *p = m_pHead->nxt;
	for(int i=0;i<m_len;i++){
		cout<<p->data;
		p=p->nxt;
	}
}
//比较函数,大于返回2,等于返回1,小于返回0;

int Unsigned_Big_Number::compare(const Unsigned_Big_Number &rhs)const{
	if(m_len < rhs.m_len) return 0;
	else if (m_len > rhs.m_len)  return 2;
	else{
		Node *p1=m_pHead->nxt;
		Node *p2=rhs.m_pHead->nxt;
		int i=1;
		while(i<m_len &&p1->data == p2->data){
			p1=p1->nxt;
			p2=p2->nxt;
			i++;
		}
		if(p1->data>p2->data) return 2;
		else if (p1->data<p2->data)  return 0 ;
		else return 1;
	}
	
}

//比较并显示 
void Unsigned_Big_Number::Compare_And_Display(const Unsigned_Big_Number &rhs){
	display(1);
	if (compare(rhs)==2) cout<<'>';
	else if (compare(rhs)==1) cout<<'=';
	else cout<<'<';
	rhs.display();
}

Unsigned_Big_Number Unsigned_Big_Number::plus(const Unsigned_Big_Number &rhs){
	Unsigned_Big_Number result;
	Node *front = new Node;
	Node *s=front;	//为了和原来的链表具有一样的结构,最后释放这个空的尾结点; 
	Node *p=m_pTail;
	Node *q=rhs.m_pTail;
	int jw=0;
	for(int i=0;i<min(m_len,rhs.m_len);i++){
		Node *newnode = new Node;
		newnode->data=(p->data+q->data+jw)%10;
		jw=(p->data+q->data+jw)/10;
		newnode->nxt=front;
		front->pre=newnode;
		front=newnode;
		p=p->pre;
		q=q->pre;
	}
	if(m_len>min(m_len,rhs.m_len)){
		for (int i=0;i<m_len-min(m_len,rhs.m_len);i++){
			Node *newnode = new Node;
			newnode->data=(p->data+jw)%10;
			jw=(p->data+jw)/10;
			newnode->nxt=front;
			front->pre=newnode;
			front=newnode;
			p=p->pre;
		}
		if(jw>0){
			Node *newnode = new Node;
			newnode->data=jw;
			newnode->nxt=front;
			front->pre=newnode;
			front=newnode;
			result.m_pHead->nxt=front;
			front->pre= result.m_pHead;
			result.m_len=m_len+1;
		}
		else{
			result.m_pHead->nxt=front;
			front->pre= result.m_pHead;
			result.m_len=m_len;
		}
	}
	else if(rhs.m_len>min(m_len,rhs.m_len)){
		for (int i=0;i<rhs.m_len-min(m_len,rhs.m_len);i++){
			Node *newnode = new Node;
			newnode->data=(q->data+jw)%10;
			jw=(q->data+jw)/10;
			newnode->nxt=front;
			front->pre=newnode;
			front=newnode;
			q=q->pre;
		}
		if(jw>0){
			Node *newnode = new Node;
			newnode->data=jw;
			newnode->nxt=front;
			front->pre=newnode;
			front=newnode;
			result.m_pHead->nxt=front;
			front->pre= result.m_pHead;
			result.m_len=rhs.m_len+1;
		}
		else{
			result.m_pHead->nxt=front;
			front->pre= result.m_pHead;
			result.m_len=rhs.m_len;
		}
	}
	else{
		if(jw>0){
			Node *newnode = new Node;
			newnode->data=jw;
			newnode->nxt=front;
			front->pre=newnode;
			front=newnode;
			result.m_pHead->nxt=front;
			front->pre= result.m_pHead;
			result.m_len=rhs.m_len+1;
		}
		else{
			result.m_pHead->nxt=front;
			front->pre= result.m_pHead;
			result.m_len=rhs.m_len;
		}
	}
	result.m_pTail=s->pre;
	s->pre->nxt = NULL;
	delete s;
	return result;
}

Unsigned_Big_Number Unsigned_Big_Number::subtraction(const Unsigned_Big_Number &rhs){
	Unsigned_Big_Number result;
	Node *front = new Node;
	Node *s=front;	//为了和原来的链表具有一样的结构,最后释放这个空的尾结点; 
	Node *p=m_pTail;
	Node *q=rhs.m_pTail;
	if(compare(rhs)==2){
		for(int i=0;i<rhs.m_len;i++){
			Node *newnode = new Node;
			if(p->data<q->data){
				newnode->data = p->data - q->data+10;
				p->pre->data-=1; 
			}
			else {newnode->data=p->data - q->data;}
			p=p->pre;
			q=q->pre;
			front->pre=newnode;
			newnode->nxt=front;
			front=newnode;
		}
		for(int i=0;i<m_len-rhs.m_len;i++){
			Node *newnode = new Node;
			newnode->data=p->data;
			p=p->pre;
			front->pre=newnode;
			newnode->nxt=front;
			front=newnode;
		}
		//去除前导0
		result.m_len=m_len;
		Node *tmp=front;
		while(front->data==0){
			front=front->nxt;
			delete tmp;
			tmp = front;
			result.m_len--;
		}
	}
	else if(compare(rhs)==0){
		for(int i=0;i<m_len;i++){
			Node *newnode = new Node;
			if(q->data<p->data){
				newnode->data = q->data - p->data+10;
				q->pre->data-=1; 
			}
			else {newnode->data=q->data - p->data;}
			p=p->pre;
			q=q->pre;
			front->pre=newnode;
			newnode->nxt=front;
			front=newnode;
		}
		for(int i=0;i<rhs.m_len-m_len;i++){
			Node *newnode = new Node;
			newnode->data=q->data;
			q=q->pre;
			front->pre=newnode;
			newnode->nxt=front;
			front=newnode;
		}
		//去除前导0
		result.m_len=rhs.m_len;
		Node *tmp=front;
		while(front->data==0){
			front=front->nxt;
			delete tmp;
			tmp = front;
			result.m_len--;
		}
	}
	else{
		Node *newnode = new Node;
		newnode->data=0;
		front->pre=newnode;
		newnode->nxt=front;
		front=newnode;
		result.m_len=1;
	}
result.m_pHead->nxt=front;
front->pre=result.m_pHead; 
result.m_pTail=s->pre;
s->pre->nxt=NULL;
delete s;	
return result;
}
int main(){
Unsigned_Big_Number ubn1,ubn2,ubn3,ubn4,ubn5;
ubn1.read();
ubn2.read();
ubn1.display();
ubn2.display();
ubn1.Compare_And_Display(ubn2);
ubn3=ubn1.plus(ubn2);
Unsigned_Big_Number ubn6(ubn1.plus(ubn2));
ubn3.display();
ubn6.display();
ubn4=ubn1.subtraction(ubn2);
ubn4.display();

ubn5=ubn3.plus(ubn4);
ubn5.display();
}
一些知识点:
  • 构造函数在类生成时会自动首先调用
  • 析构函数在类消失时后自动调用来做扫尾处理
  • 上面的加法函数里定义的s指针(指向尾结点)即使释放,其实那个内存的值还在,并没有去掉,释放了是为了说明可以重新写入数据,s是一个野指针,所以显示的时候尾结点的值依然会显示。所以要加上s的前面的后面是空的语句。
  • 可以给显示函数加一个参数来重载这个函数,用来不换行显示。
  • 用移动赋值重载=运算符,要将私有成员全部换过来,刚开始我就将头结点换过来,但是因为我定义的类里面有长度和尾指针,这两个量并没有给他们赋值。
  • 以上代码并没有用到拷贝赋值,如果定义ubn6,并且想要使他等于ubn1,语句 ubn6=ubn1就要是使用复制赋值(重载=号),如果赋值方式为 ubn6(ubn1)这就要用到拷贝构造(上面的代码有问题,赋值赋值和拷贝构造都要把m_len 和 m_pTail 定义一下才行,懒得改了。。。)
  • 2
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
数据结构课程设计中,C++双向链表是一个常见的数据结构之一。它是一种线性数据结构,由多个节点组成,每个节点包含两个指针,一个指向前一个节点,一个指向后一个节点。双向链表相比于单向链表,可以实现双向遍历。 在C++中,可以通过定义一个双向链表来实现双向链表的功能。以下是一个简单的C++双向链表的实现示例: ```cpp #include <iostream> // 双向链表节点定义 class Node { public: int data; Node* prev; Node* next; }; // 双向链表定义 class DoublyLinkedList { private: Node* head; // 头节点指针 public: DoublyLinkedList() { head = nullptr; } // 在链表头部插入节点 void insertAtHead(int value) { Node* newNode = new Node(); newNode->data = value; newNode->prev = nullptr; newNode->next = head; if (head != nullptr) { head->prev = newNode; } head = newNode; } // 在链表尾部插入节点 void insertAtTail(int value) { Node* newNode = new Node(); newNode->data = value; newNode->next = nullptr; if (head == nullptr) { newNode->prev = nullptr; head = newNode; return; } Node* temp = head; while (temp->next != nullptr) { temp = temp->next; } temp->next = newNode; newNode->prev = temp; } // 打印链表元素 void printList() { Node* temp = head; while (temp != nullptr) { std::cout << temp->data << " "; temp = temp->next; } std::cout << std::endl; } }; int main() { DoublyLinkedList dll; dll.insertAtHead(3); dll.insertAtHead(2); dll.insertAtHead(1); dll.printList(); // 输出:1 2 3 dll.insertAtTail(4); dll.insertAtTail(5); dll.printList(); // 输出:1 2 3 4 5 return 0; } ``` 以上是一个简单的C++双向链表的实现示例。你可以通过调用`insertAtHead`和`insertAtTail`方法来插入节点,通过调用`printList`方法来打印链表元素。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值