数据结构Review——线性表练习(大整数乘法)

题目来源:中国大学MOOC - 北京大学《数据结构与算法》- 第二章 线性表编程作业

2、大整数乘法(10分)

题目内容:

求两个不超过200位的非负整数的积。

输入格式:有两行,每行是一个不超过200位的非负整数,没有多余的前导0。

输出格式:一行,即相乘后的结果。结果里不能有多余的前导0,即如果结果是342,那么就不能输出为0342。

输入样例:

12345678900

98765432100

输出样例:

1219326311126352690000

时间限制:500ms内存限制:32000kb

思路:采用单链表进行数据存储,将大整数存为单链表,如将123456789存储为head->9->8->7->6->5->4->3->2->1->NULL

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>

using namespace std;

//定义大数链表节点
typedef struct Node
{
    char num;
    struct Node *next;

    Node()
    {
        num = 0;
        next = NULL;
    }
    Node(const char n)
    {
        num = n;
        next = NULL;
    }
} Node;

//定义大整数类
//此类中如123456789存储为head->9->8->7->6->5->4->3->2->1->NULL
class BigInteger
{
private:
    Node *head;
    int len;
    /**
     * 供内部调用的显示大数的方法
     * 也可作为如何倒叙输出单链表的解法,采用递归调用形式,先递归显示后继节点,再显示当前节点,终止条件为p==NULL
     */
    void show(Node *p)
    {
        if (p == NULL)
        {
            return;
        }
        else
        {
            show(p->next);
            cout << p->num;
        }
    }

public:
    //无参构造函数
    BigInteger()
    {
        head = new Node();
        len = 0;
    }
    
    //将大数字符串转化为BigInteger对象,将每一个字符存在单链表中
    BigInteger(char *str)
    {
        Node *p = NULL;
        head = new Node();
        p = head;
        for (int i = strlen(str) - 1; i >= 0; i--)
        {
            Node *node = new Node(str[i]);
            p->next = node;
            p = p->next;
            len++;
        }
    }
    
    //拷贝构造函数
    BigInteger(const BigInteger &bi)
    {
        Node *p = NULL;
        head = new Node();
        p = head;
        Node *p2 = bi.head->next;
        while (p2 != NULL)
        {
            Node *node = new Node(p2->num);
            p->next = node;
            p = p->next;
            p2 = p2->next;
        }
        len = bi.len;
    }
    
    BigInteger(const BigInteger *bi)
    {
        Node *p = NULL;
        head = new Node();
        p = head;
        Node *p2 = bi->head->next;
        while (p2 != NULL)
        {
            Node *node = new Node(p2->num);
            p->next = node;
            p = p->next;
            p2 = p2->next;
        }
        len = bi->len;
    }
    
    //在head节点之后插入字符,即将原大数*10再加上字符c
    bool prepend(char c)
    {
        Node *node = new Node(c);
        node->next = head->next;
        head->next = node;
        len++;
        return true;
    }
    //在最后一个节点后追加字符
    bool append(char c)
    {
        Node *p = head;
        while (p->next != NULL)
        {
            p = p->next;
        }
        Node *node = new Node(c);
        p->next = node;
        len++;

        return true;
    }
    
    //大整数加法
    BigInteger *add(const BigInteger &bi1) const
    {
        int carry = 0;
        Node *p1 = head->next;
        Node *p2 = bi1.head->next;
        int bit = 0;
        BigInteger *res = new BigInteger();
        while (p1 != NULL && p2 != NULL)
        {
            bit = p1->num - '0' + p2->num - '0' + carry;
            carry = bit / 10;
            bit -= carry * 10;
            res->append(bit + '0');

            p1 = p1->next;
            p2 = p2->next;
        }

        if (p1 != NULL)
        {
            while (p1 != NULL)
            {
                bit = p1->num - '0' + carry;
                carry = bit / 10;
                bit -= carry * 10;
                res->append(bit + '0');
                p1 = p1->next;
            }
        }
        if (p2 != NULL)
        {
            while (p2 != NULL)
            {
                bit = p2->num - '0' + carry;
                carry = bit / 10;
                bit -= carry * 10;
                res->append(bit + '0');
                p2 = p2->next;
            }
        }

        if (carry > 0)
        {
            res->append(carry + '0');
        }

        return res;
    }
    
    //大整数乘以一个个位数
    BigInteger *multiply(char c) const
    {
        int fac = c - '0';
        int carry = 0;
        int temp = 0;
        BigInteger *res = new BigInteger();
        Node *p = head->next;
        while (p != NULL)
        {
            temp = (p->num - '0') * fac + carry;
            carry = temp / 10;
            temp -= carry * 10;

            res->append(temp + '0');
            p = p->next;
        }
        if (carry > 0)
        {
            res->append(carry + '0');
        }
        return res;
    }
    //大数乘大数,思路为:按照手算时竖式的算法,将第二个乘数的每一位数字从个位开始依次与
    //第一个乘数相乘,注意第二个乘数每前进一位,第一个乘数就应该*10,即调用prepend('0')
    //方法,将每一次相乘结果加起来即为所求结果。
    BigInteger *multiply(const BigInteger &bi1) const
    {
        BigInteger *res = new BigInteger("0");
        BigInteger *temp = new BigInteger(*this);
        Node *p1 = bi1.head->next;
        while (p1 != NULL)
        {
            BigInteger *tmp = temp->multiply(p1->num);
            res = res->add(*tmp);
            temp->prepend('0');
            p1 = p1->next;
        }
        return res;
    }
    //供外部调用的显示大数的方法
    void show()
    {
        show(head->next);
    }
};
const int MAX_LEN = 201;
void solution();

int main()
{
    int T = 0;
    int t = 0;

    T = 1;
    while (t < T)
    {
        solution();
        t++;
    }

    system("pause");
    return 0;
}

void solution()
{
    char num1[MAX_LEN], num2[MAX_LEN];
    BigInteger *bi1 = NULL;
    BigInteger *bi2 = NULL;
    cin >> num1 >> num2;
    bi1 = new BigInteger(num1);
    bi2 = new BigInteger(num2);

    bi1->multiply(bi2)->show();
    cout << endl;
}

猜你喜欢

转载自blog.csdn.net/kingslave1/article/details/93708870