I'm trying to fill in a binary search tree with a text file, but i'm having alot of trouble implementing my insert function. Am i reading the input correctly or is it my code?
Code for reading file:
import java.io.*;
import java.util.Scanner;
public class Driver {
public static void main(String[]args) throws IOException
{
//Checks if there is a correct number of arguments passed through the command line.
if (args.length != 1)
{
quitError("Tree command word arguments expected");
}
String inputFile = args[0];
BST btree = new BST();
try
{
BufferedReader input = new BufferedReader(new FileReader(inputFile));
//Scans each word from the input and prints it out
String word = input.readLine();
while (word != null)
{
btree.insert(word);
word = input.readLine();
}
return;
} catch(FileNotFoundException filenotfoundexception) //Catches file not found exception
{
System.out.println("File not found.");
}
catch(IOException ioexception) //Catches input/output exception
{
System.out.println("File input error occured!");
}
}
//Displays an error message, program exits
public static void quitError(String msg)
{
System.out.println(msg);
System.out.println("Program will now quit.");
System.exit(0);
}
}
Code for the binary search tree node:
public class BSTNode {
protected String data;
protected BSTNode left, right;
public BSTNode()
{
left = null;
right = null;
}
public BSTNode(String data)
{
this(data,null,null);
}
public BSTNode(String data, BSTNode lt, BSTNode rt)
{
this.data = data;
left = lt;
right = rt;
}
}
Code for the binary search tree:
public class BST {
protected BSTNode root = null;
public BST(){}
public void clear()
{
root = null;
}
public boolean isEmpty()
{
return root == null;
}
public void insert(String data)
{
BSTNode p = root, prev = null;
while (p != null) {
prev = p;
if (p.data.compareTo(data) < 0)
p = p.right;
else p = p.left;
}
if (root == null)
root = new BSTNode(data);
else if (prev.data.compareTo(data) < 0)
prev.right = new BSTNode(data);
else prev.left = new BSTNode(data);
}
public void inorder()
{
inorder(root);
}
private void inorder(BSTNode p)
{
if (p != null)
{
inorder(p.left);
System.out.print(p.data + " ");
inorder(p.right);
}
}
public void breadthFirst()
{
BSTNode p = root;
Queue queue = new Queue();
if (p != null)
{
queue.enqueue(p);
while (!queue.isEmpty())
{
p = (BSTNode) queue.dequeue();
System.out.print(p.data + " ");
if (p.left != null)
queue.enqueue(p.left);
if (p.right != null)
queue.enqueue(p.right);
}
}
}
}
Unless the file has one word per line, you're going to have trouble. The buffered reader is giving you the entire line. Is it a word or a sentence?
Your insert() method is empty. Nothing will happen without that. Put some code into it and you may have better luck.
So it seems to me you have two problems:
Your input is incorrect unless it's one word per line. If each line is a sentence, you'll have to tokenize it into words.
Your insert method does nothing. No wonder your tree isn't working.
Replace this code
String word = input.readLine();
with
String word = input.read();
This should work
Related
Im trying to implement a program that adds Word Objects(string word, string meaning) into a Binary Search Tree Alphabetically. I know how to implement a Binary Search Tree with an integer attribute but I'm having difficulties doing it with strings.
public class WordInfo {
public String word;
public String meaning;
public WordInfo left;
public WordInfo right;
public WordInfo(String word, String meaning){
this.word = word;
this.meaning = meaning;
left=right = null;
}
}
public class Dictionary {
WordInfo root;
int count;
public Dictionary() {
root = null;
}
public void add(String word, String meaning) {
WordInfo w = new WordInfo(word, meaning);
if (root == null) {
root = w;
}
WordInfo curr, parent;
parent = curr = root;
while (curr != null) {
parent = curr;
if (word.compareToIgnoreCase(curr.word) < 0) {
curr = curr.left;
} else {
curr = curr.right;
}
}
if (word.compareToIgnoreCase(parent.word) < 0) {
parent.left = w;
} else {
parent.right = w;
}
} }
When I try to add these WordInfo objects into my main program nothing is being added.
In your code snippet, you haven't returned if empty dictionary.
if (root == null) {
root = w;
}
have to be replaced with
if (root == null) {
root = w;
return;
}
So if the root is null, you add an element and return it, of course you can increment the count when new element added.
I am currently in an intro data structures class and am really struggling with one of our problems about Binary Search Trees. This is the first time I have implemented this data structure and am doing my best to learn it.
Problem:
The program is supposed to create and search a BST of name and occurrence data, based upon the census data of babies born that year. We are given this data in a txt file.
I am having a lot of difficulty figuring out why it is not working. I am really just looking for someone to lead me in the right direction from here and give me some good feedback on what I already have because I feel really lost! My current work is below. I am implementing this in java. Thanks in advance!
public class Node {
String name;
int data;
Node leftChild;
Node rightChild;
public Node (String n, int d) {
name = n;
data = d;
}
public class BinarySearchTree` {
public static Node root;
public void addNode(String name, int data) {
Node newNode = new Node(name, data);
if (root == null) {
root = newNode;
} else {
Node focusNode = root;
Node parent;
while(true) {
parent = focusNode;
if (name.compareTo(focusNode.name) < 0) {
focusNode = focusNode.leftChild;
if (focusNode == null) {
parent.leftChild = newNode;
return;
} else {
focusNode = focusNode.rightChild;
if (focusNode == null) {
parent.rightChild = newNode;
return;
}
}
}
}
}
}
public Node searchName(String name) {
Node focusNode = root;
while (!focusNode.name.equals(name)) {
if (name.compareTo(focusNode.name) < 0) {
focusNode = focusNode.leftChild;
} else {
focusNode = focusNode.rightChild;
}
if (focusNode == null) {
return null;
}
}
return focusNode;
}
public static void main(String[] args) throws Exception {
BinarySearchTree tree = new BinarySearchTree();
FileReader file = new FileReader("/Users/mattspahr/Desktop/test.txt");
BufferedReader reader = new BufferedReader(file);
String str = null,
name = null,
num = null;
int data;
while(reader.readLine() != null) {
str = reader.readLine();
for (int i = 0; i < str.length(); i++) {
char c = str.charAt(i);
if (c >= '0' || c <= '9') {
name = str.substring(0, i);
}
num = str.replaceAll("[^0-9]" , "");
}
data = Integer.parseInt(num);
tree.addNode(name,data);
Node n = tree.searchName("Buffy ");
System.out.println(n);
}
}
}
How can this be fixed to read, sort, and count the binary tree correctly? Also how I could use a delimiter for my overloaded constructor, or as another method, or in my main method?
This is the current Input File I need to use:
A
/ \
B C
\ / \
D E F
/ \
G H
/ / \
I J K
The current file that represents the above tree is TreeFile.txt with a sequence that represents the missing nodes:
A
B
C
NULL
D
E
F
NULL
NULL
G
NULL
NULL
H
NULL
NULL
NULL
NULL
NULL
NULL
I
NULL
NULL
NULL
NULL
NULL
J
K
NULL
NULL
NULL
NULL
But If I use this text file then it will through off the algorithm I use in my code bellow to create and show the tree for the pre-order, in-order, post-order, and level-order, node counting, leaf counting, number of nodes on the left and right. What can be corrected in my code so that the "NULL" is not displayed back and sorting and counting shows correct too?
My Code that takes the input and makes the tree with a sample of pre-order and count left nodes:
import java.util.Scanner;
public class BinaryTree<E> {
private class NodeClass<E> {
private NodeClass<E> left;
private NodeClass<E> right;
private E value;
public NodeClass(E value) {
left = null;
right = null;
this.value = value;
}
}
private NodeClass<E> root;
// confusion here
public BinaryTree(Scanner scan) throws Exception {
NodeClass<E> currentNode = root;
NodeClass<E> nextNode = null;
while (scan.hasNextLine()) {
String value = (String) scan.nextLine().trim();
if (value.length() == 0)
continue;
if (root == null) {
root = new NodeClass(value);
} else {
currentNode = root;
nextNode = currentNode;
while (nextNode != null) {
if (nextNode.left == null) {
insertingLeft(nextNode, (E) value);
break;
} else if (nextNode.right == null) {
insertingRight(nextNode, (E) value);
break;
}
if (nextNode == currentNode) {
nextNode = currentNode.left;
} else if (nextNode == currentNode.left) {
nextNode = currentNode.right;
} else if (nextNode == currentNode.right) {
nextNode = currentNode.left.left;
currentNode = currentNode.left;
}
}
}
}
}
public void insertingRight(NodeClass<E> Node, E element) {
if (Node.right == null) {
Node.right = new NodeClass<E>(element);
} else {
insertingRight(Node.right, element);
}
}
public void insertingLeft(NodeClass<E> Node, E element) {
if (Node.left == null) {
Node.left = new NodeClass<E>(element);
} else {
insertingLeft(Node.left, element);
}
}
public BinaryTree() {
root = null;
}
public String PreOrder() {
StringBuilder builder = new StringBuilder();
PreOrder(builder, root);
return builder.toString();
}
private void PreOrder(StringBuilder builder, NodeClass<E> node) {
builder.append(" " + node.value.toString());
if (node.left != null) {
PreOrder(builder, node.left);
}
if (node.right != null) {
PreOrder(builder, node.right);
}
}
public int leftCount() {
return leftCount(root);
}
private int leftCount(NodeClass<E> node) {
int count = 0;
if (node.left != null && node.right == null) {
count++;
count += leftCount(node.left);
}
if (node.right != null) {
count += leftCount(node.right);
}
return count;
}
}
My main driver class:
import java.io.File;
import java.util.Scanner;
public class testBinaryTree {
public static void main(String[] args) {
try {
Scanner in = new Scanner(new File("TreeFile.txt"));
BinaryTree<String> bt = new BinaryTree<String>(in);
System.out.print("Pre Order: " + bt.PreOrder() + "\n");
System.out.println("Left Count: " + bt.leftCount());
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
Which displays back:
Pre Order: A B NULL NULL NULL NULL I NULL NULL NULL NULL NULL NULL NULL J K NULL NULL NULL H NULL NULL NULL NULL NULL D G NULL C E F
Left Count: 0
Your "NULL" nodes are displayed because you actually create nodes containing the text "NULL" and don't take them into account when printing the preorder output.
You can either filter those nodes with the text "NULL" when printing the preorder and ignore them (the same as you ignore nodes that are actually null).
Or, which I think is better, not insert them from the beginning. This, however, requires you to keep track of the insertion position. I think the easiest way to do that is to put the whole list of nodes in an array first and then create the tree from it. There are formulas to calculate the index of the left or right children of a node (2*i+1 for the left son, 2*i+2 for the right son) that help you find the right children.
So first just read all the strings into an array String[] nodes and then call BuildTreeFromArray(0, nodes) on it to build the tree:
NodeClass<E> BuildTreeFromArray(int index, String[] nodes) {
if (index >= nodes.length) {
return null;
} else {
NodeClass<E> node = new NodeClass<E>(nodes[index]);
node.left = BuildTreeFromArray(2 * index + 1, nodes);
node.right = BuildTreeFromArray(2 * index + 2, nodes);
return node;
}
}
I strongly recommend that you use a better tree representation in the input file. For example, use a list of triples, each linking a parent to its children. Then order doesn't matter (except make the first node root), and you can ignore all the non-existent nodes:
A B C
B - D
D G -
G I -
C E F
E - H
H J K
Then it's easy to build the tree using a dictionary of nodes:
import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.Map;
public class TreeBuilder {
Map<String, Node> valToNode = new HashMap<>();
static class Node {
String key;
Node left, right;
Node(String key) { this.key = key; }
void printTree() {
System.out.print(key);
if (left != null || right != null) {
System.out.print("(");
print(left);
System.out.print(", ");
print(right);
System.out.print(")");
}
}
static void print(Node node) {
if (node == null)
System.out.print("-");
else
node.printTree();
}
}
Node buildTree(String filePath) throws IOException {
Node root = null;
for (String line : Files.readAllLines(
Paths.get(filePath), Charset.forName("UTF-8"))) {
String[] vals = line.split("\\s+");
Node parent = lookupOrCreateNode(vals[0]);
parent.left = lookupOrCreateNode(vals[1]);
parent.right = lookupOrCreateNode(vals[2]);
if (root == null) root = parent;
}
return root;
}
Node lookupOrCreateNode(String key) {
if ("-".equals(key)) return null;
Node node = valToNode.get(key);
if (node == null) {
node = new Node(key);
valToNode.put(key, node);
}
return node;
}
void run() {
try {
Node tree = buildTree("src/hacking/data.txt");
tree.printTree();
System.out.println();
} catch (IOException ex) {
System.err.println("input file not found");
}
}
public static void main(String[] args) {
new TreeBuilder().run();
}
}
Output:
A(B(-, D(G(I, -), -)), C(E(-, H(J, K)), F))
NB: The java is short, but it skips error checking, data hiding, etc.
I'm doing a homework assignment in Java where I have to create an unsorted binary tree with a String as the data value. I then have to write a function that replaces a Node and any duplicate Nodes that match an old description with a new object that contains a new description.
Here is the code that I am working with, including the test case that causes an infinite loop:
public class Node {
private String desc;
private Node leftNode = null;
private Node rightNode = null;
private int height;
public Node(String desc) {
this.desc = desc;
height = 0; // assumes that a leaf node has a height of 0
}
public String getDesc() {
return desc;
}
public Node getLeftNode() {
return leftNode;
}
public Node getRightNode() {
return rightNode;
}
public void setLeftNode(Node node) {
++height;
leftNode = node;
}
public void setRightNode(Node node) {
++height;
rightNode = node;
}
public int getHeight() {
return height;
}
public int addNode(Node node) {
if(leftNode == null) {
setLeftNode(node);
return 1;
}
if(rightNode == null) {
setRightNode(node);
return 1;
}
if(leftNode.getHeight() <= rightNode.getHeight()) {
leftNode.addNode(node);
++height;
} else {
rightNode.addNode(node);
++height;
}
return 0;
}
public static void displayTree(Node root) {
if(root != null) {
displayTree(root.getLeftNode());
System.out.println(root.getDesc());
displayTree(root.getRightNode());
}
}
public static Node findNode(Node current, String desc) {
Node result = null;
if(current == null) {
return null;
}
if(current.getDesc().equals(desc)) {
return current;
}
if(current.getLeftNode() != null) {
result = findNode(current.getLeftNode(), desc);
}
if(result == null) {
result = findNode(current.getRightNode(), desc);
}
return result;
}
public static void replaceNode(Node root, String oldDesc, String newDesc) {
if(oldDesc == null || newDesc == null) {
System.out.println("Invalid string entered");
return;
}
boolean replacedAllNodes = false;
while(replacedAllNodes == false) {
Node replace = findNode(root, oldDesc);
if(replace == null) { // No more nodes to replace
replacedAllNodes = true;
return;
}
replace = new Node(newDesc);
root.addNode(replace);
}
return;
}
public static void main(String[] args) {
Node root = new Node("test1");
Node test_2 = new Node("test2");
Node test_3 = new Node("test3");
Node test_4 = new Node("test4");
Node test_5 = new Node("test5");
Node test_6 = new Node("test6");
root.addNode(test_2);
root.addNode(test_3);
root.addNode(test_4);
root.addNode(test_5);
root.addNode(test_6);
displayTree(root);
replaceNode(root, "test4", "hey");
System.out.println("-------");
displayTree(root);
}
}
After testing the findNode method, and seeing that it returns the correct object, I realized that the infinite loop was being caused by my replaceNode method. I'm just not really sure how it is causing it.
I got it to work with one case by removing the while loop, but obviously that won't work for duplicates, so I'm wondering how I could remove the node with oldDesc and replace it with a new object that contains newDesc when there could be multiple objects with matching oldDesc data.
you are never changing root or oldDesc in your while loop
while(replacedAllNodes == false) {
Node replace = findNode(root, oldDesc);
if(replace == null) { // No more nodes to replace
replacedAllNodes = true;
return;
}
replace = new Node(newDesc);
root.addNode(replace);
}
If you watch
public static Node findNode(Node current, String desc) {
Node result = null;
if(current == null) {
return null;
}
if(current.getDesc().equals(desc)) {
return current;
}
if(current.getLeftNode() != null) {
result = findNode(current.getLeftNode(), desc);
}
if(result == null) {
result = findNode(current.getRightNode(), desc);
}
return result;
}
If the if(current.getDesc().equals(desc)) condition matches, replace will always be root so you are stuck in your while loop
Update:
If you dont necessarily have to replace the whole node, you could just update the description for your node at the end of your while loop.
instead of
replace = new Node(newDesc);
root.addNode(replace);
do something like:
root.setDesc(newDesc);
(of course you would have to create a setDesc() method first)
If you have to replace the whole object, you have to go like this:
Instead of
replace = new Node(newDesc);
root.addNode(replace);
do something like this:
replace = new Node(newDesc);
replace.setLeftNode(root.getLeftNode);
replace.setRightNode(root.getRightNode);
Plus you have to link the node that pointed to root so it points to replace like one of the following examples (depends on which side your root was of course):
nodeThatPointedToRoot.setLeftNode(replace);
nodeThatPointedToRoot.setRightNode(replace);
well looking at your code, you are not replacing a node you are just adding a new node to the edge of the tree and the old node would still be there so the loop will go forever and you can add a temp variable with an auto increment feature and to indicate the level of the node you are reaching to replace and you'll find it's just doing it again and again, instead of doing all this process how about just replacing the description inside that node ?
I have constructed a binary search tree using a text file that is read in by the main function. The resulting tree contains the words of the text file, with a count so that the same word is not inserted twice. The problem is not with constructing the tree, but getting the information to display properly. The data is required to be printed out in columns of 4, as to keep it readable.
Example:
|BTNode1|BTNode2|BTNode3|BTNode4|
|BTNode5|BTNode6|BTNode7|BTNode8|
The BTNode class has a toString() method that prints out the data of the individual nodes. But, whenever I call this code below with the root node, and a count of 0 I get the node information properly, but in weird numbers of nodes per column. Any ideas how to get this to work? I can post additional code if necessary.
EDIT: Added entire class to reflect changes, and added sample current output. Might be a problem with constructing the tree.
EDIT2: Changed printcount = 1, fixes the display problems. Code now works properly.
package speech;
public class BSTree {
private BTNode root;
private final String DISPLAY_FORMAT_CAPS =
"*****************************************************************";
private StringBuilder buffer = new StringBuilder();
private int printcount = 1;
public BSTree (){
root = null;
}
public BTNode insert(String indata, boolean lowercase){
if(lowercase){
if(root != null){
return insertRecursive(root,indata.toLowerCase());
}
else{
root = new BTNode(indata.toLowerCase());
return root;
}
}
else{
if(root != null){
return insertRecursive(root,indata);
}
else{
root = new BTNode(indata);
return root;
}
}
}
private BTNode insertRecursive(BTNode node, String value) {
if (value.compareTo(node.data) < 0){
if (node.left != null) {
return insertRecursive(node.left, value);
} else {
//System.out.println(" Inserted " + value + " to left of Node " + node.data);
node.left = new BTNode(value);
return node.left;
}
} else if (value.compareTo(node.data) > 0) {
if (node.right != null) {
return insertRecursive(node.right, value);
} else {
//System.out.println(" Inserted " + value + " to right of Node " + node.data);
node.right = new BTNode(value);
return node.left;
}
} else if (value.compareTo(node.data) == 0){
node.incrementCount();
//System.out.println("Incremented count of " + value + " to: " + node.wordcount);
return node;
}
return null;
}
private int wordcountRecursive(BTNode node){
if(node == null){
return 0;
}
else{
return wordcountRecursive(node.left) + node.wordcount + wordcountRecursive(node.right);
}
}
public int wordcount(){
return wordcountRecursive(root);
}
public void display(){
System.out.println(DISPLAY_FORMAT_CAPS);
displayRecursive(root);
System.out.println(buffer.toString());
System.out.println(DISPLAY_FORMAT_CAPS);
System.out.println("Word Count:" + wordcount());
}
private void displayRecursive (BTNode node){
//System.out.println(count);
if(node != null){
displayRecursive(node.left);
addNodeDisplay(node);
displayRecursive(node.right);
}
}
private void addNodeDisplay(BTNode node){
if(printcount % 4 != 0){
buffer.append("|").append(node);
}
else{
buffer.append("|").append(node).append("|\n");
}
printcount++;
}
}
I've added some sample data and this looks like it works:
private void displayRecursive(Node node) {
displayRecursive(node, 0);
System.out.println("");
}
private int displayRecursive(Node node, int count) {
if (node != null) {
// Do left first.
count = displayRecursive(node.getLeft(), count);
// New line?
if (count > 0 && count % 4 == 0) {
// End of line.
System.out.println("|");
}
// Then me.
System.out.print("|" + node);
count += 1;
// Then right.
count = displayRecursive(node.getRight(), count);
}
return count;
}
private void test() {
Node root = new Node("Root");
Node left = new Node("Left");
Node right = new Node("Right");
root.setLeft(left);
root.setRight(right);
Node leftLeft = new Node("Left.Left");
leftLeft.setLeft(new Node("LeftLeftLeft"));
leftLeft.setRight(new Node("LeftLeftRight"));
left.setLeft(leftLeft);
left.setRight(new Node("Left.Right"));
right.setLeft(new Node("Right.Left"));
right.setRight(new Node("Right.Right"));
displayRecursive(root);
}
public static void main(String[] args) throws InterruptedException {
try {
Test test = new Test();
test.test();
} catch (Exception e) {
e.printStackTrace();
}
}
static class Node {
final String data;
private Node left = null;
private Node right = null;
Node(String data) {
this.data = data;
}
#Override
public String toString() {
return data;
}
/**
* #return the left
*/
public Node getLeft() {
return left;
}
/**
* #param left the left to set
*/
public void setLeft(Node left) {
this.left = left;
}
/**
* #return the right
*/
public Node getRight() {
return right;
}
/**
* #param right the right to set
*/
public void setRight(Node right) {
this.right = right;
}
}
it prints:
|LeftLeftLeft|Left.Left|LeftLeftRight|Left|
|Left.Right|Root|Right.Left|Right|
|Right.Right