Introduction
In this article, we will understand the Doubly Linked List with the example, and perform large arithmetic operations using the doubly linked list. A doubly linked list is a data structure containing a set of sequentially linked data called nodes. Each node is divided into two link fields(points to the next or previously linked nodes) and one data field.
Doubly linked list
Problem statement
We are given two very large numbers in the form of strings and we have to use different arithmetic operators on these strings using a doubly-linked list.
Sample Examples
Input
M: 1234
N: 23456
Output
Product: 289564320
Sum: 35801
Difference(m-n): 88889
Modulus: 12345
Quotient: 0
Input
M: 897
N: 876
Output
Product: 785772
Sum: 1773
Difference(m-n): 021
Modulus: 021
Quotient: 1
In the above examples, we are finding the arithmetic values using a doubly-linked list.
Recommended Topic, Floyds Algorithm and Rabin Karp Algorithm
Approach
In the given problem, we will first insert the large numeric value in the form of a string. Then we will make a doubly linked list by extracting the char at each index. After we have formed the doubly linked list, we will pass the list to different functions like addition, subtraction, multiplication, and division in which we are doing the operations respectively.
After that when all the operations are done then we will simply print the addition, subtraction, multiplication, division, etc. of the strings s1 and s2.
Pseudocode
// a is the first string and b is the second string
// addition function
while (a1->end != NULL || b1->end != NULL)
{
if (a1->end != NULL && b1->end == NULL)
{
s = ((a1->end->info) + c) % 10;
c = ((a1->end->info) + c) / 10;
a1->end = a1->end->prevnode;
}
else if (a1->end == NULL && b1->end != NULL)
{
s = ((b1->end->info) + c) % 10;
c = ((b1->end->info) + c) / 10;
b1->end = b1->end->prevnode;
}
else if (a1->end != NULL && b1->end != NULL)
{
s = ((a1->end->info) + (b1->end->info) + c) % 10;
c = ((a1->end->info) + (b1->end->info) + c) / 10;
a1->end = a1->end->prevnode;
b1->end = b1->end->prevnode;
}
}
// subtraction function
while (a1->end != NULL || b1->end != NULL)
{
if (a1->end != NULL && b1->end != NULL)
{
if ((a1->end->info) + c < (b1->end->info))
{
s = ((a1->end->info) + c + 10 - (b1->end->info));
c = -1;
}
else if((a1->end->info) + c >=(b1->end->info))
{
s = ((a1->end->info) + c - (b1->end->info));
c = 0;
}
a1->end = a1->end->prevnode;
b1->end = b1->end->prevnode;
}
else if (a1->end != NULL && b1->end == NULL)
{
if (a1->end->info < 1)
{
if (c = 0)
{
s = a1->end->info;
}
else{
s = ((a1->end->info) + 10 + c);
c = -1;
}
}
else if(a1->end->info>=1)
{
s = ((a1->end->info) + c);
c = 0;
}
a1->end = a1->end->prevnode;
}
}
we can perform division, addition, multiplication and subtraction in this way.
Implementation in C++
#include <iostream>
#include<cstdio>
using namespace std;
// Doubly Linked List structure
struct Node
{
int info;
struct Node* nextnode;
struct Node* prevnode;
// constructor
Node(int val)
{
info = val;
nextnode = prevnode = NULL;
}
};
class hugeIntegerlinkedlist
{
public:
hugeIntegerlinkedlist()
{
front = end = NULL;
size = 0;
}
~hugeIntegerlinkedlist();
// insertion of a digit in front of a doubly linked list
void insertioninfront(int data)
{
Node* temp = new Node(data);
if (front != NULL)
{ front->prevnode = temp;
temp->nextnode = front;
front = temp;
}
else
{
front = end = temp;
}
size++;
}
// insertion of a digit in the end of a doubly linked list
void insertioninend(int data)
{
Node* temp = new Node(data);
if (end!= NULL)
{ end->nextnode = temp;
temp->prevnode = end;
end = temp;
}
else
{
front = end = temp;
}
size++;
}
// printing the doubly linked list data
void displaydata()
{
Node* temp = front;
while (temp != NULL)
{
cout << temp->info;
temp = temp->nextnode;
}
}
int length()
{
return size;
}
void mul(hugeIntegerlinkedlist*, hugeIntegerlinkedlist*);
void dif(hugeIntegerlinkedlist*, hugeIntegerlinkedlist*);
void add(hugeIntegerlinkedlist*, hugeIntegerlinkedlist*);
int cmp(hugeIntegerlinkedlist*, hugeIntegerlinkedlist*);
void quo(hugeIntegerlinkedlist*, hugeIntegerlinkedlist*);
Node* end;
Node* front;
int size;
};
// function to add the numbers
void hugeIntegerlinkedlist::add(hugeIntegerlinkedlist* a, hugeIntegerlinkedlist* b)
{
int c = 0, s;
hugeIntegerlinkedlist* a1 = new hugeIntegerlinkedlist(*a);
hugeIntegerlinkedlist* b1 = new hugeIntegerlinkedlist(*b);
this->front = NULL;
this->end = NULL;
this->size = 0;
while (a1->end != NULL || b1->end != NULL)
{
if (a1->end != NULL && b1->end == NULL)
{
s = ((a1->end->info) + c) % 10;
c = ((a1->end->info) + c) / 10;
a1->end = a1->end->prevnode;
}
else if (a1->end == NULL && b1->end != NULL)
{
s = ((b1->end->info) + c) % 10;
c = ((b1->end->info) + c) / 10;
b1->end = b1->end->prevnode;
}
else if (a1->end != NULL && b1->end != NULL)
{
s = ((a1->end->info) + (b1->end->info) + c) % 10;
c = ((a1->end->info) + (b1->end->info) + c) / 10;
a1->end = a1->end->prevnode;
b1->end = b1->end->prevnode;
}
insertioninfront(s);
}
if (c != 0)
insertioninfront(c);
}
// subtraction function
void hugeIntegerlinkedlist::dif(hugeIntegerlinkedlist* a, hugeIntegerlinkedlist* b)
{
int c = 0, s;
hugeIntegerlinkedlist* a1 = new hugeIntegerlinkedlist(*a);
hugeIntegerlinkedlist* b1 = new hugeIntegerlinkedlist(*b);
this->front = NULL;
this->end = NULL;
this->size = 0;
while (a1->end != NULL || b1->end != NULL)
{
if (a1->end != NULL && b1->end != NULL)
{
if ((a1->end->info) + c < (b1->end->info))
{
s = ((a1->end->info) + c + 10 - (b1->end->info));
c = -1;
}
else if((a1->end->info) + c >=(b1->end->info))
{
s = ((a1->end->info) + c - (b1->end->info));
c = 0;
}
a1->end = a1->end->prevnode;
b1->end = b1->end->prevnode;
}
else if (a1->end != NULL && b1->end == NULL)
{
if (a1->end->info < 1)
{
if (c = 0)
{
s = a1->end->info;
}
else
s = ((a1->end->info) + 10 + c);
c = -1;
}
else if(a1->end->info>=1)
{
s = ((a1->end->info) + c);
c = 0;
}
a1->end = a1->end->prevnode;
}
insertioninfront(s);
}
}
// compares two numbers and then return 1
int hugeIntegerlinkedlist::cmp(hugeIntegerlinkedlist* a, hugeIntegerlinkedlist* b)
{
if (a->size != b->size)
return ((a->size > b->size) ? 1 : 0);
hugeIntegerlinkedlist* a1 = new hugeIntegerlinkedlist(*a);
hugeIntegerlinkedlist* b1 = new hugeIntegerlinkedlist(*b);
while (a1->front != NULL && b1->front != NULL)
{
if (a1->front->info < b1->front->info)
return 0;
else if (a1->front->info > b1->front->info)
return 1;
else
{
a1->front = a1->front->nextnode;
b1->front = b1->front->nextnode;
}
}
return 2;
}
// Returns the quotient by doing the division of two numbers
void hugeIntegerlinkedlist::quo(hugeIntegerlinkedlist* a, hugeIntegerlinkedlist* b)
{
hugeIntegerlinkedlist* a1 = new hugeIntegerlinkedlist(*a);
hugeIntegerlinkedlist* b1 = new hugeIntegerlinkedlist(*b);
hugeIntegerlinkedlist* ex = new hugeIntegerlinkedlist();
hugeIntegerlinkedlist* mp = new hugeIntegerlinkedlist();
hugeIntegerlinkedlist* pr = new hugeIntegerlinkedlist();
int i = 0;
for (i = 0; i < b1->size; i++)
{
ex->insertioninend(a1->front->info);
a1->front = a1->front->nextnode;
}
for (i = 0; i < 10; i++)
{
hugeIntegerlinkedlist* b2 = new hugeIntegerlinkedlist(*b);
mp->insertioninend(i);
pr->mul(b2, mp);
if (!cmp(ex, pr))
break;
mp->front = mp->end = NULL;
pr->front = pr->end = NULL;
mp->size = pr->size = 0;
}
mp->front = mp->end = NULL;
pr->front = pr->end = NULL;
mp->size = pr->size = 0;
mp->insertioninend(i - 1);
pr->mul(b1, mp);
ex->dif(ex, pr);
insertioninend(i - 1);
mp->front = mp->end = NULL;
pr->front = pr->end = NULL;
mp->size = pr->size = 0;
while (a1->front != NULL)
{
ex->insertioninend(a1->front->info);
while (ex->front->info == 0)
{
ex->front = ex->front->nextnode;
ex->size--;
}
for (i = 0; i < 10; i++)
{
hugeIntegerlinkedlist* b2 = new hugeIntegerlinkedlist(*b);
mp->insertioninend(i);
pr->mul(b2, mp);
if (!cmp(ex, pr))
break;
mp->front = mp->end = NULL;
pr->front = pr->end = NULL;
mp->size = pr->size = 0;
}
mp->front = mp->end = NULL;
pr->front = pr->end = NULL;
mp->size = pr->size = 0;
mp->insertioninend(i - 1);
pr->mul(b1, mp);
ex->dif(ex, pr);
insertioninend(i - 1);
mp->front = mp->end = NULL;
pr->front = pr->end = NULL;
mp->size = pr->size = 0;
a1->front = a1->front->nextnode;
}
cout<< "\nModulus : ";
ex->displaydata();
}
// multiplication function
void hugeIntegerlinkedlist::mul(hugeIntegerlinkedlist* a, hugeIntegerlinkedlist* b)
{
int k = 0, i;
hugeIntegerlinkedlist* tpro = new hugeIntegerlinkedlist();
while (b->end != NULL)
{
int c = 0, s = 0;
hugeIntegerlinkedlist* temp = new hugeIntegerlinkedlist(*a);
hugeIntegerlinkedlist* pro = new hugeIntegerlinkedlist();
while (temp->end != NULL)
{
s = ((temp->end->info) * (b->end->info) + c) % 10;
c = ((temp->end->info) * (b->end->info) + c) / 10;
pro->insertioninfront(s);
temp->end = temp->end->prevnode;
}
if (c != 0)
pro->insertioninfront(c);
for (i = 0; i < k; i++)
pro->insertioninend(0);
add(this, pro);
k++;
b->end = b->end->prevnode;
pro->front = pro->end = NULL;
pro->size = 0;
}
}
// main function
int main()
{
hugeIntegerlinkedlist* m = new hugeIntegerlinkedlist();
hugeIntegerlinkedlist* n = new hugeIntegerlinkedlist();
hugeIntegerlinkedlist* s = new hugeIntegerlinkedlist();
hugeIntegerlinkedlist* p = new hugeIntegerlinkedlist();
hugeIntegerlinkedlist* d = new hugeIntegerlinkedlist();
hugeIntegerlinkedlist* q = new hugeIntegerlinkedlist();
string s1,s2;
cout<<"enter the string s1 ";
getline (cin, s1);
cout<<"enter the string s2 ";
getline (cin,s2);
for (int i = 0; i < s1.length(); i++)
m->insertioninend(s1.at(i) - '0');
for (int i = 0; i < s2.length(); i++)
n->insertioninend(s2.at(i) - '0');
hugeIntegerlinkedlist* m1 = new hugeIntegerlinkedlist(*m);
hugeIntegerlinkedlist* n1 = new hugeIntegerlinkedlist(*n);
hugeIntegerlinkedlist* m2 = new hugeIntegerlinkedlist(*m);
hugeIntegerlinkedlist* n2 = new hugeIntegerlinkedlist(*n);
hugeIntegerlinkedlist* m3 = new hugeIntegerlinkedlist(*m);
hugeIntegerlinkedlist* n3 = new hugeIntegerlinkedlist(*n);
cout << "Product : ";
s->mul(m, n);
s->displaydata();
cout << endl;
cout << "Sum : ";
p->add(m1, n1);
p->displaydata();
cout << endl;
cout << "Difference (m-n) : m>n: ";
d->dif(m2, n2);
d->displaydata();
q->quo(m3, n3);
cout << endl;
cout << "Quotient : ";
q->displaydata();
return 0;
}
Output
Complexity analysis
Time complexity
Since we are using one for loop to traverse the linked list of N nodes multiple times therefore the time complexity would be O(N).
Space complexity
O(1), will be the space complexity as we have not used any extra space.