实现两个大数的加法运算(使用栈实现)

简介: 实现两个大数的加法运算

1.题目:



实现两个大数的加法运算


2.题目分析:



题目很清晰就是让我们实现一个大数据的加法操作,这个操作需要忽略位数的影响,很显然我们使用java提供的基本数据类型与对应的包装类是不可能完成该操作的,所以需要其他的方法,这里使用栈来解决该问题,可以使用栈来解决该问题的核心就是:两个个字符串类型数据放入两个栈后,无论它门原始是多少位,初始状态栈顶所属的位数都是个位,同时将栈顶出栈后,栈顶又都是十位,依次类推,直到将其中一个栈为空时,他们对应的位数都是一致的。一个栈为空后,较长的栈剩余在栈中的元素则不需要再参与计算,因为剩余的都是高位,我们可以直接继续将他与刚刚计算出来的数据进行拼接即可。下面看下代码实现:


3.代码实现:



笔者使用的栈是自己实现的一个栈,需要的话可以从这里查看:链栈的实现

public class BigNumberAdd {
    public static void main(String[] args) throws Exception{
        System.out.println(add("123456789123456779","123456789123456779123"));
    }
    /**
     * 将两个字符串数字存入到不同的栈中
     * @param numberOne
     * @param numberTwo
     * @return
     * @throws Exception
     */
    public static String add(String numberOne,String numberTwo) throws  Exception{
        if(StringUtil.isEmpty(numberOne)||StringUtil.isEmpty(numberTwo))
            throw new Exception("输入内容不可为空");
        IStack linkedStackOne = new LinkedStack();
        IStack linkedStackTwo = new LinkedStack();
        //将两个字符串类型数据放入到栈中
        for(int i=0;i<numberOne.length();i++){
            linkedStackOne.push(String.valueOf(numberOne.charAt(i)));
        }
        for(int i=0;i<numberTwo.length();i++){
            linkedStackTwo.push(String.valueOf(numberTwo.charAt(i)));
        }
        //调用将两个栈中的数据进行相加,然后返回一个新的栈
        StringBuilder stringBuilder;
        if(linkedStackOne.length()<=linkedStackTwo.length()){
            //较小的先传入
            stringBuilder = popStack(linkedStackOne,linkedStackTwo);
        }else{
            //较小的先传入
            stringBuilder = popStack(linkedStackTwo,linkedStackOne);
        }
        return stringBuilder.toString();
    }
    /**
     * 将两个栈中的栈顶数据相加
     * 栈顶数据他的数据位置一定是一致的,这是可以使用栈来解决该问题的关键
     * @param statckOne
     * @param stackTwo
     * @return
     * @throws Exception
     */
    public static StringBuilder popStack(IStack statckOne,IStack stackTwo) throws Exception{
        IStack iStack = new LinkedStack();
        //谁小遍历谁即可,大的最后加上
        if(statckOne.length()<=stackTwo.length()){
            //标注是否需要进位
            Integer temp = 0;
            while(!statckOne.isEmpty()){
                if(!StringUtil.isEmpty((String)statckOne.peek())){
                    //深度较浅的栈有值
                    Integer intOne = new Integer((String)statckOne.pop());
                    Integer intTwo = new Integer((String)stackTwo.pop());
                    Integer intThree = new Integer(intOne+intTwo+temp);
                    if(intThree>9){
                        temp = 1;
                        iStack.push(String.valueOf(intThree%10));
                    }else{
                        temp = 0;
                    iStack.push(String.valueOf(intThree));
                    }
                }
            }
            //深度较浅的栈无值时,拼接较长的栈与新栈,这样就是相加后的数据
            //判断statckOne栈顶的数据相加后是否进位
            if(temp==1)
                if(!stackTwo.isEmpty()){
                    Integer intFour = new Integer((String)stackTwo.pop());
                    stackTwo.push(String.valueOf(intFour+1));
                    //拼接两个栈:stackTwo、iStack
                    return apend(stackTwo,iStack);
                }else{
                    //说明两个栈相等,进位1直接放进最高位
                    iStack.push(String.valueOf(1));
                    return apend(null,iStack);
                }
            else
                return apend(stackTwo,iStack);
        }else{
            //该部分与上面逻辑相同,无差别,只是将两个数组调换位置
            return null;
        }
    }
    /**
     * 传入的两个栈计算完成后的两个栈。
     * 将两个栈中的数据元素拼接成一个新的字符串
     * @param stackOne
     * @param stackTwo
     * @return
     */
    public static StringBuilder apend(IStack stackOne,IStack stackTwo) throws Exception{
        StringBuilder stringBuilder = new StringBuilder();
        //将stackOne 中剩余的元素加入到stackTwo中
        while(null != stackOne && !stackOne.isEmpty())
            stackTwo.push(stackOne.pop());
        while(null != stackTwo && !stackTwo.isEmpty())
            stringBuilder.append(stackTwo.pop());
        return stringBuilder;
    }
}


