栈解决大数加法问题(Java实现)

*文中内容来源于《数据结构 --Java语言描述》(第二版) 刘小晶 杜选 主编
*此系列文章作为学习记录,若文中内容有误,请大家指出,谢谢

整数是有最大上限的。所谓大数就是超过整数最大上限的数。为解决两个大数的求和问题,可以将两个大数当成数字字符串,将这些数的相应数字存储在两个堆栈中,并从两个栈中弹出相应位的数字依次执行加法即可求解。

//求两个大数的和,加数和被加数以字符串的形式输入(允许大数中出现空格)
//计算的结果也以字符串的形式返回

/**
 * 对于两个大数的加法,操作步骤如下:
 * (1)将两个加数的相应位从高位到低位依次压入栈sA和sB中;
 * (2)若两个加数栈都非空,则依次从栈中弹出栈顶数字相加,并存入变量partialSum中;
 * 若和有进位,则将和的个数压入结果栈sum中,并将进位数加到下一位数字相加的和中;
 * 若和没有进位,则直接将和压入结果栈sum中;
 * (3)若某个加数堆栈为空,则将非空加数栈中的栈顶数字依次弹出与进位相加,
 * 和的个数压入结果栈sum中,直到此栈为空为止。若最高位有进位,则最后将1压入栈sum中;
 * (4)若两个加数栈都为空,则栈sum中保存的就是计算结果。注意栈顶是结果的最高为数字。
 */
public class Example3_2 {
    public String add(String a, String b) throws Exception{
        LinkStack sum = new LinkStack();    //大数的和
        LinkStack sA = numSplit(a);         //加数字符串以单个字符的形式放入栈中
        LinkStack sB = numSplit(b);         //被加数字符串以单个字符的形式放入栈中
        int partialSum;                     //对于两个位的求和
        boolean isCarry = false;            //进位标示
        while(! sA.isEmpty() && !sB.isEmpty()){    //加数和被加数栈同时为空
            partialSum = (Integer)sA.pop() + (Integer)sB.pop();  //对于两个位求和,并在栈中去除加数和被加数中的该位
            if (isCarry){                   //低位进位
                partialSum++;               //进位加到此位上
                isCarry = false;            //重置进位标示
            }
            if (partialSum >= 10){          //需要进位
                partialSum -= 10;
                sum.push(partialSum);
                isCarry = true;             //标示进位
            }
            else {                          //位和不需要进位
                sum.push(partialSum);       //和放入栈中
            }
        }

        LinkStack temp = !sA.isEmpty() ? sA: sB;    //引用指向加数和被加数中非空栈
        while(!temp.isEmpty()){
            if (isCarry){                           //最后一次执行加法运算中需要进位
                int t = (Integer)temp.pop();        //取出加数或被加数没有参加的位
                ++t;    //进位加到此位上
                if (t >= 10){                       //需要进位
                    t -= 10;
                    sum.push(t);
                }
                else {
                    sum.push(t);
                    isCarry = false;                 //重置进位标示
                }
            }
            else    //最后一次执行加法运算中不需要进位
                sum.push(temp.pop());    //把加数或被加数中非空的值放入和中
        }
        if (isCarry){     //最高位需要进位
            sum.push(1);    //进位放入栈中
        }
        String str = new String();
        while(!sum.isEmpty())    //把栈中元素转化称字符串
            str = str.concat(sum.pop().toString());
        return str;
    }

    //字符串以单个字符的形式放入栈中,并去除字符串中空格,返回以单个字符为元素的栈
    public LinkStack numSplit(String str) throws Exception{
        LinkStack s = new LinkStack();
        for (int i = 0; i < str.length(); i++){
            char c = str.charAt(i);    //指定索引处的char值
            if (' ' == c)
                continue;
            else if ('0' <= c && '9' >= c)    //数字放在栈中
                s.push(Integer.valueOf(String.valueOf(c)));
            else
                throw new Exception("错误:输入了非数字型字符!");
        }
        return s;
    }
    public static void main(String[] args) throws Exception{
        Example3_2 e = new Example3_2();
        System.out.println("两个大数的和为:" + e.add("18 452 543 389 943 209 752 345 473", "8 123 542 678 432 986 899 334"));
    }
}

关于顺序栈的相关代码,都在 这篇文章里了。

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是使用Java数据结构实现大数加法的代码: ``` import java.util.Stack; public class LargeNumberAddition { public static String add(String num1, String num2) { Stack<Integer> stack1 = new Stack<>(); Stack<Integer> stack2 = new Stack<>(); Stack<Integer> resultStack = new Stack<>(); for (int i = 0; i < num1.length(); i++) { stack1.push(num1.charAt(i) - '0'); } for (int i = 0; i < num2.length(); i++) { stack2.push(num2.charAt(i) - '0'); } int carry = 0; while (!stack1.isEmpty() || !stack2.isEmpty()) { int sum = carry; if (!stack1.isEmpty()) { sum += stack1.pop(); } if (!stack2.isEmpty()) { sum += stack2.pop(); } resultStack.push(sum % 10); carry = sum / 10; } if (carry != 0) { resultStack.push(carry); } StringBuilder sb = new StringBuilder(); while (!resultStack.isEmpty()) { sb.append(resultStack.pop()); } return sb.toString(); } public static void main(String[] args) { String num1 = "123456789"; String num2 = "987654321"; String sum = add(num1, num2); System.out.println(num1 + " + " + num2 + " = " + sum); } } ``` 在这个实现中,我们首先将两个大数转化为,然后从顶开始逐位相加。由于我们不能直接对字符串进行加法运算,所以我们需要将每个字符转化为数字。我们使用ASCII码将字符转化为数字,例如'0'的ASCII码是48,所以'0'-'0'的结果是0。 我们使用一个carry变量来记录进位,初始值为0。在每次相加时,我们将carry加上顶元素,如果非空,则将顶元素弹出并加到sum中。我们将sum % 10的结果压入结果中,并将sum / 10的结果赋给carry。最后,如果carry不为0,则将其压入结果中。 最后,我们使用StringBuilder将结果中的数字拼接起来,形成最终结果。在本例中,输出结果为: 123456789 + 987654321 = 1111111110

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值