How can I implement the Union-Find algorithm? - java

I'm trying to implement the Union-Find algorithm, but all of the implementations i've looked up use integers. I need to implement the algorithm so that I can call the union() and the connected() methods in this way: union(Vertex v, Vertex, w) - connected(Vertex v, Vertex w)
I've tried adapting my algorithm for it to work with vertices, but I don't know how to replace the parent and rank atributes to make it work. Please help :(
public class UF {
private int[] parent; // parent[i] = parent of i
private byte[] rank; // rank[i] = rank of subtree rooted at i (never more than 31)
private int count; // number of components
/**
* Initializes an empty union–find data structure with {#code n} sites
* {#code 0} through {#code n-1}. Each site is initially in its own
* component.
*
* #param n the number of sites
* #throws IllegalArgumentException if {#code n < 0}
*/
public UF(int n) {
if (n < 0) throw new IllegalArgumentException();
count = n;
parent = new int[n];
rank = new byte[n];
for (int i = 0; i < n; i++) {
parent[i] = i;
rank[i] = 0;
}
}
/**
* Returns the component identifier for the component containing site {#code p}.
*
* #param p the integer representing one site
* #return the component identifier for the component containing site {#code p}
* #throws IllegalArgumentException unless {#code 0 <= p < n}
*/
public int find(int p) {
validate(p);
while (p != parent[p]) {
parent[p] = parent[parent[p]]; // path compression by halving
p = parent[p];
}
return p;
}
/**
* Returns the number of components.
*
* #return the number of components (between {#code 1} and {#code n})
*/
public int count() {
return count;
}
/**
* Returns true if the the two sites are in the same component.
*
* #param p the integer representing one site
* #param q the integer representing the other site
* #return {#code true} if the two sites {#code p} and {#code q} are in the same component;
* {#code false} otherwise
* #throws IllegalArgumentException unless
* both {#code 0 <= p < n} and {#code 0 <= q < n}
*/
public boolean connected(int p, int q) {
return find(p) == find(q);
}
/**
* Merges the component containing site {#code p} with the
* the component containing site {#code q}.
*
* #param p the integer representing one site
* #param q the integer representing the other site
* #throws IllegalArgumentException unless
* both {#code 0 <= p < n} and {#code 0 <= q < n}
*/
public void union(int p, int q) {
int rootP = find(p);
int rootQ = find(q);
if (rootP == rootQ) return;
// make root of smaller rank point to root of larger rank
if (rank[rootP] < rank[rootQ]) parent[rootP] = rootQ;
else if (rank[rootP] > rank[rootQ]) parent[rootQ] = rootP;
else {
parent[rootQ] = rootP;
rank[rootP]++;
}
count--;
}
// validate that p is a valid index
private void validate(int p) {
int n = parent.length;
if (p < 0 || p >= n) {
throw new IllegalArgumentException("index " + p + " is not between 0 and " + (n-1));
}
}
}

In the standard algorithm each vertex is given an int id which represents it's place in an array. So this means parent[0] contains the id of the parent of vertex 0 and so.
Really you can consider arrays to be just a very efficient map from int to something else. If you replace the int with a more complex type then you need to start using a Map rather than an array.
So if you want to use a class called Vertex to represent vertices then you need to declare parents and ranks differently:
Map<Vertex,Vertex> parent = new HashMap<>();
Map<Vertex,Rank> rank = new HashMap<>();
You could replace Rank with Byte if you want to stick to the current scheme - though it's probably better encapsulation to use a class.
You'll then end up with code that looks something like:
while (!vertex.equals(parent.get(vertex))) {
parent.put(vertex, parent.get(parent.get(vertex)));
vertex = parent.get(vertex);
}
return vertex;
One thing to be aware of is that if you are going to use Vertex as the key of a map (as I've recommended) then you must implement equals and hashCode methods.

Related

showing array for quickfind

I'm trying to print out the full array id[] after each time the union() method is called. in the main() method. also need to bee able to count the number of times the array is accessed. I am aware that it is accessed twice when calling the connected method, once when calling find() and up to 2n + 1 when calling union(). Please help.
public class QuickFindUF {
private int[] id; // id[i] = component identifier of i
private int count; // number of components
/**
* Initializes an empty union–find data structure with {#code n} sites
* {#code 0} through {#code n-1}. Each site is initially in its own
* component.
*
* #param n the number of sites
* #throws IllegalArgumentException if {#code n < 0}
*/
public QuickFindUF(int n) {
count = n;
id = new int[n];
for (int i = 0; i < n; i++)
id[i] = i;
}
/**
* Returns the number of components.
*
* #return the number of components (between {#code 1} and {#code n})
*/
public int count() {
return count;
}
/**
* Returns the component identifier for the component containing site {#code p}.
*
* #param p the integer representing one site
* #return the component identifier for the component containing site {#code p}
* #throws IndexOutOfBoundsException unless {#code 0 <= p < n}
*/
public int find(int p) {
validate(p);
return id[p];
}
// validate that p is a valid index
private void validate(int p) {
int n = id.length;
if (p < 0 || p >= n) {
throw new IndexOutOfBoundsException("index " + p + " is not between 0 and " + (n-1));
}
}
/**
* Returns true if the the two sites are in the same component.
*
* #param p the integer representing one site
* #param q the integer representing the other site
* #return {#code true} if the two sites {#code p} and {#code q} are in the same component;
* {#code false} otherwise
* #throws IndexOutOfBoundsException unless
* both {#code 0 <= p < n} and {#code 0 <= q < n}
*/
public boolean connected(int p, int q) {
validate(p);
validate(q);
return id[p] == id[q];
}
/**
* Merges the component containing site {#code p} with the
* the component containing site {#code q}.
*
* #param p the integer representing one site
* #param q the integer representing the other site
* #throws IndexOutOfBoundsException unless
* both {#code 0 <= p < n} and {#code 0 <= q < n}
*/
public void union(int p, int q) {
validate(p);
validate(q);
int pID = id[p]; // needed for correctness
int qID = id[q]; // to reduce the number of array accesses
// p and q are already in the same component
if (pID == qID)
return;
for (int i = 0; i < id.length; i++)
if (id[i] == pID) id[i] = qID;
count--;
}
/**
* Reads in a sequence of pairs of integers (between 0 and n-1) from standard input,
* where each integer represents some site;
* if the sites are in different components, merge the two components
* and print the pair to standard output.
*
* #param args the command-line arguments
*/
public static void main(String[] args) {
int n = StdIn.readInt();
QuickFindUF uf = new QuickFindUF(n);
while (!StdIn.isEmpty()) {
int p = StdIn.readInt();
int q = StdIn.readInt();
if (uf.connected(p, q)){
continue;
}
uf.union(p, q);
StdOut.println(p + " " + q);
}
StdOut.println(uf.count() + " components");
}
}
Trying to break down your question...
Part 1:
I'm trying to print out the full array id[] after each time the union
method is called. in the main method.
try to create a string buffer and add the elements while you access it. once you are done and wanna print the array, you can just print the string buffer..
public void union(int p, int q) {
validate(p);
validate(q);
int pID = id[p]; // needed for correctness
int qID = id[q]; // to reduce the number of array accesses
// p and q are already in the same component
if (pID == qID)
return;
StringBuilder sb=new StringBuilder("");
for (int i = 0; i < id.length; i++)
{
sb.append(id[i]) + " "; // you are accessing all id elements anyway; add it to the 'sb' string while you are at it
// seperate each id element with a space
// do it in this place (before the if statement below) if you would like to print the before state of the array
if (id[i] == pID)
id[i] = qID;
//sb.append(id[i]) + " "; // do it here if you would like to print the after state of the array
}
System.out.println(sb);
count--;
}
Part 2:
also need to bee able to count the number of times the array is
accessed. i am aware that it is accessed twice when calling the
connected method, once when calling find() and up to 2n + 1 when
calling union()
For this you need to consider refactoring your code.. since you are dealing with arrays in the same class, you will not be able to count the number of times you access this array.. You can however consider having the Array in a different class as a private variable. create points of access via a getter and/or setter methods. then you can count the number of times you access the array in a reliable way..
hope this helps..
This is more of a general solution for printing an array of primitives in java. You could do it much more simple than this by iterating over the array and printing each member, inserting a newline character once your print loop has completed it's last loop.
int length = Array.getLength(aObject);
Object[] objArr = new Object[length];
for (int i=0; i<length; i++)
objArr[i] = Array.get(aObject, i);
System.out.println(Arrays.toString(objArr))
Try a search next time :)
Print arrays in Java

Testing My Heap

1.) I'm having difficulty testing me heap class. When I try to print my heap, it's giving me code instead of the array. I tried using toString() and DeeptoString() and neither worked.
2.) In my updateValue method. I realize that it doesn't know what to do once it's reached a node that has no children. It shoots me an index out of bounds. I think an easy way to check for that is to see if the left and right child index is greater or equal to the size. If it is...I guess I want it to do nothing.
Code below:
import java.util.NoSuchElementException;
public class MaxHeap {
public int[] heap;
private int size;
public static void main(String args[]){
MaxHeap testHeap = new MaxHeap(5);
testHeap.add(5);
testHeap.add(4);
testHeap.add(3);
testHeap.add(2);
testHeap.add(1);
System.out.println((testHeap));
testHeap.maxHeapify(0);
System.out.println(testHeap);
testHeap.extractMax();
System.out.println(testHeap);
testHeap.updateValue(1, 6);
System.out.println(testHeap);
}
/**
* _Part 0: Implement this constructor._
*
* Creates a new Heap instance initially capable of storing the specified
* number of elements.
*
* #param initialsize the initial size of the heap array
*/
public MaxHeap(int initialsize) {
// TODO: implement this
heap = new int [initialsize];
}
/**
* Provides read-only access to the heap's size. Size here is the number
* of *valid* items in the heap
*
* #return the number of items in the heap
*/
public int size() {
return size;
}
/**
* _Part 1: Implement this method._
*
* Adds an item to the heap maintaining the heap condition.
*
* An item is added to the next available slot in the array, and then
* bubbled up to its parent until the heap condition is restored.
*
* #param item
* the new int to add to the heap
*/
public void add(int item) {
// TODO: implement this
int parentIndex = (size-1)/2;
int childIndex = size;
heap[size] = item; //put it at the end
while (heap[parentIndex] < heap[childIndex] && parentIndex >= 0){ //check to make sure it's a proper heap
int temp = heap[parentIndex]; //start percolating up
heap[parentIndex] = heap[childIndex];
heap[childIndex] = temp;
childIndex = parentIndex;
parentIndex = (parentIndex-1)/2;
}
size+=1;
}
/**
* _Part 2: Implement this method._
*
* Restore the heap condition to a tree rooted at the specified index when
* the left and right subtrees obey the heap condition, but the root may
* not. This is also known as "Bubble Down".
*
* That is, given the specified index, and the fact that the left and
* right subtrees are heaps (if they exist), ensure that the largest of
* these three nodes get's swapped with the root, and then recursively
* restore the heap condition for the subtree with the element that was
* moved from the root.
*
* In essence, this method bubbles a value down from the root until the
* heap condition is restored.
*
* #param index
* the root tree to restore
*/
public void maxHeapify(int index) {
// TODO: implement this
int left, right, large, tmp; // declare variables left child, right child, largest node, temp for swap
int i = index;
left = 2 * i + 1; // left child
right = 2 * i + 2; // right child
if(left <= heap.length-1 && heap[left] > heap[i]) // find smallest child
large = left; // save index of smaller child
else
large = i;
if(right <= heap.length-1 && heap[right] > heap[large])
large = right; // save index of smaller child
if(large != i) // swap and percolate, if necessary
{
tmp = heap[i]; // exchange values at two indices
heap[i] = heap[large];
heap[large] = tmp;
maxHeapify(large);}
}
/**
* _Part 3: Implement this method._
*
* Removes the maximum valued item from the heap and restores the heap
* condition. If the heap is empty, this method should throw
* a NoSuchElementException
*
* This function is performed by:
*
* 1. removing the root of the heap
* 2. placing element from the end of the heap at the root
* 3. calling maxHeapify to restore the heap condition
* 4. making sure the size is updated
*
* #return the highest valued item from the heap
* #throws NoSuchElementException if called on an empty heap
*/
public int extractMax() {
// TODO: implement this
if (size < 1){
//throw no such element
throw new NoSuchElementException();
}
int max = heap[0];
heap[0] = heap[size-1];
size = size-1;
maxHeapify(0);
return max;
}
/**
* _Part 4: Implement this method._
*
* Checks to make sure that the *max* heap condition is upheld on a
* given array of integers.
*
* HINT: Full credit will be given on this one if you implement this
* method as a *recursive* function. It will probably make sense to
* create a private method that takes another argument (e.g., the index
* of the heap's root) to indicate where the checking should begin.
*
* My private method has the following signature:
* private static boolean check(int [] arry, int rootindx, int sz)
*
*
* #param array
* the array of data to check
* #param size
* the number of elements 'in' the heap (starting at index 0)
* #return true if the *max* heap condition is upheld
*/
public static boolean checkHeapCondition(int[] array, int size) {
// TODO: implement this
if (array != null)
return helpCheck(array,0, size);
return false;
}
//Helper method
private static boolean helpCheck(int[] arr, int i, int size) {
//Base case
if (i == size-1)
return true;
//2nd base case
if (2*i+1 >= size){
return true;
}
// check if a parent's value is larger or equal to both of
// its left child and right child
else if (arr[i] >= arr[2*i + 1] && arr[i] >= arr[2*i + 2])
return (helpCheck(arr, 2*i + 1, size) && helpCheck(arr, 2*i + 2, size));
else
return false;
}
/**
* _Part 5: Implement this method._
*
* Changes the value of an element in the heap. And bubbles the value
*
* #param index
* the index of the item to be modified
* #param newValue
* the new value of the specified item
* #return the old value of that item
* #throws IndexOutOfBoundsException if the specified index is invalid
*/
public int updateValue(int index, int newValue) {
// TODO: implement this
int parent = (index-1)/2;
int leftChild = (2*index +1);
int rightChild = (2*index+2);
if (heap == null || index >= size ){
throw new IndexOutOfBoundsException();}
int oldValue = heap[index];
heap[index] = newValue;
while (heap[parent] < heap[index] && parent >= 0 ){
int temp = heap[parent];
heap[parent] = heap[index];
heap[index] = heap[temp];
index = parent;
parent = (parent-1)/2;
}
//We need to check to see if the children don't exist
if (heap[leftChild] > heap[index] || heap[rightChild] > heap[index]){
maxHeapify(index);
return oldValue;
}
else return oldValue;
}
}
The method System.out.print(Object o) uses the parameter Object's toString() method. If you have not overridden this method to provide custom behavior, it will use the parent method (in this case, the default Object.toString()).
To print the value of MaxHeap, override it's toString method, returning a String that you want to represent an instance of this class. For instance:
#Override
public String toString(){
return java.util.Arrays.toString(heap);
}
I have found what's wrong with my updateValue. I created another if statement to check if the index value of the left and right child were within bounds. Thanks for all your help.

