tags:

views:

104

answers:

3

Hi, I'm a first year computer science student having a problem with part of an assignment. The goal of the assignment was to store the coefficients for a polynomial and find its roots using both an array and a linked list. I was able to successfully complete the array version; however the linked list is giving me a headache.

I am able to successfully store the initial round of variables provided in polynomial.java; however, things go a bit crazy once the root calculations begin and the program ends up terminating without giving any roots. I have a feeling this might be being cause by the way the Polynomial.java calculates the roots causing problems with the linked list; however, I am not allowed to change polynomial.java, only LinkedIntList.java. I have been banging my head against the computer for the past 7 hours trying to find the bug and am about ready to just give up on the assignment as I can't reach the professor for help.

I'd greatly appreciate anyone who can spot the bug or are willing to look over the code to provide tips on what I may be doing wrong or how I can work around my problem.

File 1: Node.Java

package lists;

public class Node
{
    int element;
    Node next = null;

    /**
     * Constructor which creates a new node containing the value specified by item
     *
    */
    public Node (int item)
    {
        element = item;
    }

    /**
     * Returns the current value of the data item contained inside this node
     */
    public int getElement ()
    {
        return element;
    }

    /**
     * Sets the current value of the data item contained inside this node to
     * the value specified by newVal
     */
    public void setElement (int newVal)
    {
        element = newVal;
    }

    /**
     * Links this node to the node passed in as an argument
     */ 
    public void setNext (Node n)
    {
        next = n;
    }

    /**
     * Returns a reference to the node that follows this node in the
     * linked list, or null if there is no such node
     */
    public Node getNext ()
    {
        return next;
    }

    /**
     * Returns a string based representation of the data item contained
     * in this node.
     */
    public String toString()
    {
        return Integer.toString(element);
    }   
}

File 2: LinkedIntList.Java

    package lists;

    public class LinkedIntList implements IntList
    {

        Node head = null;
        int count = 0;
        /**
         * Standard Java toString method that returns a string
         * equivalent of the IntList
         *
         * @return  a string indicating the values contained in 
         *          this IntList (ex: "[5 3 2 9 ]")
         */
        public String toString()
        {
            String retVal = "";
            String intermediary = "";
            Node n;
            for (n = head; n.getNext() != null; n = n.getNext())
            {
                intermediary = Integer.toString(n.getElement());
                retVal = intermediary + " " + retVal;
            }
            retVal = n.getElement() + " " + retVal;
            return retVal;
        }

        /**
         * Adds the given value to the <b>end</b> of the list.
         *
         * @param value  the value to add to the list
         */
        public void add (int value)
        {
            Node newNode = new Node (value);

            if (head == null)
                head = newNode;
            else
            {
                Node n = head;
                while (n.getNext() != null)
                {
                    n = n.getNext();
                }
                n.setNext(newNode);
            }
            count++;
        }

        /**
         * Returns the number of elements currently in the list.
         *
         * @return   the number of items currently in the list
         */
        public int size()
        {
            return count;
        }

        /**
         * Returns the element at the specified position in this list.
         *
         * @param index  index of the element to return (zero-based)
         * @return the element at the specified position in this list. 
         * @throws IndexOutOfBoundsException  if the index is out of range 
         *                                    (index < 0 || index >= size()). 
         */
        public int get(int index) throws IndexOutOfBoundsException
        {
            Node reference = head;
            if (index < 0 || index >= count)
            {
                throw new IndexOutOfBoundsException("Index out of bounds.");
            }
            for (int i = 0; i != index; i++)
                {
                    reference.getNext();
                }
            return reference.getElement();
        }

        /**
         * Replaces the element at the specified position in this list with 
         * the specified element. 
         *
         * @param index  index of the element to return (zero-based)
         * @param value  element to be stored at the specified position.
         * @throws IndexOutOfBoundsException  if the index is out of range 
         *                                    (index < 0 || index >= size()). 
         */
        public void set (int index, int value) throws IndexOutOfBoundsException
        {
            if (index < 0 || index >= count)
            {
                throw new IndexOutOfBoundsException("Index out of bounds.");
            }
            Node newNode = new Node (value);
            Node trailingReference = head;
            Node leadingReference = head.getNext();
                    for(int i = 1; i != index; i++)
                    {
                        trailingReference = leadingReference;
                        leadingReference = leadingReference.getNext();
                    }
            trailingReference.setNext(newNode);
            newNode.setNext(leadingReference);
            count++;
        }
    }

File 3: IntList.Java

        package lists;

        public interface IntList
        {
            /**
             * Standard Java toString method that returns a string
             * equivalent of the IntList
             *
             * @return  a string indicating the values contained in 
             *          this IntList (ex: "[5 3 2 9 ]")
             */
            public String toString();

            /**
             * Adds the given value to the <b>end</b> of the list.
             *
             * @param value  the value to add to the list
             */
            public void add (int value);

            /**
             * Returns the number of elements currently in the list.
             *
             * @return   the number of items currently in the list
             */
            public int size();

            /**
             * Returns the element at the specified position in this list.
             *
             * @param index  index of the element to return (zero-based)
             * @return the element at the specified position in this list. 
             * @throws IndexOutOfBoundsException  if the index is out of range 
             *                                    (index < 0 || index >= size()). 
             */
            public int get(int index);

            /**
             * Replaces the element at the specified position in this list with 
             * the specified element. 
             *
             * @param index  index of the element to return (zero-based)
             * @param value  element to be stored at the specified position.
             * @throws IndexOutOfBoundsException  if the index is out of range 
             *                                    (index < 0 || index >= size()). 
             */
            public void set (int index, int value);
        }