上面代码思路还算清晰,第一部分就是将两个字符串数据存入到两个栈中,第二部分则是将这两个栈中的栈顶元素进行计算后出栈,并判断进位的场景,第三部分则是计算完成后,需要对较长的栈与计算完后的栈进行一个数据的合并形成一个新的字符串。这样就完成了大数的求和运算。


4.测试结果:


先来一个较小的数相加的,输出结果如下:


20210426155030767.gif


再来看下计算机计算的结果,如下,我们可以发现并没有不同,计算正确。


20210426155122948.png


再来测试一个较大的数据,笔者选择在12345678前面加上很多的1来测试,测试结果如下:

20210426155357886.gif


笔者输入的两个数都是相同的,所以可以看到计算的结果是没有问题的,其他场景笔者也测试了,这里就不展示了。


5.总结



大数求和,关键点就是怎么实现对应的位置数据可以相加,使用栈来存储,则完美解决了这个问题,每次栈顶的元素对应的位置都是相同的,其他场景的实现就不难了。




相关文章
|
17天前
|
C语言
【数据结构】栈和队列(c语言实现)(附源码)
本文介绍了栈和队列两种数据结构。栈是一种只能在一端进行插入和删除操作的线性表,遵循“先进后出”原则;队列则在一端插入、另一端删除,遵循“先进先出”原则。文章详细讲解了栈和队列的结构定义、方法声明及实现,并提供了完整的代码示例。栈和队列在实际应用中非常广泛,如二叉树的层序遍历和快速排序的非递归实现等。
92 9
|
8天前
|
存储 算法
非递归实现后序遍历时,如何避免栈溢出?
后序遍历的递归实现和非递归实现各有优缺点,在实际应用中需要根据具体的问题需求、二叉树的特点以及性能和空间的限制等因素来选择合适的实现方式。
17 1
|
11天前
|
存储 算法 Java
数据结构的栈
栈作为一种简单而高效的数据结构,在计算机科学和软件开发中有着广泛的应用。通过合理地使用栈,可以有效地解决许多与数据存储和操作相关的问题。
|
14天前
|
开发者
除了交集运算,Set 类型还可以用于哪些数据结构的操作?
【10月更文挑战第30天】`Set`类型在数据结构操作方面提供了丰富的功能和便利,能够帮助开发者更高效地处理各种数据集合相关的任务,提高代码的简洁性和性能。
|
14天前
|
存储 JavaScript 前端开发
执行上下文和执行栈
执行上下文是JavaScript运行代码时的环境,每个执行上下文都有自己的变量对象、作用域链和this值。执行栈用于管理函数调用,每当调用一个函数,就会在栈中添加一个新的执行上下文。
|
16天前
|
存储
系统调用处理程序在内核栈中保存了哪些上下文信息?
【10月更文挑战第29天】系统调用处理程序在内核栈中保存的这些上下文信息对于保证系统调用的正确执行和用户程序的正常恢复至关重要。通过准确地保存和恢复这些信息,操作系统能够实现用户模式和内核模式之间的无缝切换,为用户程序提供稳定、可靠的系统服务。
44 4
|
1月前
|
算法 程序员 索引
数据结构与算法学习七:栈、数组模拟栈、单链表模拟栈、栈应用实例 实现 综合计算器
栈的基本概念、应用场景以及如何使用数组和单链表模拟栈,并展示了如何利用栈和中缀表达式实现一个综合计算器。
31 1
数据结构与算法学习七:栈、数组模拟栈、单链表模拟栈、栈应用实例 实现 综合计算器
|
20天前
|
算法 安全 NoSQL
2024重生之回溯数据结构与算法系列学习之栈和队列精题汇总(10)【无论是王道考研人还是IKUN都能包会的;不然别给我家鸽鸽丢脸好嘛?】
数据结构王道第3章之IKUN和I原达人之数据结构与算法系列学习栈与队列精题详解、数据结构、C++、排序算法、java、动态规划你个小黑子;这都学不会;能不能不要给我家鸽鸽丢脸啊~除了会黑我家鸽鸽还会干嘛?!!!
|
1月前
初步认识栈和队列
初步认识栈和队列
60 10
|
1月前
数据结构(栈与列队)
数据结构(栈与列队)
18 1