Dynamic array in java

What i am trying to do is
...
int sum[];
...
for(int z.....){
...
sum[z] = some_random_value;
...
}
But it gives an error at line sum[z]=ran; that variable sum might not have been initialized.
I tried int sum[] = 0; instead of int sum[]; but even that gave an error.
(I am basically a C programmer)
An array of dynamic size isn't possible in Java - you have to either know the size before you declare it, or do resizing operations on the array (which can be painful).
Instead, use an ArrayList<Integer>, and if you need it as an array, you can convert it back.
List<Integer> sum = new ArrayList<>();
for(int i = 0; i < upperBound; i++) {
sum.add(i);
}
// necessary to convert back to Integer[]
Integer[] sumArray = sum.toArray(new Integer[0]);
This is for getting rid of compile-time error:
int sum[] = null;
However, to prevent runtime-errors I strongly suggest you to initialize your array like this:
int[] sum = new int[10];
The number in brackets denotes the array size.
And if your size is dynamic, then use a List implementation, such as ArrayList.
int sum[]= new int[length];
You haven't initialized. As of now , you just declared.
And do not for get that the length of the array should decide at the time of initialization.
Even if you do int sum[] = null; you'll end up with an NullPointerException while you do sum[z]=ran;
Can't i just keep it dynamic? the length is variable
No. Arrays lenght should be fixed while initializing it. Look into Collection's in java. More specifically A List interface with ArrayList implementation, which is
Resizable-array implementation of the List interface. Implements all optional list operations, and permits all elements, including null.
By writing int[] anArray = new int[10]; you are telling that
Allocate an array with enough memory for 10 integer elements and assigns the array to the anArray variable.
Seems you are new to array's and even for java. The tutorial may help you better to understand.
http://docs.oracle.com/javase/tutorial/java/nutsandbolts/arrays.html
If you're talking about dynamic arrays, the class can be represented as -
public class DynArray {
private int size; // The current size of the array (number of elements in the array)
private int maxSize; // Size of memory allocated for the array
private Object[] array; // size of array == maxSize
/**
* An array constructor
* Argument specifies how much memory is needed to allocate for elements
*
* #param sz
* #throws IndexOutOfBoundsException
*/
public DynArray(int sz) throws IndexOutOfBoundsException {
// Here called another more general constructor
this(sz, sz, null);
}
/**
* Call the constructor, in which indicated how much memory is allocated
* for the elements and how much memory is allocated total.
*
* #param sz
* #param maxSz
* #throws IndexOutOfBoundsException
*/
public DynArray(int sz, int maxSz) throws IndexOutOfBoundsException {
// Here called another more general constructor
this(sz, maxSz, null);
}
/**
* Additional argument contains an array of elements for initialization
*
* #param sz
* #param maxSz
* #param iniArray
* #throws IndexOutOfBoundsException
*/
public DynArray(int sz, int maxSz, Object[] iniArray) throws IndexOutOfBoundsException {
if((size = sz) < 0) {
throw new IndexOutOfBoundsException("Negative size: " + sz);
}
maxSize = (maxSz < sz ? sz : maxSz);
array = new Object[maxSize]; // memory allocation
if(iniArray != null) { // copying items
for(int i = 0; i < size && i < iniArray.length; i++) {
array[i] = iniArray[i];
// Here it was possible to use the standard method System.arraycopy
}
}
}
/**
* Indexing
*
* #param i
* #return
* #throws IndexOutOfBoundsException
*/
public Object elementAt(int i) throws IndexOutOfBoundsException {
if (i < 0 || i >= size) {
throw new IndexOutOfBoundsException("Index" + i +
" out of range [0," + (size - 1) + "]");
}
return array[i];
}
/**
* Changing the current size of the array. argument delta specifies
* direction of change (positive - increase the size;
* negative - decrease the size)
*
* #param delta
*/
public void resize(int delta) {
if (delta > 0) enlarge(delta); // increasing the size of the array
else if (delta < 0) shrink(-delta); // decreasing the size of the array
}
/**
* Increasing the size of the array
*
* #param delta
*/
public void enlarge(int delta) {
if((size += delta) > maxSize) {
maxSize = size;
Object[] newArray = new Object[maxSize];
// copying elements
for(int i =0; i < size - delta; i++)
newArray[i] = array[i];
array = newArray;
}
}
/**
* Decreasing the size of the array
*
* #param delta
*/
public void shrink(int delta) {
size = (delta > size ? 0 : size - delta);
}
/**
* Adding a new element
* (with a possible increasing the size of the array)
*
* #param e
*/
public void add(Object e) {
resize(1);
array[size-1] = e;
}
/**
* Removing the given value - shifting elements and subsequent
* reduction the size of the array
*
* #param e
*/
public void remove(Object e) {
int j;
for(j = 0; j < size; j++) {
if(e.equals(array[j])) {
break;
}
}
if(j == size) {
return false;
} else {
for(int k = j; k < size; k++)
array[k] = array[k + 1];
resize(-1);
return true;
}
}
}
You still need to initialize your array after it's declared: int sum[]= new int[length];.
Now you can assign values in the array up to the size specified when you initialized it.
If you want to have a dynamically sized array, use ArrayList and call toArray at the end to convert it back to a regular array.

