北邮22信通:(8)实验1 题目五:大整数加减法(搬运官方代码)
北邮22信通一枚~
跟随课程进度每周更新数据结构与算法的代码和文章
持续关注作者 解锁更多邮苑信通专属代码~
上一篇文章:
北邮22信通:(7)实验1 题目四:一元多项式(节省内存版)_青山如墨雨如画的博客-CSDN博客
下一篇文章:
*****声明*****
本代码由官方提供,不是作者的算法。
本代码仅供研究学习使用,请不要用于其他用途。
有问题的友友也可以在评论区留言,我们可以一起讨论。
本代码在DEVC++中可以运行。
*****声明完毕*****
1.实验要求:
利用链表实现大整数加减法操作;32位极其直接操作的数据最大为32bit,若超过32bit,则需要单独设计算法。在这里,可以用链表的每个节点存储大整数的每一位的十进制数字,则可以进行大整数的算术运算,该实验仅实现加减法操作。
要求:
随机产生2个1~50位的字符串,并存储到新的链表中;
打印运算结果。
考虑链表结构的设计,是否有更节省空间的数据结构。
2.代码部分:
#include <iosfwd>
#include <iostream>
#include <stack>
#include "time.h"
using namespace std;struct Node
{int data;Node *next;
};
class BigInteger
{
public:BigInteger();BigInteger(int a[], int n, bool pos);friend BigInteger add(BigInteger &int1, BigInteger &int2); //int1 + int2friend BigInteger sub(BigInteger &int1, BigInteger &int2); //int1 - int2int getLength(); //获取链表长度void print();~BigInteger();
private:Node *first;int length;bool positive = true; //记录整数的正负
};BigInteger::BigInteger()
{first = new Node;first->data = 0;first->next = NULL;length = 1;
}BigInteger::BigInteger(int a[], int n, bool pos = true) //引用和声明只能有一个默认参数定义
{if (n < 1){throw "integer length should be at least 1";}//尾插法 不带头结点的链表first = new Node;Node *r = first; //指向最后一个结点for (int i = 0; i<n - 1; i++){r->data = a[i];Node *s = new Node; //(1)生成新结点s->next = NULL;r->next = s; //(2) 链接在尾结点后面r = s; //(3) 尾指针后移}r->data = a[n-1];r->next = NULL;length = n;positive = pos;
}
BigInteger::~BigInteger() {}BigInteger sub(BigInteger &int1, BigInteger &int2) { //都可以转换成正数的加减法BigInteger newint = BigInteger();newint.length = 0; //友元能直接访问私有变量if ((!int1.positive)&&(!int2.positive)){ //-int1-(-int2) = -int1 + int2int2.positive = true;newint = add(int1,int2);int2.positive = false;return newint;}else if (!int1.positive){int1.positive = true;newint = add(int1,int2);newint.positive = false;int1.positive = false;return newint;}else if (!int2.positive){int2.positive = true;newint = add(int1,int2);int2.positive = false;return newint;}// 这里开始的处理,int1和int2应都为正整数Node *cursor = new Node; //游标用来创建新的链表Node *tobedelete = cursor; //临时的头结点cursor->next = newint.first; Node *int1_first = int1.first; //遍历int1Node *int2_first = int2.first; //遍历int2stack<Node*> substk; //定义一个栈用来处理高位的连续0 如77772-77771 = 1 ,需要把前面的0都删除int flag = 0; //记录减法的借位//首先遍历到 min(int1.length, int2.length)位,之后至少有一个指针为NULLfor (int i = 0; i < int1.length && i < int2.length; i++){int tmp = int1_first->data - int2_first->data - flag;if (tmp < 0){tmp += 10;if (tmp == 0){substk.push(cursor); //1000 - 99 = 901}else{while (!substk.empty()) //有出现不为0的位,就把栈清空substk.pop();}flag = 1;}else if ((tmp == 0)&&(cursor->next!=newint.first)){ //个位为0不入栈,入栈的是0前面的结点substk.push(cursor);flag = 0;}else{while (!substk.empty())substk.pop();flag = 0;}cursor->next->data = tmp; //在结果链表中插入新节点cursor->next->next = new Node;cursor = cursor->next;cursor->next->next = NULL;int1_first = int1_first->next;int2_first = int2_first->next;newint.length++;}//减完位数相同的部分,讨论接下来的情况if ((int1_first == NULL) && (int2_first == NULL)){if (!flag == 0) //最高位有借位说明结果是负的,在后面计算补码newint.positive = false;}else if(int1_first == NULL){// int2位数多,结果一定是负数newint.positive = false;while (int2_first != NULL){int tmp = 0 - int2_first->data - flag;if (tmp < 0){tmp += 10;if (tmp == 0){substk.push(cursor);}else{while (!substk.empty())substk.pop();}flag = 1;}else if (tmp == 0){substk.push(cursor);flag = 0;}else{while (!substk.empty())substk.pop();flag = 0;}cursor->next->data = tmp;cursor->next->next = new Node;cursor = cursor->next;cursor->next->next = NULL;newint.length++;int2_first = int2_first->next;}}else{while (int1_first != NULL){// int1位数高,结果必为正int tmp = int1_first->data - flag;if (tmp < 0){tmp += 10;if (tmp == 0){substk.push(cursor);}else{while (!substk.empty())substk.pop();}flag = 1;}else if (tmp == 0){substk.push(cursor);flag = 0;}else{while (!substk.empty())substk.pop();flag = 0;}cursor->next->data = tmp;cursor->next->next = new Node;cursor = cursor->next;cursor->next->next =NULL;newint.length++;int1_first = int1_first->next;}}//删除初始化的临时节点delete tobedelete;//删除末尾的临时节点tobedelete = cursor->next;cursor->next = NULL;delete tobedelete;//删除最后的连续0节点while (!substk.empty()){cursor = substk.top();if (cursor->next == newint.first) //个位不能被删除(删除的也不是个位,tobedelete已经被释放了)break;substk.pop();tobedelete = cursor->next;cursor->next = NULL;newint.length--;delete tobedelete;}if (!newint.positive){//得到的newint为负数,需要补码操作,如9-16 -> 93,100-93 = 7int a[int2.length+1];for (int i = 0; i < int2.length;i++)a[i] = 0;a[int2.length] = 1;newint.positive = true;BigInteger complement = BigInteger(a,newint.length + 1);tobedelete = newint.first;newint = sub(complement,newint); //newint的地址换了,构造了一个新对象newint.positive = false;while (tobedelete != NULL){Node *tobed = tobedelete;tobedelete = tobedelete->next;delete tobed;}}return newint;
}BigInteger add(BigInteger &int1, BigInteger &int2) {BigInteger newint = BigInteger(); //定义新的大整数作为返回值newint.length = 0;if ((!int1.positive)&&(!int2.positive))newint.positive = false;else if(!int1.positive){int1.positive = true;newint = sub(int2,int1);int1.positive = false;return newint;}else if(!int2.positive){int2.positive = true;newint = sub(int1,int2);int2.positive = false;return newint;}// 这里开始的处理,int1和int2应都为正整数Node *cursor = new Node; //创建一个游标指针用于构建newintNode *tobedelete = cursor; //记录临时用的节点位置,最后删掉,防止内存泄漏cursor->next = newint.first;Node *int1_first = int1.first;Node *int2_first = int2.first;int flag = 0; //记录加法的进位//首先遍历到 min(int1.length, int2.length)位,之后至少有一个指针为NULLfor (int i = 0; i < int1.length && i < int2.length; i++){int tmp = int1_first->data + int2_first->data + flag;if (tmp >= 10){tmp -= 10;flag = 1;} elseflag = 0;cursor->next->data = tmp;cursor->next->next = new Node;cursor = cursor->next;int1_first = int1_first->next;int2_first = int2_first->next;newint.length++;}if ((int1_first == NULL) && (int2_first == NULL)){}else if(int1_first == NULL){// int2的位数多while (int2_first != NULL){int tmp = int2_first->data + flag;if (tmp >= 10){tmp -= 10;flag = 1;} elseflag = 0;cursor->next->data = tmp;cursor->next->next = new Node;cursor = cursor->next;newint.length++;int2_first = int2_first->next;}}else{while (int1_first != NULL){// int1的位数多int tmp = int1_first->data + flag;if (tmp >= 10){tmp -= 10;flag = 1;} elseflag = 0;cursor->next->data = tmp;cursor->next->next = new Node;cursor = cursor->next;newint.length++;int1_first = int1_first->next;}}delete tobedelete; //删除初始化的临时节点,防止内存泄漏if (flag != 1){//如果最后没有进位,删除末尾的临时节点,防止内存泄漏tobedelete = cursor->next;cursor->next = NULL;delete tobedelete;return newint;}else{//如果有进位,则将数据赋到末尾节点cursor->next->data = 1;cursor->next->next = NULL;newint.length++;}return newint;
}int BigInteger::getLength() //O(1)
{return this->length;
}void BigInteger::print() {stack<int> s;Node *p = first;while (p != NULL){s.push(p->data);p = p->next;}if(!positive)cout << "-";while (!s.empty()){int tmp = s.top();cout << tmp;s.pop();}
}int main()
{//从低位到高位//{个,十,百,千,万,...}int nums1[2] = {2,3};BigInteger int1(nums1, 2);int nums2[2] = {2,3};BigInteger int2(nums2, 2);// srand((unsigned )time(NULL)); //随机数种子// int n = rand() % 50 +1;// int nums1[n];// for(int i = 0; i < n; i++)// {// nums1[i] = rand()%10;// }// if(nums1[n-1] == 0)// nums1[n-1] = 1;// BigInteger int1(nums1,n);// n = rand() % 50 + 1;// int nums2[n];// for(int i = 0; i < n; i++)// {// nums2[i] = rand()%10;// }// if(nums2[n-1] == 0)// nums2[n-1] = 1;// BigInteger int2(nums2, n);cout << "int1: ";int1.print();cout << endl;cout << "int2: ";int2.print();cout << endl;try{cout << "*********************" << endl;BigInteger newint = add(int1,int2);newint.print();cout << "=";int1.print();cout << "+";int2.print();cout << endl;cout << "*********************" << endl;BigInteger subint = sub(int1,int2);subint.print();cout << "=";int1.print();cout << "-";int2.print();cout << endl;}catch (const char* e){cout << e << endl;return 0;}return 0;
}
程序运行结果:
相关文章:

