
Learn through the super-clean Baeldung Pro experience:
>> Membership and Baeldung Pro.
No ads, dark-mode and 6 months free of IntelliJ Idea Ultimate to start with.
Last updated: March 18, 2024
In mathematics, a polynomial is an expression that contains a sum of powers in one or more variables multiplied by coefficients. A polynomial in one variable, , with constant coefficients is like:
. We call each item, e.g.,
, a term. If two terms have the same power, we call them like terms.
In this tutorial, we’ll show how to add and multiply two polynomials using a linked list data structure.
We can use a linked list to represent a polynomial. In the linked list, each node has two data fields: coefficient and power. Therefore, each node represents a term of a polynomial. For example, we can represent the polynomial with a linked list:
We can sort a linked list in time, where
is the total number of the linked list nodes. In this tutorial, we’ll assume the linked list is ordered by the power for the simplicity of our algorithms.
To add two polynomials, we can add the coefficients of like terms and generate a new linked list for the resulting polynomial. For example, we can use two liked lists to represent polynomials and
:
When we add them together, we can group the like terms and generate the result :
Since both linked list are ordered by the power, we can use a two-pointer method to merge the two sorted linked list:
algorithm PolynomialAdd(head1, head2):
// INPUT
// head1 = Head pointer of the first polynomial linked list
// head2 = Head pointer of the second polynomial linked list
// OUTPUT
// Head pointer of the new polynomial linked list representing the sum
head <- tail <- null
p1 <- head1
p2 <- head2
while p1 != null and p2 != null:
if p1.power > p2.power:
tail <- append(tail, p1.power, p1.coefficient)
p1 <- p1.next
else if p2.power > p1.power:
tail <- append(tail, p2.power, p2.coefficient)
p2 <- p2.next
else:
coefficient <- p1.coefficient + p2.coefficient
if coefficient != 0:
tail <- append(tail, p1.power, coefficient)
p1 <- p1.next
p2 <- p2.next
if head is null:
head <- tail
while p1 != null:
tail <- append(tail, p1.power, p1.coefficient)
p1 <- p1.next
while p2 != null:
tail <- append(tail, p2.power, p2.coefficient)
p2 <- p2.next
return head
In this algorithm, we first create two pointers, and
, to the head pointers of the two input polynomials. Then, we generate the new polynomial nodes based on the powers of these two pointers. There are three cases:
After that, we continue to append the remaining nodes from or
until we finish the calculation on all nodes.
The function can create a new linked list node based on the input
and
. Also, it appends the new node to the
node and returns the new
node:
algorithm Append(tail, power, coefficient):
// INPUT
// tail = The last node of the current polynomial linked list
// power = The power of the new term to append
// coefficient = The coefficient of the new term to append
// OUTPUT
// The new tail node after appending the new term
new_node <- create a new node with power and coefficient
if tail != null:
tail.next <- new_node
return new node
This algorithm traverses each linked list node only once. Therefore, the overall running time is , where
and
are the number of terms for the two input polynomials.
To multiply two polynomials, we can first multiply each term of one polynomial to the other polynomial. Suppose the two polynomials have and
terms. This process will create a polynomial with
terms.
For example, after we multiply and
, we can get a linked list:
This linked list contains all terms we need to generate the final result. However, it is not sorted by the powers. Also, it contains duplicate nodes with like terms. To generate the final linked list, we can first merge sort the linked list based on each node’s power:
After the sorting, the like term nodes are grouped together. Then, we can merge each group of like terms and get the final multiplication result:
We can describe these steps with an algorithm:
algorithm PolynomialMultiply(head1, head2):
// INPUT
// head1 = Head pointer of the first polynomial linked list
// head2 = Head pointer of the second polynomial linked list
// OUTPUT
// Head pointer of the new polynomial linked list representing the product
head <- null
tail <- null
p1 <- head1
while p1 != null:
p2 <- head2
while p2 != null:
power <- p1.power + p2.power
coefficient <- p1.coefficient * p2.coefficient
tail <- append(tail, power, coefficient)
if head is null:
head <- tail
p2 <- p2.next
p1 <- p1.next
head <- mergesort(head)
mergeLikeTerms(head)
return head
In this algorithm, we first use a nested loop to multiply all term pairs from the two polynomials. This takes
time, where
and
are the number of terms for the two input polynomials. Also, this process creates a linked list with
nodes.
Then, we merge sort the linked list based on each node’s power. This process takes time.
After we sort the linked list, we can use a two-pointer approach to merge the like terms:
algorithm MergeLikeTerms(head):
// INPUT
// head = Head pointer of the polynomial linked list
// OUTPUT
// Modify the linked list in place by merging like terms
prev <- null
p1 <- head
while p1 != null:
p2 <- p1.next
while p2 != null and p2.power = p1.power:
p1.coefficient <- p1.coefficient + p2.coefficient
p2 <- p2.next
p1.next <- p2
if p1.coefficient = 0 and prev != null:
prev.next <- p2
else:
prev <- p1
p1 <- p2
In this approach, we use one pointer as the start of a like term group and use another pointer to traverse the like terms in the same group. Each time we find a like term, we add its coefficient to the start like term node. Once we finish one like term group, we move the start pointer to the next group and repeat the same process to merge like terms. The running time of this process is as we need to visit
nodes.
Overall, the running time is .
In this tutorial, we showed how to represent a polynomial with the linked list data structure. Also, we showed two algorithms to add and multiply two linked list representations of polynomials.