Trouble with 1st year programming assignment

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;
}
}
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.
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.
Take a good look at your get implementation. It does not do what you think.

Java: Using adjacency list to compute all pairs shortest path?

I am writing a Graph library that has both adjacency list and matrix implementations. Here is some code I came across in a Java data structures textbook:
static void floyd(Graph<V,E> g)
// post: g contains edge (a,b) if there is a path from a to b
{
Iterator<V> witer = g.iterator(); //vertex iterator
while (witer.hasNext())
{
Iterator<V> uiter = g.iterator();
V w = witer.next();
while (uiter.hasNext())
{
Iterator<V> viter = g.iterator();
V u = uiter.next();
while (viter.hasNext())
{
V v = viter.next();
if (g.containsEdge(u,w) && g.containsEdge(w,v))
{
Edge<V,E> leg1 = g.getEdge(u,w);
Edge<V,E> leg2 = g.getEdge(w,v);
int leg1Dist = leg1.label();
int leg2Dist = leg2.label();
int newDist = leg1Dist+leg2Dist;
if (g.containsEdge(u,v))
{
Edge<V,E> across = g.getEdge(u,v);
int acrossDist = across.label();
if (newDist < acrossDist)
across.setLabel(newDist);
}
else
{
g.addEdge(u,v,newDist);
}
}
}
}
}
But it seems like it is just overwriting the current edge with with the "shortest". Is this interpretation correct? I could use some clarification here.
Note: Here is some of the Edge class:
public class Edge
{
/**
* Two element array of vertex labels.
* When necessary, first element is source.
*/
protected Object[] vLabel; // labels of adjacent vertices
/**
* Label associated with edge. May be null.
*/
protected Object label; // edge label
/**
* Whether or not this edge has been visited.
*/
protected boolean visited; // this edge visited
/**
* Whether or not this edge is directed.
*/
protected boolean directed; // this edge directed
/**
* Construct a (possibly directed) edge between two labeled
* vertices. When edge is directed, vtx1 specifies source.
* When undirected, order of vertices is unimportant. Label
* on edge is any type, and may be null.
* Edge is initially unvisited.
*
* #post edge associates vtx1 and vtx2; labeled with label
* directed if "directed" set true
*
* #param vtx1 The label of a vertex (source if directed).
* #param vtx2 The label of another vertex (destination if directed).
* #param label The label associated with the edge.
* #param directed True iff this edge is directed.
*/
public Edge(Object vtx1, Object vtx2, Object label,
boolean directed)
{
vLabel = new Object[2];
vLabel[0] = vtx1;
vLabel[1] = vtx2;
this.label = label;
visited = false;
this.directed = directed;
}
/**
* Returns the first vertex (or source if directed).
*
* #post returns first node in edge
*
* #return A vertex; if directed, the source.
*/
public Object here()
{
return vLabel[0];
}
/**
* Returns the second vertex (or source if undirected).
*
* #post returns second node in edge
*
* #return A vertex; if directed, the destination.
*/
public Object there()
{
return vLabel[1];
}
/**
* Sets the label associated with the edge. May be null.
*
* #post sets label of this edge to label
*
* #param label Any object to label edge, or null.
*/
public void setLabel(Object label)
{
this.label = label;
}
/**
* Get label associated with edge.
*
* #post returns label associated with this edge
*
* #return The label found on the edge.
*/
public Object label()
{
return label;
}
It would be easier to understand what you're doing if you use a matrix to store the result in a matrix. Consider the following simple weighted graph:
2
1 +---------+ 2
|\ |
| -\ |
3 | -\5 | 2
| -\ |
| -\|
3 +---------+ 4
4
Now consider this implementation of the Floyd-Warshall algorithm:
public Matrix floyd() {
Matrix m = new Matrix(numVertices, numVertices, Integer.MAX_VALUE);
for (int i = 1; i<=numVertices; i++) {
EdgeNode edge = edges[i];
while (edge != null) {
m.setData(i, edge.getY(), edge.getWeight());
edge = edge.getNext();
}
m.setData(i, i, 0);
}
for (int i = 1; i <= numVertices; i++) {
for (int j = 1; j <= numVertices; j++) {
for (int k = 1; k <= numVertices; k++) {
if (m.getData(i, j) < Integer.MAX_VALUE && m.getData(i, k) < Integer.MAX_VALUE) {
int through = m.getData(i, j) + m.getData(i, k);
if (through < m.getData(j, k)) {
m.setData(j, k, through);
}
}
}
}
}
return m;
}
The first part of this seeds the matrix result with Integer.MAX_VALUE. Putting 0 here would yield an incorrect result but using values of 1 and 0 (respectively) would work fine for an unweighted graph. Integer.MAX_VALUE is there simply for correct minimal value checks.
The second part is the key part of the algorithm. It looks at the distance between two points (i,k) comparing it to the distance of (i,j) + (j,K) for all vertices j. If the indirect path is less it is substituted into the matrix as the shortest path and so on.
The result of this algorithm on the above (very simple) graph is:
[ 0 2 3 5 ]
[ 2 0 5 3 ]
[ 3 5 0 4 ]
[ 5 3 4 0 ]
What this tells you is the shortest distance between any pair of vertices. Note: I've seeded the result of (i,i) to 0 as you can argue the distance of any node to itself is 0. You can take out that assumption easily enough, yielding this result:
[ 4 2 3 5 ]
[ 2 4 5 3 ]
[ 3 5 6 4 ]
[ 5 3 4 6 ]
So node 3 to itself is a distance of 6 as it traverses 3->1->3 as the shortest path. This would get a lot more interesting in a directed graph, which Floyd's can handle.
Floyd's is an O(n3) algorithm. It won't reconstruct the actual path between each pair of points, just the total distance (weight). You can use Dijkstra's algorithm between each vertex pair to construct the actual paths, which interestingly enough is also O(n3) but tends to be slower in real world usage as the calculations of Floyd's are pretty simple.
Your algorithm uses an adjacency list instead of a matrix to implement this algorithm, which confuses the issue slightly. My version uses Integer.MAX_VALUE as a sentinel value to indicate no path (yet calculated) whereas yours uses the absence of an edge for the same thing. Other than that, it's exactly the same.

Categories