北邮22信通:(8)实验1 题目五:大整数加减法(搬运官方代码)
北邮22信通一枚~ 跟随课程进度每周更新数据结构与算法的代码和文章 持续关注作者 解锁更多邮苑信通专属代码~ 上一篇文章: 北邮22信通:(7)实验1 题目四:一元多项式(节省内存版)_青山如…...

Fiddler抓取https史上最强教程
有任何疑问建议观看下面视频 2023最新Fiddler抓包工具实战,2小时精通十年技术!!!对于想抓取HTTPS的测试初学者来说,常用的工具就是fiddler。 但是初学时,大家对于fiddler如何抓取HTTPS难免走歪路ÿ…...

STM32开发基础知识入门
C语言基础 位操作 对基本类型变量可以在位级别进行操作。 1) 不改变其他位的值的状况下,对某几个位进行设值。 先对需要设置的位用&操作符进行清零操作,然后用|操作符设值。 2) 移位操作提高代码的可读性。 3) ~取反操作使用技巧 可用于对某…...

学习操作系统的必备教科书《操作系统:原理与实现》| 文末赠书4本
使用了6年的实时操作系统,是时候梳理一下它的知识点了 摘要: 本文简单介绍了博主学习操作系统的心路历程,同时还给大家总结了一下当下流行的几种实时操作系统,以及在工程中OSAL应该如何设计。希望对大家有所启发和帮助。 文章目录…...
大数据的常用算法(分类、回归分析、聚类、关联规则、神经网络方法、web数据挖掘)
在大数据时代,数据挖掘是最关键的工作。大数据的挖掘是从海量、不完全的、有噪声的、模糊的、随机的大型数据库中发现隐含在其中有价值的、潜在有用的信息和知识的过程,也是一种决策支持过程。其主要基于人工智能,机器学习,模式学…...

