Data Structures, Algorithms, & Applications in Java
Chapter 6, Exercise 67
The code is given below.
package applications;
import utilities.*;
import exceptions.*;
public class CircularPolynomial
{
// top-level class
private static class PolyNode
{
// data members
int coeff; // coefficient
int exp; // exponent
PolyNode next; // pointer to next node
// constructors
PolyNode(int theCoeff, int theExp, PolyNode theNext)
{
coeff = theCoeff;
exp = theExp;
next = theNext;
}
PolyNode(int theCoeff, int theExp)
{
coeff = theCoeff;
exp = theExp;
}
PolyNode() {}
}
// data members of CircularPolynomial
PolyNode headNode;
static PolyNode lastNode;
// constructors
/** create the zero polynomial */
public CircularPolynomial()
{
headNode = new PolyNode(0, -1);
headNode.next = headNode;
}
/** @return polynomial degree */
public int degree()
{
if (headNode.next == headNode) // zero polynomial
return 0;
else // nonzero polynomial
return headNode.next.exp;
}
/** add a new term to the end of the list */
private void append(int theCoeff, int theExp)
{
lastNode.next = new PolyNode(theCoeff, theExp);
lastNode = lastNode.next;
}
/** make a clone */
public Object clone()
{
// w will be the clone
CircularPolynomial w = new CircularPolynomial();
lastNode = w.headNode;
// use currentNode to march through the polynomial this
PolyNode currentNode = headNode.next;
while (currentNode != headNode)
{
append(currentNode.coeff, currentNode.exp);
currentNode = currentNode.next;
}
// close circular list
lastNode.next = w.headNode;
return w;
}
/** input the polynomial from the standard input stream */
public void input(MyInputStream inStream)
{
lastNode = headNode; // use old head node
// input number of terms
System.out.println("Enter the number of nonzero terms");
int terms = inStream.readInteger();
if (terms < 0)
throw new MyInputException
("number of terms must be >= 0, it is " + terms);
if (terms > 0)
{// at least one nonzero term, input the nonzero terms
// in decreasing order of exponents
System.out.println("Enter the nonzero terms "
+ "in decreasing order of exponents.\n"
+ "Give input as a sequence e_1, c_1, e_2, c_2, ..."
);
// get first term
int exponent = inStream.readInteger();
int coefficient = inStream.readInteger();
// exponent must be >= 0 and coefficient must be nonzero
if (exponent < 0 || coefficient == 0)
throw new MyInputException
("exponent must be >= 0 and coefficient must " +
"not equal 0, they are exponent = " + exponent +
" coefficient = " + coefficient);
append(coefficient, exponent);
int lastExponent = exponent;
// get the remaining terms
for (int i = 2; i <= terms; i++)
{// get next term
exponent = inStream.readInteger();
coefficient = inStream.readInteger();
// exponent must be > lastExponent and coefficient must be nonzero
if (exponent >= lastExponent || coefficient == 0)
throw new MyInputException
("exponents must be in descending order " +
"and coefficients must not equal 0");
append(coefficient, exponent);
lastExponent = exponent;
}
}
// complete circular linkage
lastNode.next = headNode;
}
/** output the polynomial */
public void output()
{
PolyNode currentNode = headNode.next;
while (currentNode != headNode)
{// output a term
System.out.print(currentNode.exp + " " + currentNode.coeff + " ");
currentNode = currentNode.next;
}
System.out.println();
}
/** @return this + b */
public CircularPolynomial add(CircularPolynomial b)
{
// define result polynomial w
CircularPolynomial w = new CircularPolynomial();
lastNode = w.headNode; // last node in w
// define cursors for b and this
PolyNode cb = b.headNode.next, // b cursor
ct = headNode.next; // cursor for this
// compute result
while (true)
if (ct.exp > cb.exp)
{// this has higher exponent, append ct term to w
append(ct.coeff, ct.exp);
ct = ct.next;
}
else
if (ct.exp < cb.exp)
{// b has higher exponent, append cb term to w
append(cb.coeff, cb.exp);
cb = cb.next;
}
else
{// equal exponents, see if we are finished
if (ct.exp == -1)
{// returned to headNode nodes
lastNode.next = w.headNode;
return w;
}
// not finished, add coeffecients and append if sum is nonzero
int sum = ct.coeff + cb.coeff;
if (sum != 0)
append(sum, ct.exp);
ct = ct.next;
cb = cb.next;
}
}
/** @return this - b */
public CircularPolynomial subtract(CircularPolynomial b)
{
// define result polynomial w
CircularPolynomial w = new CircularPolynomial();
lastNode = w.headNode; // last node in w
// define cursors for b and this
PolyNode cb = b.headNode.next, // b cursor
ct = headNode.next; // cursor for this
// compute result
while (true)
if (ct.exp > cb.exp)
{// this has higher exponent, append ct term to w
append(ct.coeff, ct.exp);
ct = ct.next;
}
else
if (ct.exp < cb.exp)
{// b has higher exponent, append cb term to w
append(-cb.coeff, cb.exp);
cb = cb.next;
}
else
{// equal exponents, see if we are finished
if (ct.exp == -1)
{// returned to headNode nodes
lastNode.next = w.headNode;
return w;
}
// not finished, subtract coeffecients and
// append if difference is nonzero
int diff = ct.coeff - cb.coeff;
if (diff != 0)
append(diff, ct.exp);
ct = ct.next;
cb = cb.next;
}
}
/** @return w = this * b */
public CircularPolynomial multiply(CircularPolynomial b)
{
CircularPolynomial w = new CircularPolynomial(); // result polynomial
// define cursors for w, b, and this
PolyNode cw, // cursor for w
cb = b.headNode.next, // b cursor
ct; // cursor for this
// multiply the two polynomials
while (cb != b.headNode)
{// multiply this and cb.coeff and add to w
cw = w.headNode;
ct = headNode.next;
while (ct != headNode)
{
int e = ct.exp + cb.exp; // exponent of new term
int c = ct.coeff * cb.coeff;
// find place to append new term
while (e < cw.next.exp)
cw = cw.next;
if (e == cw.next.exp)
{// add terms
cw.next.coeff += c;
if (cw.next.coeff != 0)
cw = cw.next;
else // coefficient is zero, remove the node
cw.next = cw.next.next;
}
else
{// new exponent, insert right of cw
cw.next = new PolyNode(c, e, cw.next);
cw = cw.next.next;
}
ct = ct.next;
}
cb = cb.next;
}
return w;
}
/** @return w = this / b, discard remainder */
public CircularPolynomial divide(CircularPolynomial b)
{
if (b.headNode.next == b.headNode) // division by zero
throw new IllegalArgumentException
("divisor cannot be zero");
CircularPolynomial w = new CircularPolynomial(), // result polynomial
r = (CircularPolynomial) this.clone(); // current remainder
// define pointers to first terms in b and r
// and to last one in w
PolyNode fb = b.headNode.next, // first in b
fr = r.headNode.next; // first in r
lastNode = w.headNode; // last in w
// divide the two polynomials
while (fb.exp <= fr.exp)
{// possible new term in answer
// compute coefficient of new term
int c = fr.coeff / fb.coeff;
if (c == 0) // coefficient is zero, no more terms
break;
// compute exponent of new term
int e = fr.exp - fb.exp;
// append new term to w
append(c, e);
// check if additional terms possible
if (c * fb.coeff != fr.coeff)
// no more terms
break;
// update remainder r by subtracting
// p * c * x^e from r
PolyNode cr = r.headNode;
// first term of r is eliminated
cr.next = cr.next.next;
PolyNode cb = fb.next;
while (cb != b.headNode)
{// multiply term of b with c * x^e
int newCoeff = c * cb.coeff;
int newExp = e + cb.exp;
// find place for this term in r
while (newExp < cr.next.exp)
cr = cr.next; // new term goes right of cr
// see if r has a term with the same exponent
if (newExp == cr.next.exp)
{// subtract terms
cr.next.coeff -= newCoeff;
if (cr.next.coeff != 0)
cr = cr.next;
else
// coefficient is zero, remove the node
cr.next = cr.next.next;
}
else
{// new exponent, insert right of cr
cr.next = new PolyNode(-newCoeff, newExp, cr.next);
cr = cr.next.next;
}
cb = cb.next;
}
fr = r.headNode.next; // fr has changed
}
// close the list w
lastNode.next = w.headNode;
return w;
}
/** @return polynomial value at x */
public int valueOf(int x)
{
if (headNode.next == headNode)
// zero polynomial
return 0;
if (x == 0)
{// x is zero
// find coefficient of x^0
PolyNode currentNode = headNode.next;
while(currentNode.next != headNode)
currentNode = currentNode.next;
if (currentNode.exp != 0)
// no term with exponent 0
return 0;
else // currentNode points to node for x^0
return currentNode.coeff;
}
// compute highest power of x that is needed
int powerOfX = 1;
for (int i = 1; i <= headNode.next.exp; i++)
powerOfX *= x;
int currentPower = headNode.next.exp;
// powerOfX = x^currentPower
// evlauate first term of polynomial
PolyNode currentNode = headNode.next;
int value = currentNode.coeff * powerOfX;
// add in remaining terms
currentNode = currentNode.next;
while (currentNode != headNode)
{
// compute powerOfX for this term
for (int i = currentPower; i > currentNode.exp; i--)
powerOfX /= x;
currentPower = currentNode.exp;
// add in the term
value += currentNode.coeff * powerOfX;
// move to next term
currentNode = currentNode.next;
}
return value;
}
}
The test program, input, and output are given in the files
CircularPolynomial.*.