File 4: Polynomial.java

/**
 * A program which finds the integer (whole number) roots of a
 * polynomial with integer coeffecients.  The method used is based
 * upon the ideas presented at:
 *
*/

import lists.*;

public class Polynomial
{
    public static void main (String [] args)
    {
        // trick to get out of static context
        new Polynomial().runMe();
    }

    public void runMe()
    {

        IntList poly = new LinkedIntList();

        // Create the polynomial:
        // 3x^10 + 12x^9 - 496x^8 - 211x^7 + 18343x^6 -43760x^5 + 
        //    11766x^4 + 26841x^3 - 126816x^2 + 37278x - 84240
        poly.add (-84240);
        poly.add (37278);
        poly.add (-126816);
        poly.add (26841);
        poly.add (11766);
        poly.add (-43760);
        poly.add (18343);
        poly.add (-211);
        poly.add (-496);
        poly.add (12);
        poly.add (3);

        System.out.print ("Finding the integer roots of the polynomial: ");
        System.out.println (poly);
        IntList roots = findRoots (poly);

        for (int x = 0; x < roots.size(); x++)
            System.out.println ("Root found: " + roots.get(x));
    }

    /**
     * Find all *integer* roots of the polynomial represented by the IntList.
     * 
     * @param poly    a polynomial encoded as a list of coefficients
     * @return     a list of all roots of the given polynomial. Note that
     *         the returned list may have duplicate entries. 
     */
    public IntList findRoots (IntList poly)
    {
        IntList l = new LinkedIntList();  

        int q = poly.get(poly.size() - 1);
        int p = poly.get(0);

        IntList pVals = divTerms(Math.abs(p));
        IntList qVals = divTerms(Math.abs(q));

        IntList possibleZeros = findPotentialZeros(pVals, qVals);

        //for (Integer i : possibleZeros)
        for (int x = 0; x < possibleZeros.size(); x++)
            if (eval (poly, possibleZeros.get(x)) == 0)
                l.add (possibleZeros.get(x));

        return l;
    }

    /**
     * Evaluates the polynomial represented by the IntList with the given
     * value.
     *
     * @param poly    a 
     * @param val    the value to evaluate the polynomial with.
     * @return    f(val), where f is the polynomial encoded as poly
     */
    private int eval (IntList poly, int val)
    {
        int result = 0;
        for (int x = poly.size() - 1; x >= 0; x--)
            result += poly.get(x) * (int) Math.pow (val, x);  

        return result;

    }

    private IntList findPotentialZeros (IntList plist, IntList qlist)
    {

        IntList result = new LinkedIntList();

        for (int p = 0; p < plist.size(); p++)
        {
            for (int q = 0; q < qlist.size(); q++)
            {
                // add it only if q evenly divides p (we're looking
                // for integer roots only
                if (plist.get(p) % qlist.get(q) == 0)
                {
                    int x = plist.get(p) / qlist.get(q);
                    result.add (x);
                    result.add (-x);
                }
            }
        }
        return result;
    }


    /**
     * Find all integers that evenly divide i.
     *
     * @param i    the integer to find all divisors of
     * @return a list of all integers that evenly divide i
     */
    private IntList divTerms (int i)
    {

        IntList v = new LinkedIntList();  


        // 1 divides all numbers
        v.add(1);

        // find all divisors < i and >= 2
        for (int x = 2; x < i; x++)
            if (i % x == 0)
                v.add(x);

        // all numbers are evenly divisible by themselves
        if (i > 1) 
            v.add(i);

        return v;
    } 
}
A: 

The set method in the LinkedIntList isn't adhering to the contract specified in the Javadoc. It says replace the element at the given index but I see code that adds a new Node.

Have a look at what methods the Node class provides to help you make the set method a lot easier and correct.

suihock
Well that's what I get for recycling my code without paying attention. I guess I was a little tired when I first added that method and copied a remove one instead of creating a set one.
+2  A: 

I think, the mistake (or one of them) is in your LinkedList imlementation, exactly in get method:

    public int get(int index) throws IndexOutOfBoundsException
    {
        Node reference = head;
        if (index < 0 || index >= count)
        {
            throw new IndexOutOfBoundsException("Index out of bounds.");
        }
        for (int i = 0; i != index; i++)
            {
                reference.getNext(); // <--- the mistake is here
            }
        return reference.getElement();
    }

Your reference always refers on the head of the list.

If you're allowed to use any java packages - use java.util.LinkedList. Otherwise, use java.util.LinkedList until all other parts of your programm would be finished and tested and work as you wish. After that carefully replace it with your LinkedList implementation.

Roman
Yup, I forgot to make reference = reference.getNext();
A: 

Take a good look at your get implementation. It does not do what you think.

jackrabbit