Exercise data structure Review-- linear table (large integer multiplication)

 

Topic Source: China University of MOOC - "Data Structures and Algorithms" Peking University - Chapter II linear programming assignments table

2, a large integer multiplication (10 minutes)

Title Contents:

Product of the sum of two non-negative integers less than 200 bits.

Input format: There are two lines, each not more than 200 is a non-negative integer, no extra leading zero.

Output format: one line, i.e., the multiplied result. The results can not have extra leading 0, that is, if the result is 342, you can not output to 0342.

Sample input:

12345678900

98765432100

Sample output:

1219326311126352690000

Time limit: 500ms Memory Limit: 32000kb

Thinking: single linked list for data storage, large integers stored as a singly linked list, as will be stored as 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;
}

 

Guess you like

Origin blog.csdn.net/kingslave1/article/details/93708870