I'm trying to create a balanced tree with a string of letters. If you put "ABCDE" for string, your code is expected to give an output something like this.
INPUT : "ABCDE"
OUTPUT :
.......................................................
+
+ E
+ + -- --
A B C D -- -- -- --
.......................................................
The book suggests me to first create an array of one-node tree whose root will be each character of the string. Then, make a three-node tree out of each pair of one-node trees, making a new + node for the root which will result in a forest of three - node trees.
I know this problem is a stepping-stone to ultimately write the Huffman tree.
I'm having trouble putting the three-node tree back into the array with one-node trees and then make a 7-node tree by combining the two three-node trees and so on.
Below is my code,
import java.util.*; // for Stack class
class StringNode {
public char iData; // data item (key)
public StringNode leftChild; // this node's left child
public StringNode rightChild; // this node's right child
StringNode(char d) {
iData = d;
}
public void displayNode() // display ourself
{
System.out.print('{');
System.out.print(iData);
System.out.print("} ");
}
} // end class Node
class STree {
private StringNode root; // first node of tree
public String sequence;
// -------------------------------------------------------------
public STree() // constructor
{
root = null;
} // no nodes in tree yet
public void makeBalanceTree() // creating a balanced tree
{
StringNode array[] = new StringNode[sequence.length()];
for (int i = 0; i < sequence.length(); i++)
array[i] =
new StringNode(sequence.charAt(i)); //fill array with node holding each character as key
STree forest[] = new STree[array.length]; //make a forest of trees
for (int j = 0; j < array.length; j++) { //store each node as the root of the tree
forest[j] = new STree();
forest[j].root = array[j];
}
int count = sequence.length();
while (count == 0) {}
}
public void displayTree() {
Stack globalStack = new Stack();
globalStack.push(root);
int nBlanks = 32;
boolean isRowEmpty = false;
System.out.println("......................................................");
while (isRowEmpty == false) {
Stack localStack = new Stack();
isRowEmpty = true;
for (int j = 0; j < nBlanks; j++) System.out.print(' ');
while (globalStack.isEmpty() == false) {
StringNode temp = (StringNode) globalStack.pop();
if (temp != null) {
System.out.print(temp.iData);
localStack.push(temp.leftChild);
localStack.push(temp.rightChild);
if (temp.leftChild != null || temp.rightChild != null) isRowEmpty = false;
} else {
System.out.print("--");
localStack.push(null);
localStack.push(null);
}
for (int j = 0; j < nBlanks * 2 - 2; j++) System.out.print(' ');
} // end while globalStack not empty
System.out.println();
nBlanks /= 2;
while (localStack.isEmpty() == false) globalStack.push(localStack.pop());
} // end while isRowEmpty is false
System.out.println("......................................................");
} // end displayTree()
} // end class Tree
public class StringTreeApp {
public static void main(String[] args) {
int value;
STree theTree = new STree();
theTree.sequence = "ABCDE";
theTree.makeBalanceTree();
theTree.displayTree();
} // end main()
} // end class TreeApp
I think that the book is making it harder for you than necessary by recommending creating an array of StringNodes up front.
If you have a String, you know that the "middle" character is going to be the iData; the characters preceding it are going to be in the left tree; the characters following it are going to be in the right tree.
As such, you should be able to construct a StringNode as follows:
StringNode buildStringNode(String sequence) {
if (sequence.isEmpty()) return null;
int middlePos = (sequence.length() + 1) / 2;
char iData = sequence.charAt(middlePos);
StringNode result = new StringNode(iData);
result.leftChild = buildStringNode(sequence.substring(0, middlePos));
result.rightChild = buildStringNode(sequence.substring(middlePos + 1));
return result;
}
This "automatically" combines the child trees with the parent tree. Your makeBalanceTree() method is then simply:
void makeBalanceTree() {
root = buildStringNode(sequence);
}
Related
I have a nearly fully functional program but I am not able to format the output correctly. I am in desperate need of help as my project is past due already.
I am a student working on a program that reads in a simple text file and creates a graph object of nodes from the input file. I am then, supposed to use a heap class to build the nodes into a Min-heap. Finally I am supposed to call a heap sort method to sort the nodes (preferably in descending order)
I believe that my methods are correct and that my data is being correctly built into a min heap and is being correctly sorted. The only problem I am having is formatting the output which should be simple but for some reason isn't. The idea is this:
my graph object contains 2 arrayLists the first is the unordered node list that was created from the input text file. The second is a blank arrayList that I am trying to copy nodes one at a time.
I am trying to use a for loop or a while loop to first copy one single node into the empty ArrayList then call my build heap method to build a Min heap of only 1 element, then call my sort method to sort the heap of 1 element. Then, I want to copy in a second node and again build a min heap of 2 elements and then call my sort method on the 2 element heap. Then, copy in a third node and build the heap with 3 nodes, and then call the sort on the 3 element heap, and so on and so forth until all elements have been copied into the array list and the full heap is built and the sort method is called on all elements.
My 3 element test file looks like this:
~ val X Y Z
Xerxes 0 ~ ~ ~
York -1 ~ ~ ~
Zardoz 1 ~ ~ ~
My 6 element test file looks like this:
~ val A B C D E F
Alfa 4 ~ ~ ~ ~ ~ ~
Bravo 6 ~ ~ ~ ~ ~ ~
Charlie -3 ~ ~ ~ ~ ~ ~
Delta -6 ~ ~ ~ ~ ~ ~
Echo 0 ~ ~ ~ ~ ~ ~
Foxtrot 55 ~ ~ ~ ~ ~ ~
the output should look something like this:
Heaps:
X
YX
YXZ
HeapSort:
YXZ
XZY
ZXY
I am using several "test" files including one with 3 elements and one with 6 elements.
My classes are as follows:
import java.io.*;
public class DelivB {
File inputFile;
File outputFile;
PrintWriter output;
Graph g;
public DelivB( File in, Graph gr ) {
inputFile = in;
g = gr;
// Get output file name.
String inputFileName = inputFile.toString();
String baseFileName = inputFileName.substring( 0, inputFileName.length()-4 ); // Strip off ".txt"
String outputFileName = baseFileName.concat( "_out.txt" );
outputFile = new File( outputFileName );
if ( outputFile.exists() ) { // For retests
outputFile.delete();
}
try {
output = new PrintWriter(outputFile);
writeGraphInfo(output);
//System.out.println("=============================\n" + "testing testing testing Deliv B Class");
}
catch (Exception x ) {
System.err.format("Exception: %s%n", x);
System.exit(0);
}
//System.out.println( "DelivB: To be implemented");
//System.out.println("\nDeliv B Class ++++++++++++++++++++++++++++++++++");
}
public Graph getG() {
return g;
}
public void setG(Graph g) {
this.g = g;
}
/** Read the file containing the Strings, line by line, then process each line as it is read.
**/
public void writeGraphInfo( PrintWriter output ) {
try {
// output the graph information.
// I chose to output it to the console as well as the file for debugging purposes.
System.out.println( "\n\n=========================================================================\n\n");
System.out.println( g );
output.println( g );
}
catch (Exception x ) {
System.err.format("ExceptionInner: %s%n", x);
System.exit(0);
}
output.close();
}
}
// NEXT CLASS
//===================================================
import java.util.*;
// A node of a graph for the Spring 2018 ICS 340 program
public class Node {
String name;
String val; // The value of the Node
String abbrev; // The abbreviation for the Node
ArrayList<Edge> outgoingEdges;
ArrayList<Edge> incomingEdges;
public Node( String theAbbrev ) {
setAbbrev( theAbbrev );
val = null;
name = null;
outgoingEdges = new ArrayList<Edge>();
incomingEdges = new ArrayList<Edge>();
}
public String getAbbrev() {
return abbrev;
}
public String getName() {
return name;
}
public String getVal() {
return val;
}
public ArrayList<Edge> getOutgoingEdges() {
return outgoingEdges;
}
public ArrayList<Edge> getIncomingEdges() {
return incomingEdges;
}
public void setAbbrev( String theAbbrev ) {
abbrev = theAbbrev;
}
public void setName( String theName ) {
name = theName;
}
public void setVal( String theVal ) {
val = theVal;
}
public void addOutgoingEdge( Edge e ) {
outgoingEdges.add( e );
}
public void addIncomingEdge( Edge e ) {
incomingEdges.add( e );
}
}
//NEXT CLASS ==================================================
//import java.util.*;
// Edge between two nodes
public class Edge {
String label;
Node tail;
Node head;
public Edge( Node tailNode, Node headNode, String theLabel ) {
setLabel( theLabel );
setTail( tailNode );
setHead( headNode );
}
public String getLabel() {
return label;
}
public Node getTail() {
return tail;
}
public Node getHead() {
return head;
}
public void setLabel( String s ) {
label = s;
}
public void setTail( Node n ) {
tail = n;
}
public void setHead( Node n ) {
head = n;
}
}
//NEXT CLASS ===================================================
import java.util.*;
public class Heap
{
int heapSize;
Graph gr;
ArrayList<Node> unordered_nodelist;
ArrayList<Node> ordered_nodelist;
Node dummy = new Node("dummy node");
//constructor for heap object with the following attributes:
//a graph object and an int representing the size of an arraylist of nodes
public Heap(Graph g)
{
unordered_nodelist = g.getNodeList();
heapSize = unordered_nodelist.size();
ordered_nodelist = new ArrayList<Node>();
//for (int i = 0; i < heapSize; i++)
//ordered_nodelist.add(dummy);
//probably don't need this graph variable
gr = g;
}
//getters and setters
public ArrayList<Node> getUnordered_nodelist() {
return unordered_nodelist;
}
public void setUnordered_nodelist(ArrayList<Node> unordered_nodelist) {
this.unordered_nodelist = unordered_nodelist;
}
public ArrayList<Node> getOrdered_nodelist() {
return ordered_nodelist;
}
public void setOrdered_nodelist(ArrayList<Node> ordered_nodelist) {
this.ordered_nodelist = ordered_nodelist;
}
public int getHeapSize() {
return heapSize;
}
public void setHeapSize(int heapSize) {
this.heapSize = heapSize;
}
//heap methods
public int Parent(ArrayList<Node> A, int i)
{
//if (i == 1)
//return (Integer)null;
if (i%2 != 0)
return i/2;
else
return (i-1)/2;
}
public int Left(ArrayList<Node> A, int i)
{
//while (A.get(i).getVal() != null && A.get(i).getName() != null)
//{
//if (2*i < heapSize)
return (2*i)+1;
//else
//return (Integer)null;
//}
}
public int Right(ArrayList<Node> A, int i)
{
//if ((2*i)+1 < heapSize)
return 2*i+2;
//else
//return (Integer)null;
}
public void Heapify(ArrayList<Node> A, int i)
{
Node smallest;
Node temp;
int index;
int l = Left(A,i);
int r = Right(A,i);
while (A.get(i).getVal() != null && A.get(i).getName() != null)
{
if (l <= heapSize-1 && Integer.parseInt(A.get(l).getVal()) < Integer.parseInt(A.get(i).getVal()))
{
//left child is smaller
smallest = A.get(l);
index = l;
}
else
{
//parent node is smaller
smallest = A.get(i);
index = i;
}
if (r <= heapSize-1 && Integer.parseInt(A.get(r).getVal()) < Integer.parseInt(smallest.getVal()))
{
//right child is smaller
smallest = A.get(r);
index = r;
}
if (index != i)
{
//if the smallest element is not the parent node
//swap the smallest child with the parent
temp = A.get(i);
A.set(i, A.get(index));
A.set(index, temp);
//recursively call heapify method to check next parent/child relationship
Heapify(A, index);
}
}
}
//method to construct min heap from unordered arraylist of nodes
public void Build_min_Heap(ArrayList<Node> A)
{
for (int k = 0; k<A.size()-1; k++)
{
//while (A.get(k).getVal() != null && A.get(k).getName() != null)
//{
int i;
int heapSize = A.size();
for (i = (heapSize/2); i>=0; i--)
{
Heapify(A, i);
System.out.print(gr.toString2()+"\n");
}
//}
}
}
//decreases the value of a given node, used with insert method
public void heap_Decrease_Key(ArrayList<Node> A, int i, int key)
{
Node parent;
Node child;
Node temp;
if (key > i)
{
System.out.println("error key must be less than i");
//break;
}
A.get(i).setVal(Integer.toString(key));
while(i>0 && Integer.parseInt(A.get(Parent(A,i)).getVal()) > Integer.parseInt(A.get(i).getVal()) )
{
parent = A.get(Parent(A,i));
child = A.get(i);
temp = parent;
//take the child node and place it in the parent node's place
A.set(Parent(A,i), child);
//take the parent node and place it in the child node's place
A.set(i, temp);
}
}
//method to sort in descending order, a min heap
public void heap_Sort(ArrayList<Node> A)
{
Node temp;
for (int k = 0; k<A.size()-1; k++)
{
//while (A.get(k).getVal() != null && A.get(k).getName() != null)
//{
Build_min_Heap(A);
System.out.println(gr.toString2()+"\n");
for(int i = A.size()-1; i >= 1; i--)
{
//exchange a[1] with a[i]
temp = A.get(0);
A.set(0, A.get(i));
A.set(i, temp);
//decrement heapSize
heapSize--;
//recursive heapify call
Heapify(A, 0);
}
//}
}
}
public Node heap_Extract(ArrayList<Node> A)
{
Node min;
min = A.get(0);
A.set(0, A.get(heapSize-1));
//decrement heapSize
heapSize--;
Heapify(A, 0);
return min;
}
public void heap_Insert(ArrayList<Node> A, int key)
{
heapSize++;
A.get(heapSize-1).setVal(Integer.toString(2147483647));
heap_Decrease_Key(A, heapSize-1, key);
}
public String toString()
{
String s = "Graph g.\n";
//s += "Heaps: \n";
if ( ordered_nodelist.size() > 0 )
{
//for loop to traverse an ArrayList of Nodes
for(Node n : ordered_nodelist)
{
//output string to print each node's character abbreviation
String t = n.getAbbrev();
s = s.concat(t);
}
}
return s;
}
}
//NEXT CLASS =================================================
import java.util.*;
public class Heap
{
int heapSize;
Graph gr;
ArrayList<Node> unordered_nodelist;
ArrayList<Node> ordered_nodelist;
Node dummy = new Node("dummy node");
//constructor for heap object with the following attributes:
//a graph object and an int representing the size of an arraylist of nodes
public Heap(Graph g)
{
unordered_nodelist = g.getNodeList();
heapSize = unordered_nodelist.size();
ordered_nodelist = new ArrayList<Node>();
//for (int i = 0; i < heapSize; i++)
//ordered_nodelist.add(dummy);
//probably don't need this graph variable
gr = g;
}
//getters and setters
public ArrayList<Node> getUnordered_nodelist() {
return unordered_nodelist;
}
public void setUnordered_nodelist(ArrayList<Node> unordered_nodelist) {
this.unordered_nodelist = unordered_nodelist;
}
public ArrayList<Node> getOrdered_nodelist() {
return ordered_nodelist;
}
public void setOrdered_nodelist(ArrayList<Node> ordered_nodelist) {
this.ordered_nodelist = ordered_nodelist;
}
public int getHeapSize() {
return heapSize;
}
public void setHeapSize(int heapSize) {
this.heapSize = heapSize;
}
//heap methods
public int Parent(ArrayList<Node> A, int i)
{
//if (i == 1)
//return (Integer)null;
if (i%2 != 0)
return i/2;
else
return (i-1)/2;
}
public int Left(ArrayList<Node> A, int i)
{
//while (A.get(i).getVal() != null && A.get(i).getName() != null)
//{
//if (2*i < heapSize)
return (2*i)+1;
//else
//return (Integer)null;
//}
}
public int Right(ArrayList<Node> A, int i)
{
//if ((2*i)+1 < heapSize)
return 2*i+2;
//else
//return (Integer)null;
}
public void Heapify(ArrayList<Node> A, int i)
{
Node smallest;
Node temp;
int index;
int l = Left(A,i);
int r = Right(A,i);
while (A.get(i).getVal() != null && A.get(i).getName() != null)
{
if (l <= heapSize-1 && Integer.parseInt(A.get(l).getVal()) < Integer.parseInt(A.get(i).getVal()))
{
//left child is smaller
smallest = A.get(l);
index = l;
}
else
{
//parent node is smaller
smallest = A.get(i);
index = i;
}
if (r <= heapSize-1 && Integer.parseInt(A.get(r).getVal()) < Integer.parseInt(smallest.getVal()))
{
//right child is smaller
smallest = A.get(r);
index = r;
}
if (index != i)
{
//if the smallest element is not the parent node
//swap the smallest child with the parent
temp = A.get(i);
A.set(i, A.get(index));
A.set(index, temp);
//recursively call heapify method to check next parent/child relationship
Heapify(A, index);
}
}
}
//method to construct min heap from unordered arraylist of nodes
public void Build_min_Heap(ArrayList<Node> A)
{
for (int k = 0; k<A.size()-1; k++)
{
//while (A.get(k).getVal() != null && A.get(k).getName() != null)
//{
int i;
int heapSize = A.size();
for (i = (heapSize/2); i>=0; i--)
{
Heapify(A, i);
System.out.print(gr.toString2()+"\n");
}
//}
}
}
//decreases the value of a given node, used with insert method
public void heap_Decrease_Key(ArrayList<Node> A, int i, int key)
{
Node parent;
Node child;
Node temp;
if (key > i)
{
System.out.println("error key must be less than i");
//break;
}
A.get(i).setVal(Integer.toString(key));
while(i>0 && Integer.parseInt(A.get(Parent(A,i)).getVal()) > Integer.parseInt(A.get(i).getVal()) )
{
parent = A.get(Parent(A,i));
child = A.get(i);
temp = parent;
//take the child node and place it in the parent node's place
A.set(Parent(A,i), child);
//take the parent node and place it in the child node's place
A.set(i, temp);
}
}
//method to sort in descending order, a min heap
public void heap_Sort(ArrayList<Node> A)
{
Node temp;
for (int k = 0; k<A.size()-1; k++)
{
//while (A.get(k).getVal() != null && A.get(k).getName() != null)
//{
Build_min_Heap(A);
System.out.println(gr.toString2()+"\n");
for(int i = A.size()-1; i >= 1; i--)
{
//exchange a[1] with a[i]
temp = A.get(0);
A.set(0, A.get(i));
A.set(i, temp);
//decrement heapSize
heapSize--;
//recursive heapify call
Heapify(A, 0);
}
//}
}
}
public Node heap_Extract(ArrayList<Node> A)
{
Node min;
min = A.get(0);
A.set(0, A.get(heapSize-1));
//decrement heapSize
heapSize--;
Heapify(A, 0);
return min;
}
public void heap_Insert(ArrayList<Node> A, int key)
{
heapSize++;
A.get(heapSize-1).setVal(Integer.toString(2147483647));
heap_Decrease_Key(A, heapSize-1, key);
}
public String toString()
{
String s = "Graph g.\n";
//s += "Heaps: \n";
if ( ordered_nodelist.size() > 0 )
{
//for loop to traverse an ArrayList of Nodes
for(Node n : ordered_nodelist)
{
//output string to print each node's character abbreviation
String t = n.getAbbrev();
s = s.concat(t);
}
}
return s;
}
}
//NEXT CLASS ===============================================
import java.util.*;
public class Graph {
ArrayList<Node> nodeList;
ArrayList<Edge> edgeList;
public Graph() {
nodeList = new ArrayList<Node>();
edgeList = new ArrayList<Edge>();
}
public ArrayList<Node> getNodeList() {
return nodeList;
}
public ArrayList<Edge> getEdgeList() {
return edgeList;
}
public void addNode( Node n ) {
nodeList.add( n );
}
public void addEdge( Edge e ) {
edgeList.add( e );
}
//overridden toString() method to output both Nodes and the edges incumbent upon them
public String toString() {
String s = "Graph g.\n";
if ( nodeList.size() > 0 ) {
//for loop to traverse an ArrayList of Nodes
for( Node n : nodeList ) {
//output string to print basic labels for each node
String t = "\nNode " + n.getName() + ", abbrev " + n.getAbbrev() + ", value " + n.getVal() + "\n";
s = s.concat(t);
//for loop to traverse an ArrayList of outgoing Edges incumbent upon
//the given node in each iteration of the outer for loop
for(Edge a : n.getOutgoingEdges()){
//output String to print data about each outgoing edge
String q = n.getName() + " has edge to: " + a.getHead().getName() + " labeled: " + a.getLabel() + "\n";
s = s.concat(q);
}
//for loop to traverse an ArrayList of incomming Edges incumbent upon
//the given node in each iteration of the outer for loop
for(Edge a : n.getIncomingEdges()){
//output string to print data about each incomming edge
String r = n.getName() + " has edge from: " + a.getTail().getName() + " labeled: " + a.getLabel() + "\n";
s = s.concat(r);
}
}
s = s.concat("\n");
}
return s;
}
public String toString2()
{
String s = "Graph g.\n";
if ( nodeList.size() > 0 )
{
//for loop to traverse an ArrayList of Nodes
for( Node n : nodeList )
{
//output string to print each node's mnemonic
String t = n.getAbbrev();
s = s.concat(t);
}
}
return s;
}
}
//NEXT CLASS ==============================================
import javax.swing.*;
import java.io.*;
import java.util.*;
import java.awt.*;
import java.awt.event.*;
/** ProgramA simply reads a file containing rows of space-separated Strings,
** your assignment is to print out those strings interpreted as a graph.
**
** #author
** Mike Stein
**/
public class Prog340 extends JPanel implements ActionListener {
private static final long serialVersionUID = 1L; // Keep Eclipse happy.
File inputFile;
File outputFile;
PrintWriter output;
JFileChooser fileChooser;
Graph g;
Heap h;
String[] comboBoxList; // For putting names in Combo Box
/** The main method instantiates a Prog340 class, which includes giving you a choice of things to do.
** The only one active now will be reading the graph file and having you parse it.
**
** #param args
** - Not used
**
** #throws FileNotFoundException
** - Thrown if the file selected is not found. Shouldn't happen with a FileChooser.
**/
public static void main(String[] args) throws FileNotFoundException {
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
/** Create and show the GUI.
** For thread safety, this method should be invoked from the event-dispatching thread.
**/
private static void createAndShowGUI() {
// Create and set up the window
JFrame frame = new JFrame("Prog340");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// Create and set up the content pane.
JComponent newContentPane = new Prog340();
newContentPane.setOpaque(true);; // content panes must be opaque
frame.setContentPane(newContentPane);;
// Display the window.
frame.pack();
frame.setVisible(true);
}
/** The constructor creates a new ProgramA object, and sets up the input and output files.
**/
public Prog340() {
super( new BorderLayout() );
try {
// I like the colorful FileChooser.
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
System.out.println( "Look and feel set.");
}
catch (Exception e) { // exit on exception.
System.err.format("Exception: %s%n", e);
System.exit(0);
}
fileChooser = new JFileChooser();
fileChooser.setDialogTitle("Choose a file");
// Start looking for files at the currect directory, not home.
fileChooser.setCurrentDirectory(new File("."));
inputFile = null;
g = new Graph();
// Select the action
comboBoxList = new String[8];
comboBoxList[0] = new String("prog340: Select file and read graph");
comboBoxList[1] = new String("Deliv A: Write Graph Info");
comboBoxList[2] = new String ("Deliv B: Run Heap methods on selected file");
comboBoxList[3] = new String ("Deliv C: TBD");
comboBoxList[4] = new String ("Deliv D: TBD");
comboBoxList[5] = new String ("Deliv E: TBD");
comboBoxList[6] = new String ("Deliv F: TBD");
comboBoxList[7] = new String ("exit");
JComboBox actionList = new JComboBox( comboBoxList );
actionList.setName("Action List");
actionList.setSelectedIndex(0);
actionList.addActionListener( this );
add( actionList, BorderLayout.PAGE_START );
}
// Listen to the Combo Box
public void actionPerformed( ActionEvent e ) {
JComboBox cb = (JComboBox)e.getSource();
String actionName = (String)cb.getSelectedItem();
int actionIndex = cb.getSelectedIndex();
switch( actionIndex ) {
case 0:{
g = new Graph();
readGraphInfo( g );
break;
}
case 1:
DelivA dA = new DelivA( inputFile, g );
break;
case 2:
{
int numElements = 1;
int j =0;
int k;
//rewritten switch statement case to make DelivB combo box work
g = new Graph();
readGraphInfo( g );
DelivB dB = new DelivB(inputFile, g);
h = new Heap(g);
System.out.println("unordered list: \n");
System.out.println(g.toString());
System.out.println("==========================================");
//h.Build_min_Heap(h.getOrdered_nodelist());
for (j = 0; j <= h.getHeapSize(); j++)
//while (j <= h.getHeapSize())
//for (Node n : h.getOrdered_nodelist())
{
//copy node elements from unordered arraylist to new empty arraylist
h.getOrdered_nodelist().add(h.getUnordered_nodelist().get(j));
System.out.println("unordered node list size is: " + h.getUnordered_nodelist().size()+ "\n");
System.out.println("ordered node list size is: " + h.getOrdered_nodelist().size());
System.out.println("\nvalue of j is: " + j + "\n");
System.out.println("Heaps: \n");
h.Build_min_Heap(h.getOrdered_nodelist());
System.out.println("after build heap call: \n" );
System.out.println(h.toString());
//System.out.println("\ngraph class toString method: \n");
//System.out.println(g.toString() + "\n");
//System.out.println(g.toString2());
System.out.println("HeapSort: \n");
h.heap_Sort(h.getOrdered_nodelist());
System.out.println("after heapsort call: \n");
System.out.println(h.toString());
j++;
//System.out.println("\n graph class toString method: \n");
//System.out.println(g.toString() + "\n");
//System.out.println(g.toString2());
//System.out.println("the"+j+"th element in the original array is: \n"+h.getOrdered_nodelist().get(j).getAbbrev());
//System.out.println("the"+j+"th element in the new array is: \n"+h.getUnordered_nodelist().get(j).getAbbrev());
//System.out.println("\n after build heap method call, the output is as follows: " + g.toString());
}
break;
}
case 3:
DelivC dC = new DelivC( inputFile, g );
break;
case 4:
DelivD dD = new DelivD( inputFile, g );
break;
case 5:
DelivE dE = new DelivE( inputFile, g );
break;
case 6:
DelivF dF = new DelivF( inputFile, g );
break;
case 7:
System.out.println( "Goodbye");
System.exit(0);
default:
System.out.println( "Invalid choice" );
System.exit(0);
}
}
/** Read the file containing the Strings, line by line, then process each line as it is read.
**/
public void readGraphInfo( Graph g ) {
try {
if (fileChooser.showOpenDialog(null) == JFileChooser.APPROVE_OPTION) {
// Instantiate the selected input and output files.
inputFile = fileChooser.getSelectedFile();
System.out.println( "Chosen file = " + inputFile + "\n");
}
// read text file
Scanner sc = new Scanner( inputFile );
// First line special: It contains "~", and "val", and the nodes with the edges.
String firstLine = sc.nextLine();
String[] splitString = firstLine.split( " +" );
// Ignore first two fields of first line, Every other field is a node.
for ( int i = 2; i < splitString.length; i++ ) {
Node n = new Node( splitString[i] );
g.addNode( n );
}
// Every other line gives the name and value of the Node, and any edges.
int nodeIndex = 0;
ArrayList<Node> nodeList = g.getNodeList();
while ( sc.hasNextLine() ) {
String nextLine = sc.nextLine();
splitString = nextLine.split(" +");
Node n = nodeList.get( nodeIndex );
n.setName( splitString[0] );
n.setVal( splitString[1] );
for ( int i = 2; i < splitString.length; i++ ) {
if ( !splitString[i].equals("~") ) {
Node head = nodeList.get(i-2);
Edge e = new Edge( n, head, splitString[i] );
g.addEdge( e );
n.addOutgoingEdge( e );
head.addIncomingEdge( e );
}
}
nodeIndex++;
}
sc.close();
}
catch (Exception x) {
System.err.format("ExceptionOuter: %s%n", x);
}
}
}
This is my code so far to find all of the nodes represented by char characters. I've been able to code how to get the root node's "(" and ")" using the helper method. However, i'm having a mind block when trying to integrate the helper method into the treeProcessor. In the treeProcessor method i'm trying to further delve into binary tree so that the end goal is to just print out the root node and sub trees.
public static ArrayList<String> paths = new ArrayList<>();
public static void main(String[] args)
{
String tree = "(a(b()())(c()()))";
//replace this line with a call to the treeProcessor
System.out.println(Arrays.toString(treeBreakdownHelper(tree)));//a, (b()()), (c()())
System.out.println();
System.out.println(paths);//prints every path found
}
//recursive method
public static void treeProcessor(String tree, String path)
{
//breakdown tree
//update path
//check if current element is leaf/last element
//if it is, add to ArrayList
//if not last element, run processor again on subtrees that are not empty
}
//valid tree:
//(a()())
//(a(b()())(c()()))
//helper method
public static String[] treeBreakdownHelper(String tree)
{
String[] temp = new String[3];
//0 = root
//1 = left tree
//2 = right tree
tree = tree.substring(1, tree.length()-1);
//System.out.println(tree);//test removal of outer parens
temp[0] = "" + tree.charAt(0);
tree = tree.substring(1);
//System.out.println(tree);//test removal of root node
int openCount = 0;
int middle = 0;
for(int i = 0; i < tree.length(); i++)
{
//System.out.println(openCount);
if(tree.charAt(i) == '(')
{
openCount++;
}
else if(tree.charAt(i) == ')')
{
openCount--;
}
if(openCount == 0)
{
middle = i;
break;
}
}
//System.out.println(middle);
//System.out.println(tree.substring(0,middle+1));
temp[1] = tree.substring(0,middle+1);
//System.out.println(tree.substring(middle+1));
temp[2] = tree.substring(middle+1);
return temp;
}
}
I have run into a problem converting pseudocode of Dijkstras algorithm into actual code. I was given and adjacency list such as "Location - adjacent location - distance to location," example for one node: AAA AAC 180 AAD 242 AAH 40.
My task was to read a file organized as adjacency list as described, and compute the shortest path from one node to another.
Here is the Dijkstra pseudocode:
void dijkstra( Vertex s )
{
for each Vertex v
{
v.dist = INFINITY;
v.known = false;
}
s.dist = 0;
while( there is an unknown distance vertex )
{
Vertex v = smallest unknown distance vertex;
v.known = true;
for each Vertex w adjacent to v
if( !w.known )
{
DistType cvw = cost of edge from v to w;
if( v.dist + cvw < w.dist )
{
// Update w
decrease( w.dist to v.dist + cvw );
w.path = v;
}
}
}
}
im having the most trouble with the line "for each Vertex w adjacent to v"
Here is my nonworking code:
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.LinkedList;
import java.util.List;
import java.util.ListIterator;
public class Dijkstra {
public static boolean isInteger(String s) {
return isInteger(s, 10);
}
public static boolean isInteger(String s, int radix) {
if (s.isEmpty())
return false;
for (int i = 0; i < s.length(); i++) {
if (i == 0 && s.charAt(i) == '-') {
if (s.length() == 1)
return false;
else
continue;
}
if (Character.digit(s.charAt(i), radix) < 0)
return false;
}
return true;
}
public static void dijkstra(Vertex[] a, Vertex s, int lineCount) {
int i = 0;
while (i < (lineCount)) // each Vertex v
{
a[i].dist = Integer.MAX_VALUE;
a[i].known = false;
i++;
}
s.dist = 0;
int min = Integer.MAX_VALUE; //
while (!(a[0].known == true && a[1].known == true && a[2].known == true && a[3].known == true
&& a[4].known == true && a[5].known == true && a[6].known == true && a[7].known == true
&& a[8].known == true && a[9].known == true && a[10].known == true && a[11].known == true
&& a[12].known == true)) {
System.out.println("here");
for (int b = 0; b < lineCount; b++) {
if (a[b].dist < min && a[b].known == false) {
min = a[b].dist;
}
}
int c = 0;
while (c < lineCount) {
if (a[c].dist == min && a[c].known == false) {
break;
}
c++;
}
System.out.println(min);
a[c].known = true;
int adjSize = a[c].adj.size();
int current = 0;
System.out.println(adjSize);
while (current < adjSize - 1) {
String currentAdjacent = (String) a[c].adj.get(current);
int p = 0;
while (p < lineCount) {
if (a[p].name.equals(currentAdjacent)) {
if (!a[p].known) {
String cvwString = (String) a[c].distance.get(current);
int cvw = Integer.parseInt(cvwString);
System.out.println(" This is cvw" + cvw);
System.out.println("Here2");
if (a[c].dist + cvw < a[p].dist) {
a[p].dist = a[c].dist + cvw;
a[p].path = a[c];
}
}
}
p++;
}
current++;
}
}
}
public static class Vertex {
public List adj; // Adjacency list
public List distance;
public boolean known;
public int dist; // DistType is probably int
public Vertex path;
public String name;
// Other fields and methods as needed
}
public static void printPath(Vertex v) {
if (v.path != null) {
printPath(v.path);
System.out.print(" to ");
}
System.out.print(v);
}
public static void main(String[] args) throws IOException {
int lineCounter = 0;
BufferedReader br = new BufferedReader(new FileReader("airport.txt"));
try {
StringBuilder sb = new StringBuilder();
String line = br.readLine();
while (line != null) {
sb.append(line);
sb.append(System.lineSeparator());
line = br.readLine();
lineCounter = lineCounter + 1;
}
Vertex[] arr = new Vertex[lineCounter];
for (int i = 0; i < lineCounter; i++) {
arr[i] = new Vertex();
arr[i].adj = new LinkedList<String>();
arr[i].distance = new LinkedList<Integer>();
}
;
//
int arrayCounter = 0;
String everything = sb.toString();
String[] lines = everything.split("\\s*\\r?\\n\\s*");
for (String line1 : lines) {
arr[arrayCounter] = new Vertex();
arr[arrayCounter].adj = new LinkedList<String>();
arr[arrayCounter].distance = new LinkedList<Integer>();
String[] result = line1.split("\\s+");
for (int x = 0; x < result.length; x++) {
if (x == 0) {
arr[arrayCounter].name = result[0];
continue;
} else if (isInteger(result[x])) {
arr[arrayCounter].distance.add(result[x]);
continue;
} else {
arr[arrayCounter].adj.add(result[x]);
continue;
}
}
arrayCounter++;
}
for (int i = 0; i < 12; i++) {
System.out.println(arr[i].name);
}
System.out.println(lineCounter);
dijkstra(arr, arr[3], lineCounter - 1);
printPath(arr[11]);
} finally {
br.close();
}
}
}
Using my vertex class as is I was using a series of while loops to first, traverse the adjacency strings stored in a linked list while comparing to see which vertex is equivalent to the adjacency list string. Is there a better way to code "for each Vertex w adjacent to v" using my Vertex class? And apologies ahead for messy code and any others style sins i may have committed. Thanks!
To solve this problem you need a bunch of "Node" objects, stored in a HashMap, keyed on Source Location.
In the node, you need a collection of references to adjacent "Node" objects (or at least their "key" so you can write logic against it. The "Node" also needs to know it's location and distance to each "adjacent" node. Think Lundon Underground Tube Maps - each station connects to at least one other station. Usually two or more. Therefore, adjacent nodes to tube stations are the immediate next stops you can get to from that station.
Once you have that data structure in place, you can then use a recursive routine to iterate through each individual node. It should then iterate through each child node (aka adjacent node), and track distances from the initial (source) node to the current node by storing this data in a HashMap and using the current accumulated distance whilst recursing (or "walking" the graph"). This tracking information should be part of your method signature when recursing. You will also need to track the current path you have taken when recursing, in order to avoid circular loops (which will ultimately and ironically cause a StackOverflowError). You can do this by using a HashSet. This Set should track the source and current node's location as the entry key. If you see this present during your recursion, then you have already seen it, so don't continue processing.
I'm not going to code the solution for you because I suspect that you ask more specific questions as you work your way through understanding the answer, which are very likely answered elsewhere.
I already build a binary search tree. The primitive data type I store in the tree is integer. I try to store it on a 2-D char array and then print it out as the graph shown below(the numbers represent row numbers and column numbers and I do not need to print it, ignoring "-" symbol please, I only use it to indicate the exact position)
-----0---1---2---3---4---5---6---7---8---9---10---11---12---13---14---15---16
0---------------------------------------12
1--------------------------------/-------------------\
2----------------------8--------------------------------------14
3-----------------/----------\ -----------------------------------------\
4-------------5----------------9-------------------------------------------34
5--------/-------------------------------------------------------------/-------------\
6---2---------------------------------------------------------24------------------------35
number 12 need to store on location [0][8], the middle of the first row.
number 4 store on[2][4], number 14=[2][12], 5=[4][2], 9=[4][9] and so on.
row number 1 which is second row, "/" is on position[1][6] and "\" is on position[1][10] etc.they are also on the middle between two numbers
following is my code
public class MainClass {
public static void main(String[] args) {
//level represents row number;
// start indicates the column I am going to
//store number in, and end is a fixed column number
// BinarySearchTree is a BinaryTree type instance,
// I already story integers on it and follow with the format
// of binary search trees, and I did tested it.
int level=0; int start=0; int end=80;
BinaryTree.plot(BinarySearchTree, level, start, end);
}
private static class BinaryTree {
private BinaryNode root;
static char[][] offset = new char [10][20];
public BinaryTree(){
root = null;
}
public BinaryTree(Object x){
root = new BinaryNode(x);
}
public boolean isEmpty(){
return root == null;
}
public Object getRootobj() throws BinaryTreeException{
if(root == null)
throw new BinaryTreeException("Empty Tree");
else
return root.element;
}
public BinaryTree getLeft() throws BinaryTreeException{
if(root == null)
throw new BinaryTreeException("Empty Tree");
else {
BinaryTree t = new BinaryTree();
t.root = root.left;
return t;
}
}
public BinaryTree getRight() throws BinaryTreeException{
if(root == null)
throw new BinaryTreeException("Empty Tree");
else {
BinaryTree t = new BinaryTree();
t.root = root.right;
return t;
}
}
public static void plot(BinaryTree t, int level, int start, int end){
if(!t.isEmpty()){
plot(t.getLeft(), level+2, start/2, end/2);
String string = Integer.toString((Integer)t.getRootobj());
for(char c: string.toCharArray())
offset[level][start++]=c;
if(!(t.getLeft().isEmpty()))
offset[++level][start/4*3] = '/';
if(!(t.getRight().isEmpty()))
offset[++level][((start+end)/2+start)/2] = '\\';
plot(t.getRight(), level+2, end/2, end);
}
for(int i = 0; i<10; i++){
for(int j= 0; j<20; j++)
System.out.print(offset[i][j]);
}
}
}
private static class BinaryNode {
Object element;
BinaryNode left,right;
BinaryNode() {
this(0);
}
BinaryNode(Object e) {
this(e, null, null);
}
BinaryNode(Object e, BinaryNode ln, BinaryNode m){
element=e;
left=ln;
right=m;
}
}
}
Question: the method plot I used to store and print out binarysearchtree did not work, which causes a java.lang.ArrayIndexOutOfBoundsException:
can anyone take a look at it. appreciated for the help.
Your fixed-size char-Array cannot cope with your dynamic sized BinaryTree. For your given example alone you need way more then 20 characters per line! That's where your Exception is coming from.
But to give you an idea of an alternative approach - even though it took a while, made the following additions to your code:
First, I added a method to the BinaryNode class:
int getDepth() {
int subTreeDepth;
if (left == null && right == null) {
subTreeDepth = 0;
} else if (left == null) {
subTreeDepth = right.getDepth();
} else if (right == null) {
subTreeDepth = left.getDepth();
} else {
subTreeDepth = Math.max(left.getDepth(), right.getDepth());
}
return 1 + subTreeDepth;
}
Second, I removed your fixed char-Array and replaced the whole plotting algorithm in your BinaryTree (I just couldn't wrap my head around all those relative array-index manipulations):
public void plot() {
if (root == null) {
throw new BinaryTreeException("Empty Tree");
}
int lineCount = 2 * root.getDepth() - 1;
StringBuilder[] lines = new StringBuilder[lineCount];
for (int lineIndex = 0; lineIndex < lineCount; lineIndex++) {
lines[lineIndex] = new StringBuilder();
}
// get the right most node (which contains the largest element value)
BinaryNode rightMostNode = root;
while (rightMostNode.right != null) {
rightMostNode = rightMostNode.right;
}
// check how many characters we have to reserve for a single node element
int maxElementLength = String.valueOf(rightMostNode.element).length();
plot(root, 0, 0, maxElementLength, lines);
for (StringBuilder singleLine : lines) {
System.out.println(singleLine.toString());
}
}
private void plot(BinaryNode subTreeRoot, int offset, int lineIndex, int elementLength, StringBuilder[] lines) {
int actualOffset;
if (subTreeRoot.left == null) {
actualOffset = offset;
} else {
actualOffset = offset + (int) Math.pow(2, subTreeRoot.left.getDepth() - 1) * elementLength;
}
StringBuilder currentLine = lines[lineIndex];
String elementValue = String.valueOf(subTreeRoot.element);
for (int lineFillIndex = currentLine.length() + elementValue.length() / 2; lineFillIndex < actualOffset; lineFillIndex++) {
currentLine.append(' ');
}
currentLine.append(elementValue);
if (subTreeRoot.left != null) {
// draw connection to left sub tree
int connectPosition = (actualOffset - offset) * 3 / 4 + offset;
StringBuilder connectLine = lines[lineIndex + 1];
for (int lineFillIndex = connectLine.length(); lineFillIndex < connectPosition; lineFillIndex++) {
connectLine.append(' ');
}
connectLine.append('/');
// insert the left part of the next value line
plot(subTreeRoot.left, offset, lineIndex + 2, elementLength, lines);
}
if (subTreeRoot.right != null) {
// draw connection to right sub tree
int connectPosition = actualOffset + elementLength - elementValue.length() / 2;
if (subTreeRoot.right.left != null) {
connectPosition += (int) Math.pow(2, subTreeRoot.right.left.getDepth() - 1) * elementLength / 2;
}
StringBuilder connectLine = lines[lineIndex + 1];
for (int lineFillIndex = connectLine.length(); lineFillIndex < connectPosition; lineFillIndex++) {
connectLine.append(' ');
}
connectLine.append('\\');
// insert the right part of the next value line
plot(subTreeRoot.right, actualOffset + elementLength, lineIndex + 2, elementLength, lines);
}
}
For a tree similar to the one, you included in your question:
BinaryTree binarySearchTree = new BinaryTree(
new BinaryNode(12,
new BinaryNode(8,
new BinaryNode(5,
new BinaryNode(3),
null),
new BinaryNode(9)),
new BinaryNode(14,
null,
new BinaryNode(34,
new BinaryNode(24),
new BinaryNode(35)))));
binarySearchTree.plot();
I get the following output:
12
/ \
8 14
/ \ \
5 9 34
/ / \
3 24 35
I'm very close to being done, but can't quite figure out how to tie everything together. I have the separate methods responsible for their particular task, but i feel like my cohesion is really bad. not real sure how they tie together and what needs to be called in main. The goal here is to read a text file from the command line and list the words in the story lexicographically.
% java Ten < story.txt
Word Occurs
==== ======
a 21
animal 3
.
.
.
zebra 1
%
Here's my code thus far:
import java.util.Scanner;
public class Ten2
{
public static void main(String [] arg)
{
Scanner input = new Scanner(System.in);
String word;
List sortedList = new List();
word = nextWord(input);
while (word!=null) {
sortedList.insert(word);
word = nextWord(input);
}
sortedList.printWords();
}
private static String nextWord(Scanner input)
{
// return null if there are no more words
if (input.hasNext() == false )
return null;
// take next element, convert to lowercase, store in s
else {
String s = input.next().toLowerCase() ;
// empty string
String token = "";
// loop through s and concatonate chars onto token
for (int i =0; i < s.length(); i++) {
if (Character.isLetter(s.charAt(i)) == true)
token = token + s.charAt(i);
else if (s.charAt(i) == '\'' )
token = token + s.charAt(i);
else if (s.charAt(i) == '-')
token = token + s.charAt(i);
}
return token;
}
}
}
class List
{
/*
* Internally, the list of strings is represented by a linked chain
* of nodes belonging to the class ListNode. The strings are stored
* in lexicographical order.
*/
private static class ListNode
{
// instance variables for ListNode objects
public String word;
public ListNode next;
public int count;
// Listnode constructor
public ListNode(String w, ListNode nxt)
{
word = w; // token from nextWord()?
next = nxt; // link to next ListNode
count = 1; // number of word occurences
}
}
// instance variables for List object
private ListNode first;
private int numWords;
// constructor postcondition: creates new Listnode storing object
public List()
{
first = null; // pointer to ListNode?
numWords = 0; // counter for nodes in list
}
// Insert a specified word into the list, keeping the list
// in lexicographical order.
public void insert(String word)
{
// check if first is null
if (first == null) {
ListNode newNode;
newNode = addNode(word, null);
first = newNode;
}
// else if (first is not null) check if word matches first word in List
else if (word.equals(first.word)) {
// increase count
first.count++;
}
// else (first is not null && doesn't match first word)
else {
ListNode newNode;
ListNode current;
current = first;
ListNode previous;
previous = null;
int cmp = word.compareTo(current.word);
/*
* Fist two cases of empty list and word already existing
* handled in above if and else statements, now by using compareTo()
* method between the words, the insertion postion can be determined.
* Links between ListNode variables current and previous need to be
* modified in order to maintain the list
*/
// loop as long as value comparing to is positive
// when compareTo() returns positive this means the "word" parameter is greater than the word in the list
while ((cmp >0) && (current.next != null)) {
previous = current;
current = current.next;
cmp = word.compareTo(current.word);
}
// insert after current at end of list
if ((cmp >0 && current.next == null)) {
newNode = addNode(word, null);
current.next = newNode;
}
// increments count when word already exists
else if (cmp==0) {
current.count++;
}
// else (cmp < 0) we insert BEFORE current
else {
newNode = addNode(word, current);
// first node in list comes after new word
if (previous == null) {
first = newNode;
}
else {
// inserting new word in middle of list
previous.next = newNode;
}
}
}
}
// method to add new ListNode and increase counter
private ListNode addNode(String word, ListNode next)
{
ListNode newNode = new ListNode(word, next);
numWords++;
return newNode;
}
// Returns a string array that contains all the words in the list.
public String[] getWords()
{
String[] Words = new String[numWords];
ListNode current = first;
int i =0;
while (current != null) {
Words[i] = current.word;
current = current.next;
i++;
}
return Words;
}
// Returns an int array that contains the number of times
// each word occurs in the list.
public int[] getNumbers()
{
int[] Numbers = new int[numWords];
ListNode current = first;
int i =0;
while (current != null) {
Numbers[i] = current.count;
current = current.next;
i++;
}
return Numbers;
}
// Outputs the string array and int array containing all the
// words in the list and the number of times each occurs.
public void printWords()
{
int[] Numbers = getNumbers();
String[] Words = getWords();
System.out.println("Word \t \t Occurs");
System.out.println("==== \t \t ======");
for (int i =0; i < numWords; i++) {
System.out.println(Words[i] + " \t " + Numbers[i]);
}
}
}
Well, I would start by defining what you want your program to do, which you've already done:
The goal here is to read a text file from the command line and list the words in the story lexicographically.
You're main function does this almost. Basically, what you need is a loop to tie it together:
public static void main(String [] arg)
{
// print out your initial information first (i.e. your column headers)
// ...
List sortedList = new List();
String word = nextWord();
// now, the question is... what is the end condition of the loop?
// probably that there aren't any more words, so word in this case
// will be null
while (word != null)
{
sortedList.insert(word);
word = nextWord();
}
// now, your list takes care of the sorting, so let's just print the list
sortedList.printWords();
}
I think that's all there is to it. Normally, I don't like to post solutions to homework questions, but in this case, since you already had all of the code and you just needed a little nudge to drive you in the right direction, I think it's fine.
There are a few things I noticed that are incorrect with your
Your list constructor has a 'void' return type - there should be no return type on constructors:
public List() //make an empty list
{
first = null;
numWords = 0;
}
The 'else' statement in this method is unneeded:
public static String nextWord()
{
if ( keyboard.hasNext() == false )
return null;
else {
String start = keyboard.next().toLowerCase() ;
String organized = "";
for (int i =0; i < start.length(); i++) {
if (Character.isLetter(start.charAt(i)) == true)
organized = organized + start.charAt(i);
else if (start.charAt(i) == '\'' )
organized = organized + start.charAt(i);
else if (start.charAt(i) == '-')
organized = organized + start.charAt(i);
}
return organized;
}
}
So, this should be:
public static String nextWord()
{
if ( keyboard.hasNext() == false )
return null;
String start = keyboard.next().toLowerCase() ;
String organized = "";
for (int i =0; i < start.length(); i++) {
if (Character.isLetter(start.charAt(i)) == true)
organized = organized + start.charAt(i);
else if (start.charAt(i) == '\'' )
organized = organized + start.charAt(i);
else if (start.charAt(i) == '-')
organized = organized + start.charAt(i);
}
return organized;
}
If you want to use a BufferedReader, it's pretty easy. Just set it up in your main method:
if (arg.length > 0)
{
// open our file and read everything into a string buffer
BufferedReader bRead = null;
try {
bRead = new BufferedReader(new FileReader(arg[0]));
} catch(FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
System.exit(0);
}
setupScanner(bRead);
}
Then, create a new method that sets up the scanner object:
public static void setupScanner(BufferedReader rdr)
{
keyboard = new Scanner(rdr);
}
And then just pass it in on the command line (i.e. java ten2 [filename])
import java.util.Scanner;
public class Ten2
{
public static void main(String [] arg)
{
Scanner input = new Scanner(System.in);
String word;
List sortedList = new List();
word = nextWord(input);
while (word!=null) {
sortedList.insert(word);
word = nextWord(input);
}
sortedList.printWords();
}
private static String nextWord(Scanner input)
{
// return null if there are no more words
if (input.hasNext() == false )
return null;
// take next element, convert to lowercase, store in s
else {
String s = input.next().toLowerCase() ;
// empty string
String token = "";
// loop through s and concatonate chars onto token
for (int i =0; i < s.length(); i++) {
if (Character.isLetter(s.charAt(i)) == true)
token = token + s.charAt(i);
else if (s.charAt(i) == '\'' )
token = token + s.charAt(i);
else if (s.charAt(i) == '-')
token = token + s.charAt(i);
}
return token;
}
}
}
class List
{
/*
* Internally, the list of strings is represented by a linked chain
* of nodes belonging to the class ListNode. The strings are stored
* in lexicographical order.
*/
private static class ListNode
{
// instance variables for ListNode objects
public String word;
public ListNode next;
public int count;
// Listnode constructor
public ListNode(String w, ListNode nxt)
{
word = w; // token from nextWord()?
next = nxt; // link to next ListNode
count = 1; // number of word occurences
}
}
// instance variables for List object
private ListNode first;
private int numWords;
// constructor postcondition: creates new Listnode storing object
public List()
{
first = null; // pointer to ListNode?
numWords = 0; // counter for nodes in list
}
// Insert a specified word into the list, keeping the list
// in lexicographical order.
public void insert(String word)
{
// check if first is null
if (first == null) {
ListNode newNode;
newNode = addNode(word, null);
first = newNode;
}
// else if (first is not null) check if word matches first word in List
else if (word.equals(first.word)) {
// increase count
first.count++;
}
// else (first is not null && doesn't match first word)
else {
ListNode newNode;
ListNode current;
current = first;
ListNode previous;
previous = null;
int cmp = word.compareTo(current.word);
/*
* Fist two cases of empty list and word already existing
* handled in above if and else statements, now by using compareTo()
* method between the words, the insertion postion can be determined.
* Links between ListNode variables current and previous need to be
* modified in order to maintain the list
*/
// loop as long as value comparing to is positive
// when compareTo() returns positive this means the "word" parameter is greater than the word in the list
while ((cmp >0) && (current.next != null)) {
previous = current;
current = current.next;
cmp = word.compareTo(current.word);
}
// insert after current at end of list
if ((cmp >0 && current.next == null)) {
newNode = addNode(word, null);
current.next = newNode;
}
// increments count when word already exists
else if (cmp==0) {
current.count++;
}
// else (cmp < 0) we insert BEFORE current
else {
newNode = addNode(word, current);
// first node in list comes after new word
if (previous == null) {
first = newNode;
}
else {
// inserting new word in middle of list
previous.next = newNode;
}
}
}
}
// method to add new ListNode and increase counter
private ListNode addNode(String word, ListNode next)
{
ListNode newNode = new ListNode(word, next);
numWords++;
return newNode;
}
// Returns a string array that contains all the words in the list.
public String[] getWords()
{
String[] Words = new String[numWords];
ListNode current = first;
int i =0;
while (current != null) {
Words[i] = current.word;
current = current.next;
i++;
}
return Words;
}
// Returns an int array that contains the number of times
// each word occurs in the list.
public int[] getNumbers()
{
int[] Numbers = new int[numWords];
ListNode current = first;
int i =0;
while (current != null) {
Numbers[i] = current.count;
current = current.next;
i++;
}
return Numbers;
}
// Outputs the string array and int array containing all the
// words in the list and the number of times each occurs.
public void printWords()
{
int[] Numbers = getNumbers();
String[] Words = getWords();
System.out.println("Word \t \t Occurs");
System.out.println("==== \t \t ======");
for (int i =0; i < numWords; i++) {
System.out.println(Words[i] + " \t " + Numbers[i]);
}
}
}