1. Introduction
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.
2. Represent a Polynomial with a Linked List
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.
3. Add Two Polynomials
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:
- ‘s power is greater than ‘s power: In this case, we append a new node with ‘s power and coefficient. Also, we move to the next node.
- ‘s power is greater than ‘s power: In this case, we append a new node with ‘s power and coefficient. Also, we move to the next node.
- and have the same power: In this case, the new coefficient is the total of ‘s coefficient and ‘s coefficient. If the new coefficient is not , we append a new node with the same power and the new coefficient. Also, we move both and to the next nodes.
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.
4. Multiply Two 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 .
5. Conclusion
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.