Initial revision
commit
a65c19be29
Binary file not shown.
After Width: | Height: | Size: 3.8 KiB |
|
@ -0,0 +1,535 @@
|
|||
import java.util.*;
|
||||
import java.text.DecimalFormat;
|
||||
import java.awt.Color;
|
||||
import java.awt.Graphics;
|
||||
|
||||
/**
|
||||
* Graph.java, models graph management and creation.<br>
|
||||
* Implements: GraphInterface.<br>
|
||||
* @author <A HREF="mailto:mem1780@tntech.edu">Matt Markham</A><BR>
|
||||
*/
|
||||
|
||||
public class Graph implements GraphInterface
|
||||
{
|
||||
//size integer variable to keep track of number of nodes in the graph
|
||||
private int size;
|
||||
//Double two-dimensional array for the adjacency matrix
|
||||
private double[][] adjacent;
|
||||
//boolean to determine whether a graph is directed
|
||||
private boolean directed;
|
||||
//Vertex storage list
|
||||
private ArrayList vertexList;
|
||||
//int to determin generic unweighted value
|
||||
private final int UNWEIGHTED_VALUE = 1;
|
||||
//temporary Arraylist for dfs
|
||||
private ArrayList tempAL=new ArrayList();
|
||||
//ArrayList containing the current shortest path
|
||||
private ArrayList path;
|
||||
|
||||
|
||||
/**
|
||||
* Default Constructor, creates an undirected graph.<br>
|
||||
*/
|
||||
|
||||
public Graph ()
|
||||
{
|
||||
size = 0;
|
||||
adjacent = new double[size][size];
|
||||
vertexList = new ArrayList();
|
||||
directed=false;
|
||||
path = new ArrayList();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Constructor, takes a boolean to determine directed or undirected.<br>
|
||||
*/
|
||||
|
||||
public Graph (boolean param)
|
||||
{
|
||||
size = 0;
|
||||
adjacent = new double[size][size];
|
||||
vertexList = new ArrayList();
|
||||
directed=param;
|
||||
path = new ArrayList();
|
||||
}
|
||||
|
||||
public void makeEmpty()
|
||||
{
|
||||
size=0;
|
||||
adjacent = new double[size][size];
|
||||
vertexList.clear();
|
||||
}
|
||||
|
||||
public boolean isEmpty()
|
||||
{
|
||||
return (size==0);
|
||||
}
|
||||
|
||||
|
||||
public int numVertices()
|
||||
{
|
||||
return size;
|
||||
}
|
||||
|
||||
|
||||
public int numEdges()
|
||||
{
|
||||
int c=0;
|
||||
for(int x=0; x<size;x++)
|
||||
{
|
||||
for(int y=0;y<size;y++)
|
||||
{
|
||||
if (!(adjacent[x][y]==(Double.POSITIVE_INFINITY)))
|
||||
{
|
||||
c++; //Insert nerdy joke here
|
||||
}
|
||||
}
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
public void addVertex (GraphNode myItem) throws GraphException
|
||||
{
|
||||
for(int a=0; a<vertexList.size();a++)
|
||||
|
||||
if ( ((GraphNode) vertexList.get(a)).getKey().compareTo ( myItem.getKey() ) == 0 )
|
||||
|
||||
throw new GraphException ( "Duplicate entry" );
|
||||
|
||||
size++;
|
||||
|
||||
vertexList.add(myItem);
|
||||
|
||||
resizeAdjacent ( vertexList.size() );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Method to resize the adjacency matrix.<br>
|
||||
* Preconditions: must be passed a new size value.<br>
|
||||
* Postconditions: resizes adjacency matrix.<br>
|
||||
* Throws: None.
|
||||
*/
|
||||
|
||||
private void resizeAdjacent ( int size )
|
||||
{
|
||||
|
||||
double[][] temp = new double[size][size];
|
||||
|
||||
for( int x = 0; x < size - 1; x++)
|
||||
|
||||
for ( int y = 0; y < size - 1; y++ )
|
||||
|
||||
temp[x][y] = adjacent[x][y];
|
||||
|
||||
for ( int x = 0; x < size; x++ )
|
||||
{
|
||||
|
||||
temp[x][size - 1] = Double.POSITIVE_INFINITY;
|
||||
|
||||
temp[size - 1][x] = Double.POSITIVE_INFINITY;
|
||||
|
||||
}
|
||||
|
||||
adjacent = temp;
|
||||
}
|
||||
|
||||
public void addEdge(Comparable searchKey1, Comparable searchKey2, double weight) throws GraphException
|
||||
{
|
||||
for(int x=0; x<size; x++)
|
||||
{
|
||||
if ( ((GraphNode) vertexList.get(x)).getKey().compareTo(searchKey1) == 0 )
|
||||
{
|
||||
for(int y=0; y<size;y++)
|
||||
{
|
||||
if ( ((GraphNode) vertexList.get(y)).getKey().compareTo(searchKey2) == 0 )
|
||||
{
|
||||
adjacent[x][y]=weight;
|
||||
return;
|
||||
}//end if get(y)
|
||||
}// end for y
|
||||
}//end if get(x)
|
||||
}//end for x
|
||||
throw new GraphException ( "Duplicate found!" );
|
||||
}
|
||||
|
||||
public void addEdge(Comparable searchKey1, Comparable searchKey2) throws GraphException
|
||||
|
||||
{
|
||||
for(int x=0; x<size; x++)
|
||||
{
|
||||
if ( ((GraphNode) vertexList.get(x)).getKey().compareTo(searchKey1) == 0 )
|
||||
{
|
||||
for(int y=0; y<size;y++)
|
||||
{
|
||||
if ( ((GraphNode) vertexList.get(y)).getKey().compareTo(searchKey2) == 0 )
|
||||
{
|
||||
adjacent[x][y]=UNWEIGHTED_VALUE;
|
||||
if(!directed)
|
||||
{adjacent[y][x]=UNWEIGHTED_VALUE;}
|
||||
return;
|
||||
}//end if get(y)
|
||||
}// end for y
|
||||
}//end if get(x)
|
||||
}//end for x
|
||||
throw new GraphException ( "Duplicate found!" );
|
||||
}
|
||||
|
||||
public double getWeight(Comparable searchKey1, Comparable searchKey2) throws GraphException
|
||||
{
|
||||
for(int x=0; x<size;x++)
|
||||
{
|
||||
if ( ((GraphNode) vertexList.get(x)).getKey().compareTo(searchKey1) == 0 )
|
||||
{
|
||||
for(int y=0; y<size;y++)
|
||||
{
|
||||
if ( ((GraphNode) vertexList.get(y)).getKey().compareTo(searchKey2) == 0 )
|
||||
{
|
||||
return adjacent[x][y];
|
||||
}//end if get(y)
|
||||
}// end for y
|
||||
}//end if get(x)
|
||||
}//end for x
|
||||
throw new GraphException ( "Edge does not exist!");
|
||||
}
|
||||
|
||||
public GraphNode getVertex(int index) throws GraphException
|
||||
{
|
||||
if (index>size)
|
||||
throw new GraphException ("index out of bounds!");
|
||||
else
|
||||
return (GraphNode)vertexList.get(index);
|
||||
}
|
||||
|
||||
public GraphNode getVertex(Comparable searchKey) throws GraphException
|
||||
{
|
||||
for (int x=0;x<vertexList.size();x++)
|
||||
{
|
||||
if ( ((GraphNode) vertexList.get(x)).getKey().compareTo(searchKey) == 0)
|
||||
{
|
||||
return (GraphNode) vertexList.get(x);
|
||||
}
|
||||
}
|
||||
throw new GraphException ("Vertex not Found in List!");
|
||||
}
|
||||
|
||||
/**
|
||||
* FInds the index of a given searchKey.<br>
|
||||
* Preconditions: Must be passed searchKey.<br>
|
||||
* Postconditions: returns integer index of given searchKey.<br>
|
||||
* Throws:Nonde.
|
||||
*/
|
||||
|
||||
private int findVertex (Comparable searchKey)
|
||||
{
|
||||
for (int d=0; d<size;d++)
|
||||
{
|
||||
if ( ((GraphNode) vertexList.get(d)).getKey().compareTo(searchKey) == 0 )
|
||||
{ return d; }
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears all vertices, sets all to be unmarked.<br>
|
||||
* Preconditions: None.<br>
|
||||
* Postconditions: Makes all vertices unmarked.<br>
|
||||
* Throws:None.
|
||||
*/
|
||||
|
||||
private void clearMarks()
|
||||
{
|
||||
for (int x=0;x<size;x++)
|
||||
{
|
||||
((GraphNode) vertexList.get(x)).setMarked(false);
|
||||
}
|
||||
}
|
||||
|
||||
public Comparable getSearchKey (int index)
|
||||
{
|
||||
return ((GraphNode)(vertexList.get(index))).getKey();
|
||||
}
|
||||
|
||||
public void removeEdge(Comparable searchKey1, Comparable searchKey2) throws GraphException
|
||||
{
|
||||
int a=findVertex(searchKey1);
|
||||
int b=findVertex(searchKey2);
|
||||
if (a==-1 || b==-1)
|
||||
throw new GraphException ("Entry not found in list!");
|
||||
adjacent[a][b]=Double.POSITIVE_INFINITY;
|
||||
}
|
||||
|
||||
|
||||
public ArrayList bfs (Comparable searchKey) throws GraphException
|
||||
{
|
||||
GraphNode temp;
|
||||
ArrayList searchList = new ArrayList();
|
||||
QueueReferenceBased bfsQueue= new QueueReferenceBased();
|
||||
bfsQueue.enqueue(vertexList.get(findVertex(searchKey)));
|
||||
getVertex(searchKey).setMarked(true);
|
||||
searchList.add(getVertex(searchKey));
|
||||
|
||||
while (!bfsQueue.isEmpty())
|
||||
{
|
||||
temp=(GraphNode)bfsQueue.dequeue();
|
||||
|
||||
for(int g=0;g<size;g++)
|
||||
{
|
||||
if (adjacent[findVertex(temp.getKey())][g] != Double.POSITIVE_INFINITY && !getVertex(g).isMarked())
|
||||
{
|
||||
((GraphNode)vertexList.get(g)).setMarked(true);
|
||||
bfsQueue.enqueue(vertexList.get(g));
|
||||
searchList.add(getVertex(g));
|
||||
}//end if
|
||||
}//end for
|
||||
}//end while
|
||||
clearMarks();
|
||||
return searchList;
|
||||
}
|
||||
|
||||
public GraphNode removeVertex ( Comparable key ) throws GraphException
|
||||
{
|
||||
int index = -1;
|
||||
for ( int i = 0; i < vertexList.size(); i++ )
|
||||
if ( ((GraphNode) vertexList.get ( i )).getKey().compareTo ( key ) == 0 )
|
||||
index = i;
|
||||
if ( index == -1 )
|
||||
throw new GraphException ( "Vertex not in graph" );
|
||||
double[][] temp = new double[adjacent.length - 1][adjacent.length - 1];
|
||||
for ( int row = 0; row < adjacent.length; row++ )
|
||||
{
|
||||
for ( int col = 0; col < adjacent[0].length; col++ )
|
||||
{
|
||||
if ( row != index && col != index )
|
||||
{
|
||||
int newrow = row;
|
||||
int newcol = col;
|
||||
/* make sure the row/col are not in the row/col of the vertex to be removed */
|
||||
if ( row > index )
|
||||
newrow = row - 1;
|
||||
if ( col > index )
|
||||
newcol = col - 1;
|
||||
temp[newrow][newcol] = adjacent[row][col];
|
||||
}
|
||||
}
|
||||
}
|
||||
adjacent = temp;
|
||||
size--;
|
||||
return (GraphNode) vertexList.remove ( index );
|
||||
}
|
||||
|
||||
public ArrayList dfs (Comparable searchKey) throws GraphException
|
||||
{
|
||||
ArrayList dfsList = new ArrayList();
|
||||
dfsList=dfsRec(getVertex(searchKey), dfsList);
|
||||
clearMarks();
|
||||
return dfsList;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Private recursive method called to generate a breadth-first search.<br>
|
||||
* Preconditions: Must be passed a graphNode and an ArrayList.<br>
|
||||
* Postconditions: Returns an Arraylist for the bfs.<br>
|
||||
* Throws:None.
|
||||
*/
|
||||
|
||||
private ArrayList dfsRec(GraphNode vertex, ArrayList searchRecList)
|
||||
{
|
||||
searchRecList.add(vertex);
|
||||
vertex.setMarked(true);
|
||||
int i=vertexList.indexOf(vertex);
|
||||
for(int j=0; j<size; j++)
|
||||
{
|
||||
if (adjacent[i][j]!=(Double.POSITIVE_INFINITY) &&
|
||||
!(getVertex(j)).isMarked())
|
||||
dfsRec( getVertex(j), searchRecList );
|
||||
|
||||
}//end for j
|
||||
return searchRecList;
|
||||
}
|
||||
|
||||
/**
|
||||
* Draws the panel with all of the edges and vertices. <BR>
|
||||
* Preconditions: A Graphics object and the radius of the vertecies. <BR>
|
||||
* Postconditions: Draws all of the neccessary components onto the GraphScreen. <BR>
|
||||
* @author <A HREF="mailto:arc4472@tntech.edu">Andrew Coleman</A><BR>
|
||||
*/
|
||||
public void draw ( Graphics g, int radius )
|
||||
{
|
||||
/* draw all of the edges in orange */
|
||||
g.setColor ( Color.orange );
|
||||
for ( int i = 0; i < adjacent.length; i++ )
|
||||
{
|
||||
int firstx = getVertex ( i ).getX();
|
||||
int firsty = getVertex ( i ).getY();
|
||||
String firstkey = getVertex ( i ).getKey().toString();
|
||||
for ( int j = 0; j < adjacent[i].length; j++ )
|
||||
{
|
||||
if ( adjacent[i][j] != Double.POSITIVE_INFINITY )
|
||||
{
|
||||
int secondx = ((GraphNode) getVertex ( j )).getX();
|
||||
int secondy = ((GraphNode) getVertex ( j )).getY();
|
||||
String secondkey = (String)((GraphNode) getVertex ( j )).getKey();
|
||||
DecimalFormat format = new DecimalFormat();
|
||||
format.setMaximumFractionDigits ( 3 );
|
||||
int difference = 10;
|
||||
/* the final x and y coordinates for the string for each edge */
|
||||
int xcoord, ycoord;
|
||||
if ( firstx < secondx )
|
||||
xcoord = (secondx - firstx) / 2 + firstx;
|
||||
else
|
||||
xcoord = (firstx - secondx) / 2 + secondx;
|
||||
if ( firsty < secondy )
|
||||
ycoord = (secondy - firsty) / 2 + firsty;
|
||||
else
|
||||
ycoord = (firsty - secondy) / 2 + secondy;
|
||||
/* if i < j, then the edge goes from j to i */
|
||||
if ( i < j )
|
||||
{
|
||||
g.drawLine ( firstx, firsty - 10, secondx, secondy - 10 );
|
||||
g.drawString ( firstkey + " to " + secondkey + ", Weight: " + format.format ( adjacent[i][j] ), xcoord, ycoord - 11 );
|
||||
}
|
||||
/* if i > j, then the edge goes from i to j */
|
||||
else if ( i > j )
|
||||
{
|
||||
g.drawLine ( firstx, firsty + 10, secondx, secondy + 10 );
|
||||
g.drawString ( firstkey + " to " + secondkey + ", Weight: " + format.format ( adjacent[i][j] ), xcoord, ycoord + 11 );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* draw the shortest path stored in green */
|
||||
g.setColor ( Color.green );
|
||||
for ( int i = 1; i < path.size(); i++ )
|
||||
{
|
||||
int firstx = ((GraphNode) path.get ( i - 1 )).getX();
|
||||
int firsty = ((GraphNode) path.get ( i - 1 )).getY();
|
||||
int secondx = ((GraphNode) path.get ( i )).getX();
|
||||
int secondy = ((GraphNode) path.get ( i )).getY();
|
||||
g.drawLine ( firstx, firsty, secondx, secondy );
|
||||
}
|
||||
|
||||
/* draw all of the vertices in dark gray with a light gray border and the comparable data in the middle */
|
||||
for ( int i = 0; i < numVertices(); i++ )
|
||||
{
|
||||
g.setColor ( Color.lightGray );
|
||||
GraphNode temp = getVertex ( i );
|
||||
g.fillOval ( temp.getX() - radius, temp.getY() - radius, radius * 2, radius * 2 );
|
||||
g.setColor ( Color.darkGray );
|
||||
int difference = 2;
|
||||
g.fillOval ( temp.getX() - radius + difference, temp.getY() - radius + difference, (radius - difference) * 2, (radius - difference) * 2 );
|
||||
g.setColor ( Color.white );
|
||||
g.drawString ( (String) temp.getKey(), temp.getX(), temp.getY() );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is used to set the arraylist containing the shortest path to be displayed. <BR>
|
||||
* Preconditions: An arraylist containing a valid shortest path. <BR>
|
||||
* Postconditions: Sets the current path to the given arraylist. <BR>
|
||||
* @author <A HREF="mailto:arc4472@tntech.edu">Andrew Coleman</A><BR>
|
||||
*/
|
||||
public void setShortestPathDisplay ( ArrayList path )
|
||||
{
|
||||
this.path = path;
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to calculate the shortest distance between two vertices using Djisktra's algorithm. <BR>
|
||||
* Preconditions: Two comparables representing the data in the two vertices. <BR>
|
||||
* Postconditions: Returns an ArrayList containing the GraphNodes in the path. <BR>
|
||||
* Throws: Throws a GraphException if the comparables are the same or there is no connecting path. <BR>
|
||||
* @author <A HREF="mailto:arc4472@tntech.edu">Andrew Coleman</A><BR>
|
||||
*/
|
||||
public ArrayList shortestPath ( Comparable firstkey, Comparable lastkey ) throws GraphException {
|
||||
if ( firstkey.compareTo ( lastkey ) == 0 )
|
||||
throw new GraphException ( "Cannot find shortest path to same vertex!" );
|
||||
/* the arraylist containing the raw path array */
|
||||
ArrayList path = new ArrayList ( vertexList.size() );
|
||||
/* mark the first vertex */
|
||||
getVertex ( firstkey ).setMarked ( true );
|
||||
/* indexes of the first and last search keys */
|
||||
int firstindex = findIndex ( firstkey );
|
||||
int secondindex = findIndex ( lastkey );
|
||||
/* the row of the adjacency matrix at firstindex */
|
||||
double[] weight = new double[vertexList.size()];
|
||||
/* initialize the weight/path arrays */
|
||||
for ( int i = 0; i < weight.length; i++ )
|
||||
{
|
||||
path.add ( vertexList.get ( i ) );
|
||||
weight[i] = adjacent[firstindex][i];
|
||||
/* if the weight is not infinity we must change the path to reflect the changes */
|
||||
if ( weight[i] < Double.POSITIVE_INFINITY )
|
||||
path.set ( i, getVertex ( firstkey ) );
|
||||
}
|
||||
|
||||
/* loop through all the elements in the graph, must mark them all */
|
||||
for ( int i = 1; i < vertexList.size(); i++ )
|
||||
{
|
||||
/* index of smallest vertex */
|
||||
int smallest = -1;
|
||||
/* smallest weight thus far that is not marked */
|
||||
double smallestweight = Double.POSITIVE_INFINITY;
|
||||
for ( int j = 0; j < weight.length; j++ )
|
||||
/* run through the weight array and find the smallest weight */
|
||||
if ( smallestweight >= weight[j] && !((GraphNode) vertexList.get ( j )).isMarked() )
|
||||
{
|
||||
/* note smallest vertex */
|
||||
smallest = j;
|
||||
smallestweight = weight[j];
|
||||
}
|
||||
/* mark smallest vertex */
|
||||
GraphNode smallnode = (GraphNode) vertexList.get ( smallest );
|
||||
smallnode.setMarked ( true );
|
||||
/* update the weight/path arrays */
|
||||
for ( int j = 0; j < weight.length; j++ )
|
||||
/* if a new weight to that vertex is less than the current weight, change the weight in the array and change the path arraylist */
|
||||
if ( weight[j] > weight[smallest] + adjacent[smallest][j] )
|
||||
{
|
||||
weight[j] = weight[smallest] + adjacent[smallest][j];
|
||||
path.set ( j, vertexList.get ( smallest ) );
|
||||
}
|
||||
}
|
||||
/* backwards path */
|
||||
ArrayList result = new ArrayList();
|
||||
GraphNode node = getVertex ( lastkey );
|
||||
int lastindex = findIndex ( lastkey );
|
||||
/* while the node is not the first node */
|
||||
while ( lastindex != firstindex )
|
||||
{
|
||||
result.add ( node );
|
||||
node = (GraphNode) path.get ( lastindex );
|
||||
int newlastindex = findIndex ( node.getKey() );
|
||||
/* if the indexes are the same, then there is no way to get to that vertex */
|
||||
if ( newlastindex == lastindex )
|
||||
throw new GraphException ( "No connecting path!" );
|
||||
else
|
||||
lastindex = newlastindex;
|
||||
}
|
||||
/* gotta add the first one */
|
||||
result.add ( getVertex ( firstkey ) );
|
||||
/* the result to return */
|
||||
ArrayList sortedresult = new ArrayList ( result.size() );
|
||||
/* reverse the arraylist */
|
||||
for ( int i = result.size() - 1; i >= 0; i-- )
|
||||
sortedresult.add ( result.get ( i ) );
|
||||
return sortedresult;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method finds the index of a given comparable object. <BR>
|
||||
* Preconditions: A valid comparable key in the graph. <BR>
|
||||
* Postcondtions: Returns the index of the key, or -1 if the key is not in the graph. <BR>
|
||||
*/
|
||||
private int findIndex ( Comparable key )
|
||||
{
|
||||
for ( int i = 0; i < vertexList.size(); i++ )
|
||||
if ( ((GraphNode) vertexList.get ( i )).getKey().compareTo ( key ) == 0 )
|
||||
return i;
|
||||
return -1;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
import java.util.ArrayList;
|
||||
|
||||
public class GraphDriver
|
||||
{
|
||||
public static void main ( String[] args )
|
||||
{
|
||||
Graph mygraph = new Graph();
|
||||
mygraph.addVertex ( new GraphNode ( "A" ) );
|
||||
mygraph.addVertex ( new GraphNode ( "B" ) );
|
||||
mygraph.addVertex ( new GraphNode ( "C" ) );
|
||||
mygraph.addVertex ( new GraphNode ( "D" ) );
|
||||
mygraph.addVertex ( new GraphNode ( "E" ) );
|
||||
|
||||
mygraph.addEdge ( "A", "D", 9.0 );
|
||||
mygraph.addEdge ( "A", "B", 8.0 );
|
||||
mygraph.addEdge ( "A", "E", 4.0 );
|
||||
mygraph.addEdge ( "B", "C", 1.0 );
|
||||
mygraph.addEdge ( "C", "B", 2.0 );
|
||||
mygraph.addEdge ( "C", "D", 3.0 );
|
||||
mygraph.addEdge ( "D", "C", 2.0 );
|
||||
mygraph.addEdge ( "D", "E", 7.0 );
|
||||
mygraph.addEdge ( "E", "C", 1.0 );
|
||||
|
||||
ArrayList bft = mygraph.shortestPath ( "A", "C" );
|
||||
for ( int i = 0; i < bft.size(); i++ )
|
||||
System.out.println ( bft.get ( i ).toString() );
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
public class GraphException extends RuntimeException
|
||||
{
|
||||
public GraphException()
|
||||
{
|
||||
} // end default constructor
|
||||
|
||||
public GraphException(String s)
|
||||
{
|
||||
super(s);
|
||||
} // end constructor
|
||||
} // end GraphException
|
|
@ -0,0 +1,93 @@
|
|||
import javax.swing.*;
|
||||
import java.awt.event.*;
|
||||
import java.awt.*;
|
||||
import java.util.*;
|
||||
|
||||
/** This is the parent window in the graph, it only sets flags based on menu choices and provides a place for the GraphScreen to draw itself */
|
||||
public class GraphGUI extends JFrame {
|
||||
|
||||
/** the height of the frame */
|
||||
private final int HEIGHT = 550;
|
||||
|
||||
/** the width of the frame */
|
||||
private final int WIDTH = 640;
|
||||
|
||||
/** the JPanel that does all of the work */
|
||||
private GraphScreen graphscreen;
|
||||
|
||||
/** the status bar */
|
||||
private JLabel information;
|
||||
|
||||
/**
|
||||
* The default constructor. <BR>
|
||||
* Preconditions: None. <BR>
|
||||
* Postconditions: Sets up the window and displays everything. <BR>
|
||||
*/
|
||||
public GraphGUI() {
|
||||
super ( "GraphGUI" );
|
||||
setSize ( WIDTH, HEIGHT );
|
||||
getContentPane().setLayout ( new BorderLayout() );
|
||||
|
||||
addWindowListener ( new WindowAdapter() {
|
||||
public void windowClosing ( WindowEvent event ) {
|
||||
System.exit ( 0 );
|
||||
}
|
||||
});
|
||||
|
||||
/* Center the window in the middle of the screen */
|
||||
Dimension screensize = getToolkit().getScreenSize();
|
||||
int screenwidth = screensize.width;
|
||||
int screenheight = screensize.height;
|
||||
setLocation ( screenwidth / 2 - WIDTH / 2, screenheight / 2 - HEIGHT / 2);
|
||||
|
||||
/* These are the individual menu items in the menu bar. */
|
||||
JMenuItem cleargraph = new JMenuItem ( new ImageIcon ( "ClearGraph.jpg" ) );
|
||||
cleargraph.setBackground ( Color.black );
|
||||
cleargraph.setToolTipText ( "Makes a new, empty, pretty graph." );
|
||||
cleargraph.addActionListener ( new ActionListener() {
|
||||
public void actionPerformed ( ActionEvent event ) {
|
||||
graphscreen.clearGraph();
|
||||
}
|
||||
});
|
||||
JMenuItem shortestpath = new JMenuItem ( new ImageIcon ( "ShortestPath.jpg" ) );
|
||||
shortestpath.setBackground ( Color.black );
|
||||
shortestpath.setToolTipText ( "Determines the shortest path between two vertices." );
|
||||
shortestpath.addActionListener ( new ActionListener() {
|
||||
public void actionPerformed ( ActionEvent event ) {
|
||||
graphscreen.findShortestPath();
|
||||
}
|
||||
});
|
||||
JMenuItem quit = new JMenuItem ( new ImageIcon ( "Quit.jpg" ) );
|
||||
quit.setBackground ( Color.black );
|
||||
quit.setToolTipText ( "All your base are belong to us." );
|
||||
quit.addActionListener ( new ActionListener() {
|
||||
public void actionPerformed ( ActionEvent event ) {
|
||||
System.exit ( 0 );
|
||||
}
|
||||
});
|
||||
|
||||
/* the menu that keeps the menuitems */
|
||||
JMenu graph = new JMenu ( "GraphGUI" );
|
||||
graph.add ( cleargraph );
|
||||
graph.add ( shortestpath );
|
||||
graph.add ( quit );
|
||||
JMenuBar toolbar = new JMenuBar();
|
||||
toolbar.add ( graph );
|
||||
setJMenuBar ( toolbar );
|
||||
|
||||
/* set up the two remaining graphical components */
|
||||
information = new JLabel ( "Ready" );
|
||||
graphscreen = new GraphScreen ( information );
|
||||
|
||||
getContentPane().add ( graphscreen, BorderLayout.CENTER );
|
||||
getContentPane().add ( information, BorderLayout.SOUTH );
|
||||
|
||||
setResizable ( false );
|
||||
setVisible ( true );
|
||||
}
|
||||
|
||||
/** Start the party */
|
||||
public static void main ( String[] args ) {
|
||||
GraphGUI mygraph = new GraphGUI();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,142 @@
|
|||
import java.util.*;
|
||||
|
||||
public interface GraphInterface
|
||||
{
|
||||
|
||||
//two constructors
|
||||
//default constructor makes a directed graph
|
||||
//constructor that takes a boolean (true for directed)
|
||||
|
||||
|
||||
/**
|
||||
* Makes the current graph empty.<br>
|
||||
* Preconditions: None.<br>
|
||||
* Postconditions: makes graph empty.<br>
|
||||
* Throws: None.
|
||||
*/
|
||||
public void makeEmpty();
|
||||
|
||||
/**
|
||||
* Indicates if graph is empty.<br>
|
||||
* Preconditions: None.<br>
|
||||
* Postconditions: returns boolean true if graph is empty, false if not.<br>
|
||||
* Throws: None.
|
||||
*/
|
||||
public boolean isEmpty();
|
||||
|
||||
/**
|
||||
* Returns an integer corresponding to thenumber of vertices in the graph.<br>
|
||||
* Preconditions: None.<br>
|
||||
* Postconditions: returns int.<br>
|
||||
* THrows: None.
|
||||
*/
|
||||
public int numVertices();
|
||||
|
||||
/**
|
||||
* Returns an integer corresponding to the numberof edges in the graph.<br>
|
||||
* Preconditions: None.<br>
|
||||
* Postconditions: returns int.<br>
|
||||
* Throws: NOne.
|
||||
*/
|
||||
public int numEdges();
|
||||
|
||||
/**
|
||||
* Adds a vertex to the graph.<br>
|
||||
* Preconditions: Must be passed GraphNode to be inserted into the graph.<br>
|
||||
* Postconditions: Adds the passed-in node to the graph.<br>
|
||||
* Throws: None.
|
||||
*/
|
||||
|
||||
//add a vertex to the Graph
|
||||
public void addVertex(GraphNode myItem) throws GraphException;
|
||||
|
||||
/**
|
||||
*Adds an edge to the Graph.<br>
|
||||
*Preconditions: must be passed the searchkeys of the nodes that are to be connected.<br>
|
||||
*Postconditions: adds edge to graph.<br>
|
||||
*Throws: GraphException if searchkeys don't exist.
|
||||
*/
|
||||
|
||||
public void addEdge(Comparable searchKey1, Comparable searchKey2) throws GraphException;
|
||||
|
||||
/**
|
||||
* Adds a weighted edge to the graph.<br>
|
||||
* Preconditions: must be passed two search keys and a weight.<br>
|
||||
* Postconditions: adds weighted edge to the graph.<br>
|
||||
* Throws: GraphException if given invalid endpoints or weight value
|
||||
*/
|
||||
|
||||
public void addEdge(Comparable searchKey1, Comparable searchKey2, double weight) throws GraphException;
|
||||
|
||||
/**
|
||||
* Retrieves the weight of a given edge. <br>
|
||||
* Preconditions: must be given searchkeys of the endpoints of the edge.<br>
|
||||
* Postconditions: returns double value for the weight.<br>
|
||||
* Throws: GraphException if given invalid endpoints.
|
||||
*/
|
||||
|
||||
public double getWeight(Comparable searchKey1, Comparable searchKey2) throws GraphException;
|
||||
|
||||
/**
|
||||
* Removes an edge from the graph.<br>
|
||||
* Preconditions: must be passed searchKey valued for edge's endpoints.<br>
|
||||
* Postconditions: removes edge from graph.<br>
|
||||
* Throws: GraphException if invalid vertices.
|
||||
*/
|
||||
|
||||
public void removeEdge(Comparable searchKey1, Comparable searchKey2) throws GraphException;
|
||||
|
||||
/**
|
||||
* Removes a vetex from the graph.<br>
|
||||
* Preconditions: must be passed a searchKey to delete.<br>
|
||||
* Postconditions: removes given searchKey.<br>
|
||||
* Throws: GraphException if given invalid searchkey.
|
||||
*/
|
||||
|
||||
public GraphNode removeVertex(Comparable searchKey) throws GraphException;
|
||||
|
||||
/**
|
||||
* Gets vertex from graph.<br>
|
||||
* Preconditions: must be passed a valid searchKey.<br>
|
||||
* Postconditions: returns a graphNode for the given searchKey.<br>
|
||||
* Throws: GraphException if given an invaid searchKey.
|
||||
*/
|
||||
|
||||
public GraphNode getVertex(Comparable searchKey) throws GraphException;
|
||||
|
||||
/**
|
||||
* Gets vertex from graph.<br>
|
||||
* Preconditions: must be passed integer index of node in list.<br>
|
||||
* Postconditions: returns GraphNode at given index.<br>
|
||||
* Throws: GraphException if given invalid index value.
|
||||
*/
|
||||
|
||||
public GraphNode getVertex(int index) throws GraphException;
|
||||
|
||||
/**
|
||||
* Obtains a depth-first search of the grap from the given starting vertex.<br>
|
||||
* Preconditions: must be passed a searchKey for the starting point of the search.<br>
|
||||
* Postconditions: returns ArrayList of vertices along the search path.<br>
|
||||
* Throws: GraphException if given invalid searchKey
|
||||
*/
|
||||
|
||||
public ArrayList dfs(Comparable searchKey) throws GraphException;
|
||||
|
||||
/**
|
||||
* Obtains a breadth-first search of the graph.<br>
|
||||
* Preconditions: must be passed searchKey of the starring point of the search.<br>
|
||||
* Postconditions: returns an ArrayList of the vertices in the search.<br>
|
||||
* Throws: GraphException if the searchKey is invalid.
|
||||
*/
|
||||
|
||||
public ArrayList bfs(Comparable searchKey) throws GraphException;
|
||||
|
||||
/**
|
||||
* Returns the shortest path between two vertices in the graph.<br>
|
||||
* Preconditions: must be passed searchKeys of the starting and ending vertices.<br>
|
||||
* Postconditions: returns an ArrayList of vertices between the starting and ending search Keys.<br>
|
||||
* Throws: GraphException if enteres searchKeys are invalid.
|
||||
*/
|
||||
public ArrayList shortestPath(Comparable searchKey1, Comparable searchKey2) throws GraphException;
|
||||
|
||||
}
|
|
@ -0,0 +1,81 @@
|
|||
/**
|
||||
* GraphNode.java, an object that stores information about a graph node for
|
||||
* Tree Applicatons.<br>
|
||||
* Extends: KeyedItem.<br>
|
||||
* Author: Matt Markham
|
||||
*/
|
||||
|
||||
public class GraphNode extends KeyedItem
|
||||
{
|
||||
private int xCoord, yCoord;
|
||||
boolean mark;
|
||||
|
||||
GraphNode (Comparable item)
|
||||
{
|
||||
super(item);
|
||||
mark=false;
|
||||
}
|
||||
|
||||
GraphNode (Comparable item, int x, int y)
|
||||
{
|
||||
super(item);
|
||||
xCoord=x;
|
||||
yCoord=y;
|
||||
mark=false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the x-coordinate of the current Graph Node.<br>
|
||||
* Preconditions: None.<br>
|
||||
* Postconditions: Returns int value of this nodes x position.<br>
|
||||
* Throws: None
|
||||
*/
|
||||
|
||||
|
||||
public int getX()
|
||||
{
|
||||
return xCoord;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the y-coordiante of the current Graph Node.<br>
|
||||
* Preconditions: None.<br>
|
||||
* Postconditions: Returns int value of this nodes y position.<br>
|
||||
* Throws: None
|
||||
*/
|
||||
|
||||
public int getY()
|
||||
{
|
||||
return yCoord;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if node is marked, false if it is not.<br>
|
||||
* Preconditions: None.<br>
|
||||
* Postconditions: returns true if node is marked, false if it is not.
|
||||
* Throws: None.
|
||||
*/
|
||||
|
||||
public boolean isMarked()
|
||||
{
|
||||
return mark;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sets value of mark to true or false.<br>
|
||||
* Preconditions: Must be passed in a boolean.<br>
|
||||
* Postconditions: Sets mark to passed-in boolean.<br>
|
||||
* Throws: None.
|
||||
*/
|
||||
|
||||
public void setMarked(boolean setbool)
|
||||
{
|
||||
mark=setbool;
|
||||
}
|
||||
|
||||
public boolean equals (GraphNode node)
|
||||
{
|
||||
return ((node.getX() == xCoord)&&(node.getY()==yCoord) && (node.getKey().compareTo(this.getKey())==0));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,267 @@
|
|||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.awt.event.*;
|
||||
import java.util.*;
|
||||
import java.text.DecimalFormat;
|
||||
|
||||
/** This class defines a custom JPanel that will draw vertices, edges, and the shortest path of a Graph object. This custom JPanel is used because it is much easier to intercept x and y coordinates in this panel than in the frame and then having to compensate for the other graphical components. */
|
||||
|
||||
public class GraphScreen extends JPanel implements MouseListener {
|
||||
/** defines the radius of the vertices in pixels */
|
||||
private final int radius = 20;
|
||||
|
||||
/** the path of vertices for the currently displayed shortest path */
|
||||
private ArrayList path;
|
||||
|
||||
/** the graph to add vertices/edges to */
|
||||
private Graph mygraph;
|
||||
|
||||
/** the status bar in the parent jframe */
|
||||
private JLabel information;
|
||||
|
||||
/* a flag to check if you are calculating the shortest path */
|
||||
private boolean shortestpath;
|
||||
|
||||
/* a flag used to check if the mouseclick intercepted was the second in the series (add edge, shortest path) */
|
||||
private boolean issecondvertex;
|
||||
|
||||
/* the data stored in the first vertex clicked in the series */
|
||||
private Comparable firstvertex;
|
||||
|
||||
|
||||
/**
|
||||
* Default constructor for the GraphScreen panel. <BR>
|
||||
* Preconditions: A JLabel status bar in the parent JFrame. <BR>
|
||||
* Postconditions: Initializes all variables. <BR>
|
||||
*/
|
||||
public GraphScreen ( JLabel information ) {
|
||||
super ( true );
|
||||
this.information = information;
|
||||
addMouseListener ( this );
|
||||
mygraph = new Graph();
|
||||
mygraph.setShortestPathDisplay ( new ArrayList() );
|
||||
information.setText ( " Click to add vertex" );
|
||||
issecondvertex = false;
|
||||
firstvertex = null;
|
||||
shortestpath = false;
|
||||
}
|
||||
|
||||
/** mousePressed and mouseReleased could be used to move vertices around the graph,
|
||||
but as per explicitly stated in the program requirements, the GraphNodes have no
|
||||
setX ( int x ) and setY ( int y ) methods. */
|
||||
public void mousePressed ( MouseEvent event ) {}
|
||||
public void mouseReleased ( MouseEvent event ) {}
|
||||
|
||||
/** not used, just here to fully implement the MouseListener interface */
|
||||
public void mouseEntered ( MouseEvent event ) {}
|
||||
public void mouseExited ( MouseEvent event ) {}
|
||||
|
||||
/**
|
||||
* Intercepts a mouse click in the drawing window. <BR>
|
||||
* Preconditions: A mouse click. <BR>
|
||||
* Postconditions: This method could add a vertex, add an edge, or calculate where the shortest path needs to be based upon flags and user interaction. <BR>
|
||||
*/
|
||||
public void mouseClicked ( MouseEvent event ) {
|
||||
/* If it is a right mouse click, then we must add an edge */
|
||||
if ( SwingUtilities.isRightMouseButton ( event ) ) {
|
||||
/* the node that is contained within radius pixels of the MouseEvent */
|
||||
GraphNode temp = findVertex ( event.getX(), event.getY() );
|
||||
/* if temp is null then the user clicked in blank space */
|
||||
if ( temp != null ) {
|
||||
/* if this is the second right mouse click, and it is not the same vertex */
|
||||
if ( issecondvertex && firstvertex.compareTo ( temp.getKey() ) != 0 ) {
|
||||
/* lets add an edge, and hopefully it will work */
|
||||
try {
|
||||
addEdge ( firstvertex, temp.getKey() );
|
||||
information.setText ( " Edge added between " + firstvertex.toString() + " and " + temp.getKey().toString() );
|
||||
}
|
||||
/* error exists between keyboard and chair */
|
||||
catch ( GraphException exception ) {
|
||||
information.setText ( " Could not add the edge" );
|
||||
JOptionPane.showMessageDialog ( null, exception.toString(), "Exception caught", JOptionPane.WARNING_MESSAGE );
|
||||
}
|
||||
/* we will set all the flags to normal */
|
||||
issecondvertex = false;
|
||||
firstvertex = null;
|
||||
}
|
||||
/* this must be the first right click intercepted */
|
||||
else {
|
||||
/* save the data for use later */
|
||||
firstvertex = temp.getKey();
|
||||
issecondvertex = true;
|
||||
information.setText ( " Right click on another vertex to create an edge" );
|
||||
}
|
||||
}
|
||||
/* we don't care and set everything to normal since the user clicked in blank space */
|
||||
else {
|
||||
firstvertex = null;
|
||||
issecondvertex = false;
|
||||
information.setText ( " Right click on vertices to add and edge" );
|
||||
}
|
||||
}
|
||||
|
||||
/* not the right mouse button, so this could be shortest path or add a vertex */
|
||||
/* if the shortest path flag is set, we must find two different vertices */
|
||||
else if ( shortestpath ) {
|
||||
/* if there are less than 2 vertices in the graph, it is impossible to find the shortest path */
|
||||
if ( mygraph.numVertices() > 2 ) {
|
||||
GraphNode temp = findVertex ( event.getX(), event.getY() );
|
||||
/* if this is the second click and the user clicked on a node and the node is not the same node */
|
||||
if ( issecondvertex && temp != null && firstvertex.compareTo ( temp.getKey() ) != 0 ) {
|
||||
/* set the shortest path arraylist to the path in the graph */
|
||||
try {
|
||||
mygraph.setShortestPathDisplay ( mygraph.shortestPath ( firstvertex, temp.getKey() ) );
|
||||
information.setText ( " Shortest path is displayed in green" );
|
||||
repaint();
|
||||
}
|
||||
catch ( GraphException exception ) {
|
||||
JOptionPane.showMessageDialog ( null, exception.toString(), "Exception caught", JOptionPane.WARNING_MESSAGE );
|
||||
mygraph.setShortestPathDisplay ( new ArrayList() );
|
||||
information.setText ( " Could not create the shortest path" );
|
||||
}
|
||||
shortestpath = false;
|
||||
issecondvertex = false;
|
||||
firstvertex = null;
|
||||
}
|
||||
/* the user is clicking on blank space */
|
||||
else if ( temp == null ) {
|
||||
information.setText ( " You must first click on vertices" );
|
||||
shortestpath = false;
|
||||
issecondvertex = false;
|
||||
firstvertex = null;
|
||||
}
|
||||
/* must be the first click in the series then */
|
||||
else {
|
||||
firstvertex = temp.getKey();
|
||||
issecondvertex = true;
|
||||
information.setText ( " Click on the ending vertex of the path" );
|
||||
}
|
||||
}
|
||||
/* not enough vertices to make a shortest path */
|
||||
else {
|
||||
information.setText ( " There must be at least 2 vertices in the graph before calculating the shortest path" );
|
||||
shortestpath = false;
|
||||
firstvertex = null;
|
||||
issecondvertex = false;
|
||||
}
|
||||
}
|
||||
|
||||
/* well, the only thing left is to add a new vertex */
|
||||
else {
|
||||
/* if the user clicked in blank space for once */
|
||||
if ( findVertex ( event.getX(), event.getY() ) == null ) {
|
||||
information.setText ( " Click to add vertex" );
|
||||
shortestpath = false;
|
||||
issecondvertex = false;
|
||||
firstvertex = null;
|
||||
/* ask the user what they want to call it */
|
||||
String name = JOptionPane.showInputDialog ( null, "Enter name: ","Add new graph node", JOptionPane.QUESTION_MESSAGE );
|
||||
/* as long as the name appears somewhat valid anyways */
|
||||
if ( name != null && !name.equals ( "" ) ) {
|
||||
int x = event.getX(), y = event.getY();
|
||||
/* these if's check to make sure the user didn't click too close to the edge */
|
||||
if ( x + radius > getWidth() )
|
||||
x = getWidth() - radius;
|
||||
if ( x - radius < 0 )
|
||||
x = radius;
|
||||
if ( y - radius > getHeight() )
|
||||
y = getHeight() - radius;
|
||||
if ( y - radius < 0 )
|
||||
y = radius;
|
||||
try {
|
||||
mygraph.addVertex ( new GraphNode ( name, x, y ) );
|
||||
information.setText ( " Vertex added at (" + x + ", " + y + ")" );
|
||||
repaint();
|
||||
}
|
||||
catch ( Exception exception ) {
|
||||
JOptionPane.showMessageDialog ( null, exception.toString(), "Exception caught!", JOptionPane.WARNING_MESSAGE );
|
||||
information.setText ( " Vertex could not be added" );
|
||||
}
|
||||
}
|
||||
}
|
||||
/* the user clicked on a vertex */
|
||||
else {
|
||||
information.setText ( " Vertex already added at location" );
|
||||
JOptionPane.showMessageDialog ( null, "Vertex is already at that point!", "Waitaminit!", JOptionPane.WARNING_MESSAGE );
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Empties the graph and sets all flags to default values. <BR>
|
||||
* Preconditions: None. <BR>
|
||||
* Postconditions: Resets all internally used variables to default values. <BR>
|
||||
*/
|
||||
public void clearGraph() {
|
||||
mygraph.makeEmpty();
|
||||
information.setText ( " Click to add vertex" );
|
||||
mygraph.setShortestPathDisplay ( new ArrayList() );
|
||||
issecondvertex = false;
|
||||
firstvertex = null;
|
||||
shortestpath = false;
|
||||
repaint();
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to set the flag to find the shortest path. <BR>
|
||||
* Preconditions: None. <BR>
|
||||
* Postconditions: Sets the shortestpath flag to true. <BR>
|
||||
*/
|
||||
public void findShortestPath() {
|
||||
shortestpath = true;
|
||||
information.setText ( " Click on the starting vertex" );
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempts to locate a GraphNode within x +/- radius pixels and y +/- radius pixels of the given coordinate. <BR>
|
||||
* Preconditions: Two integers representing coordinates inside the GraphScreen. <BR>
|
||||
* Postconditions: Returns null if no GraphNode is close to the coord. or the GraphNode closest to that point. <BR>
|
||||
*/
|
||||
private GraphNode findVertex ( int x, int y ) {
|
||||
/* look through all of the nodes one by one */
|
||||
for ( int i = 0; i < mygraph.numVertices(); i++ ) {
|
||||
GraphNode result = mygraph.getVertex ( i );
|
||||
int tempx = result.getX();
|
||||
int tempy = result.getY();
|
||||
if ( tempx + radius >= x && tempx - radius <= x && tempy - radius <= y && tempy + radius >= y )
|
||||
return result;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an edge between two vertices. <BR>
|
||||
* Preconditions: Two comparable objects that are in the graph. <BR>
|
||||
* Postconditions: Adds an edge between the two vertices containing the comparable objects. <BR>
|
||||
*/
|
||||
public void addEdge ( Comparable first, Comparable second ) {
|
||||
String temp = JOptionPane.showInputDialog ( null, "Enter a weight", "Add an edge", JOptionPane.QUESTION_MESSAGE );
|
||||
double result = -1.0;
|
||||
if ( temp != null ) {
|
||||
try {
|
||||
result = Double.parseDouble ( temp );
|
||||
if ( result < 0 )
|
||||
throw new GraphException ( "Invalid weight for edge." );
|
||||
mygraph.addEdge ( first, second, result );
|
||||
information.setText ( " New edge added between vertices {" + (String) first + "} and {" + (String) second + "}" );
|
||||
repaint();
|
||||
}
|
||||
catch ( Exception exception ) {
|
||||
information.setText ( " Edge could not be added" );
|
||||
JOptionPane.showMessageDialog ( null, exception.toString(), "Exception Caught", JOptionPane.WARNING_MESSAGE );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Draws the background for the custom JPanel. <BR>
|
||||
*/
|
||||
public void paint ( Graphics g ) {
|
||||
/* draw a black background */
|
||||
g.setColor ( Color.black );
|
||||
g.fillRect ( 0, 0, this.getWidth(), this.getHeight() );
|
||||
mygraph.draw ( g, radius );
|
||||
}
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
public abstract class KeyedItem
|
||||
{
|
||||
private Comparable searchKey;
|
||||
|
||||
public KeyedItem(Comparable key)
|
||||
{
|
||||
searchKey = key;
|
||||
} // end constructor
|
||||
|
||||
public Comparable getKey()
|
||||
{
|
||||
return searchKey;
|
||||
} // end getKey
|
||||
|
||||
public String toString()
|
||||
{
|
||||
return searchKey.toString();
|
||||
}
|
||||
|
||||
} // end KeyedItem
|
||||
|
||||
|
||||
/*
|
||||
How to use:
|
||||
public class CD extends KeyedItem
|
||||
{
|
||||
//title not present here
|
||||
String artist;
|
||||
...
|
||||
public CD(String title, String artist, double price, int tracks)
|
||||
{
|
||||
super(title);
|
||||
this.artist=artist;
|
||||
...
|
||||
}
|
||||
|
||||
}
|
||||
*/
|
|
@ -0,0 +1,39 @@
|
|||
public class Node
|
||||
{
|
||||
private Object item;
|
||||
private Node next; //reference to another node
|
||||
|
||||
public Node(Object item)
|
||||
{
|
||||
this.item = item;
|
||||
next = null;
|
||||
} // end constructor
|
||||
|
||||
public Node(Object item, Node next)
|
||||
{
|
||||
this.item = item;
|
||||
this.next = next;
|
||||
} // end constructor
|
||||
|
||||
public void setItem(Object item)
|
||||
{
|
||||
this.item = item;
|
||||
} // end setItem
|
||||
|
||||
public Object getItem()
|
||||
{
|
||||
return item;
|
||||
} // end getItem
|
||||
|
||||
public void setNext(Node next)
|
||||
{
|
||||
this.next = next;
|
||||
} // end setNext
|
||||
|
||||
public Node getNext()
|
||||
{
|
||||
return next;
|
||||
} // end getNext
|
||||
|
||||
} // end class Node
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
public class QueueException extends RuntimeException
|
||||
{
|
||||
public QueueException(String s)
|
||||
{
|
||||
super(s);
|
||||
} // end constructor
|
||||
} // end QueueException
|
|
@ -0,0 +1,57 @@
|
|||
public interface QueueInterface
|
||||
{
|
||||
/**
|
||||
* Determines whether a queue is empty.
|
||||
* Precondition: None.
|
||||
* Postcondition: Returns true if the queue is empty;
|
||||
* otherwise returns false.
|
||||
*/
|
||||
public boolean isEmpty();
|
||||
|
||||
/**
|
||||
* Adds an item at the back of a queue.
|
||||
* Precondition: item is the item to be inserted.
|
||||
* Postcondition: If the operation was successful, newItem
|
||||
* is at the back of the queue. Some implementations
|
||||
* may throw QueueException if item cannot be added to the queue.
|
||||
*/
|
||||
public void enqueue(Object item) throws QueueException;
|
||||
|
||||
/**
|
||||
* Retrieves and removes the front of a queue.
|
||||
* Precondition: None.
|
||||
* Postcondition: If the queue is not empty, the item
|
||||
* that was added to the queue earliest is returned and
|
||||
* the item is removed. If the queue is empty, the
|
||||
* operation is impossible and QueueException is thrown.
|
||||
*/
|
||||
public Object dequeue() throws QueueException;
|
||||
|
||||
/**
|
||||
* Removes all items of a queue.
|
||||
* Precondition: None.
|
||||
* Postcondition: The queue is empty.
|
||||
*/
|
||||
public void dequeueAll();
|
||||
|
||||
/**
|
||||
* Retrieves the item at the front of a queue.
|
||||
* Precondition: None.
|
||||
* Postcondition: If the queue is not empty, the item
|
||||
* that was added to the queue earliest is returned.
|
||||
* If the queue is empty, the operation is impossible
|
||||
* and QueueException is thrown.
|
||||
*/
|
||||
public Object peek() throws QueueException;
|
||||
|
||||
/**
|
||||
* Determines the length of a queue.
|
||||
* Precondition: None.
|
||||
* Postcondition: Returns the number of items that are
|
||||
* currently in the queue.
|
||||
* Throws: None.
|
||||
*/
|
||||
public int size();
|
||||
|
||||
|
||||
} // end QueueInterface
|
|
@ -0,0 +1,92 @@
|
|||
public class QueueReferenceBased implements QueueInterface
|
||||
{
|
||||
// circular references
|
||||
private Node tail;
|
||||
private int size;
|
||||
|
||||
public QueueReferenceBased()
|
||||
{
|
||||
tail = null;
|
||||
size=0;
|
||||
} // end default constructor
|
||||
|
||||
// queue operations:
|
||||
public boolean isEmpty()
|
||||
{
|
||||
return tail == null;
|
||||
} // end isEmpty
|
||||
|
||||
public int size()
|
||||
{
|
||||
return size;
|
||||
}
|
||||
|
||||
public void dequeueAll()
|
||||
{
|
||||
if (tail!=null)
|
||||
tail.setNext(null);
|
||||
|
||||
tail = null;
|
||||
size=0;
|
||||
} // end dequeueAll
|
||||
|
||||
public void enqueue(Object item)
|
||||
{
|
||||
Node myNode = new Node(item);
|
||||
|
||||
// insert the new node
|
||||
if (isEmpty())
|
||||
{
|
||||
// insertion into empty queue
|
||||
myNode.setNext(myNode);
|
||||
}
|
||||
else
|
||||
{
|
||||
// insertion into nonempty queue
|
||||
myNode.setNext(tail.getNext());
|
||||
tail.setNext(myNode);
|
||||
} // end if
|
||||
|
||||
tail = myNode; // new node is at back
|
||||
size++;
|
||||
} // end enqueue
|
||||
|
||||
public Object dequeue() throws QueueException
|
||||
{
|
||||
if (!isEmpty())
|
||||
{
|
||||
// queue is not empty; remove front
|
||||
Node head = tail.getNext();
|
||||
if (head == tail)
|
||||
{ // special case?
|
||||
tail.setNext(null);
|
||||
tail = null; // yes, one node in queue
|
||||
}
|
||||
else
|
||||
{
|
||||
tail.setNext(head.getNext());
|
||||
} // end if
|
||||
size--;
|
||||
return head.getItem();
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new QueueException("Queue empty");
|
||||
} // end if
|
||||
} // end dequeue
|
||||
|
||||
public Object peek() throws QueueException
|
||||
{
|
||||
if (!isEmpty())
|
||||
{
|
||||
// queue is not empty; retrieve front
|
||||
Node head = tail.getNext();
|
||||
return head.getItem();
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new QueueException("Queue empty");
|
||||
} // end if
|
||||
} // end peek
|
||||
|
||||
} // end QueueCircular
|
Binary file not shown.
After Width: | Height: | Size: 4.1 KiB |
Reference in New Issue