【数据结构】详解二叉树与堆与堆排序的关系
🌇个人主页:平凡的小苏 📚学习格言:别人可以拷贝我的模式,但不能拷贝我不断往前的激情 🛸C语言专栏:https://blog.csdn.net/vhhhbb/category_12174730.html 🚀数据结构专栏ÿ…...

【Pandas】数据分析入门
文章目录前言一、Pandas简介1.1 什么是Pandas1.2 Pandas应用二、Series结构2.1 Series简介2.2 基本使用三、DataFrame结构3.1 DataFrame简介3.2 基本使用四、Pandas-CSV4.1 CSV简介4.2 读取CSV文件4.3 数据处理五、数据清洗5.1 数据清洗的方法5.2 清洗案例总结前言 大家好&…...

【c++】:list模拟实现“任意位置插入删除我最强ƪ(˘⌣˘)ʃ“
文章目录 前言一.list的基本功能的使用二.list的模拟实现总结前言 1. list是可以在常数范围内在任意位置进行插入和删除的序列式容器,并且该容器可以前后双向迭代。2. list的底层是双向链表结构,双向链表中每个元素存储在互不相关的独立节点中࿰…...

QT表格控件实例(Table Widget 、Table View)
欢迎小伙伴的点评✨✨,相互学习🚀🚀🚀 博主🧑🧑 本着开源的精神交流Qt开发的经验、将持续更新续章,为社区贡献博主自身的开源精神👩🚀 文章目录前言一、图示实例二、列…...

第二章Vue组件化编程
文章目录模块与组件、模块化与组件化模块组件模块化组件化Vue中的组件含义非单文件组件基本使用组件注意事项使用 kebab-case使用 PascalCase组件的嵌套模板templateVueComponent一个重要的内置功能单文件组件Vue脚手架使用Vue CLI脚手架先配置环境初始化脚手架分析脚手架结构实…...

面试官:vue2和vue3的区别有哪些
目录 多根节点,fragment(碎片) Composition API reactive 函数是用来创建响应式对象 Ref toRef toRefs 去除了管道 v-model的prop 和 event 默认名称会更改 vue2写法 Vue 3写法 vue3组件需要使用v-model时的写法 其他语法 1. 创…...
【TopK问题】——用堆实现
文章目录一、TopK问题是什么二、解决方法三、时间复杂度一、TopK问题是什么 TopK问题就是从1000个数中找出前K个最大的数或者最小的数这样的类似问题。 不过并不要求这k个数字必须是有序的,如果题目有要求,则进行堆排序即可。 还有比如求出全国玩韩信…...

【Spring从成神到升仙系列 四】从源码分析 Spring 事务的来龙去脉
👏作者简介:大家好,我是爱敲代码的小黄,独角兽企业的Java开发工程师,CSDN博客专家,阿里云专家博主📕系列专栏:Java设计模式、数据结构和算法、Kafka从入门到成神、Kafka从成神到升仙…...
使用Nginx反向代理OpenAI API
由于OpenAI的API在国内无法访问,所以可以通过海外服务器利用Nginx实现反向代理。 安装Nginx 这一步就不赘述了,不同的Linux系统安装方式略有不同,根据自己的服务器的系统自行百度即可。 OpenSSL创建证书 因为OpenAI的接口是https协议的&a…...
USB键盘实现——字符串描述符(四)
字符串描述符 字符串描述符内容解析和 HID鼠标 一致。 获取字符串描述符请求 标准设备请求 typedef struct __attribute__ ((packed)){union {struct __attribute__ ((packed)) {uint8_t recipient : 5; ///< Recipient type usb_request_recipient_t.uint8_t type …...

STM32的中断
目录 一、STM32中断概述 二、外部中断控制器EXTI 三、按键中断 四、串口中断 一、STM32中断概述 处理器中的中断在处理器中,中断是一个过程,即CPU在正常执行程序的过程中,遇到外部/内部的紧急事件需要处理,暂时中止当前程序的…...

Flink进阶篇-CDC 原理、实践和优化采集到Doris中
简介 基于doris官方用doris构建实时仓库的思路,从flinkcdc到doris实时数仓的实践。 原文 Apache Flink X Apache Doris 构建极速易用的实时数仓架构 (qq.com) 前提-Flink CDC 原理、实践和优化 CDC 是什么 CDC 是变更数据捕获(Change Data Captur…...

看完这篇 教你玩转渗透测试靶机vulnhub——My File Server: 1
Vulnhub靶机My File Server: 1渗透测试详解Vulnhub靶机介绍:Vulnhub靶机下载:Vulnhub靶机安装:Vulnhub靶机漏洞详解:①:信息收集:②:FTP匿名登入:③:SMB共享服务…...

OpenHarmony实战STM32MP157开发板 “控制” Hi3861开发板 -- 中篇
一、前言 我们在 OpenHarmony实战STM32MP157开发板 “控制” Hi3861开发板 – 上篇 中介绍到了,App面板的开发,以及JS API接口的开发和调用。 那么本篇文章,会详解:BearPi-HM Nano开发板,如何实现数据上报和指令接收响应的。 看到这里,可能有同学可能已经知道思路了,因…...

【数据结构初阶】单链表
目录一、思路>>>>>>>>>>>>过程<<<<<<<<<<<<<<<1.打印2.尾插3.尾删4.头插5.头删6.查找7.指定位置后插入8.指定位置后删除9.链表的销毁二、整个程序1.SLTlist.c2.SLTlist.c一、思路 #define …...

SpringBoot-17-MyBatis动态SQL标签之常用标签
文章目录 1 代码1.1 实体User.java1.2 接口UserMapper.java1.3 映射UserMapper.xml1.3.1 标签if1.3.2 标签if和where1.3.3 标签choose和when和otherwise1.4 UserController.java2 常用动态SQL标签2.1 标签set2.1.1 UserMapper.java2.1.2 UserMapper.xml2.1.3 UserController.ja…...

调用支付宝接口响应40004 SYSTEM_ERROR问题排查
在对接支付宝API的时候,遇到了一些问题,记录一下排查过程。 Body:{"datadigital_fincloud_generalsaas_face_certify_initialize_response":{"msg":"Business Failed","code":"40004","sub_msg…...
java 实现excel文件转pdf | 无水印 | 无限制
文章目录 目录 文章目录 前言 1.项目远程仓库配置 2.pom文件引入相关依赖 3.代码破解 二、Excel转PDF 1.代码实现 2.Aspose.License.xml 授权文件 总结 前言 java处理excel转pdf一直没找到什么好用的免费jar包工具,自己手写的难度,恐怕高级程序员花费一年的事件,也…...

【项目实战】通过多模态+LangGraph实现PPT生成助手
PPT自动生成系统 基于LangGraph的PPT自动生成系统,可以将Markdown文档自动转换为PPT演示文稿。 功能特点 Markdown解析:自动解析Markdown文档结构PPT模板分析:分析PPT模板的布局和风格智能布局决策:匹配内容与合适的PPT布局自动…...

相机从app启动流程
一、流程框架图 二、具体流程分析 1、得到cameralist和对应的静态信息 目录如下: 重点代码分析: 启动相机前,先要通过getCameraIdList获取camera的个数以及id,然后可以通过getCameraCharacteristics获取对应id camera的capabilities(静态信息)进行一些openCamera前的…...
JS设计模式(4):观察者模式
JS设计模式(4):观察者模式 一、引入 在开发中,我们经常会遇到这样的场景:一个对象的状态变化需要自动通知其他对象,比如: 电商平台中,商品库存变化时需要通知所有订阅该商品的用户;新闻网站中࿰…...

Linux 内存管理实战精讲:核心原理与面试常考点全解析
Linux 内存管理实战精讲:核心原理与面试常考点全解析 Linux 内核内存管理是系统设计中最复杂但也最核心的模块之一。它不仅支撑着虚拟内存机制、物理内存分配、进程隔离与资源复用,还直接决定系统运行的性能与稳定性。无论你是嵌入式开发者、内核调试工…...

Kafka入门-生产者
生产者 生产者发送流程: 延迟时间为0ms时,也就意味着每当有数据就会直接发送 异步发送API 异步发送和同步发送的不同在于:异步发送不需要等待结果,同步发送必须等待结果才能进行下一步发送。 普通异步发送 首先导入所需的k…...

【 java 虚拟机知识 第一篇 】
目录 1.内存模型 1.1.JVM内存模型的介绍 1.2.堆和栈的区别 1.3.栈的存储细节 1.4.堆的部分 1.5.程序计数器的作用 1.6.方法区的内容 1.7.字符串池 1.8.引用类型 1.9.内存泄漏与内存溢出 1.10.会出现内存溢出的结构 1.内存模型 1.1.JVM内存模型的介绍 内存模型主要分…...

高考志愿填报管理系统---开发介绍
高考志愿填报管理系统是一款专为教育机构、学校和教师设计的学生信息管理和志愿填报辅助平台。系统基于Django框架开发,采用现代化的Web技术,为教育工作者提供高效、安全、便捷的学生管理解决方案。 ## 📋 系统概述 ### 🎯 系统定…...