I'm pretty new to Java, with this being my second class (in College) using it. Towards the beginning of the semester, I made a simple class representing Zombies that holds their age, type, and name. Later on, I made a linked list of integers. Now, I need to make a generic linked list that can hold these 'Zombies'. I also have to make a menu that allows me to add, remove, count, and display 'Zombies'. I've been staring at this for hours, going through my book, and looking online for the answer to my problem. I can add and display these 'Zombies', but counting them in the list and trying to remove them simply has it tell me there's none with the parameters I entered. In other words, there might be a problem with how I compare the 'Zombies'. Here's my code. I understand it's a good 300 lines of code to look through... but i'm out of ideas.
Zombie.java
public class Zombie
{
private String zAge;
private String zType;
private String zName;
public Zombie(String zA, String zT, String zN)
{
zAge = zA;
zType = zT;
zName = zN;
}
public void setZAge(String zA)
{
zAge = zA;
}
public void setZType(String zT)
{
zType = zT;
}
public void setZName(String zN)
{
zName = zN;
}
public String getZAge()
{
return zAge;
}
public String getZType()
{
return zType;
}
public String getZName()
{
return zName;
}
public boolean equals(Zombie zomb)
{
if(zomb.getZAge() == zAge && zomb.getZType() == zType && zomb.getZName() == zName)
return true;
else
return false;
}
}
LinkedBag.java
public class LinkedBag<E>
{
//Head node and number of nodes in bag
private Node<E> head;
private int manyNodes;
//Constructor
public LinkedBag()
{
head = null;
manyNodes = 0;
}
//Returns the number of nodes in the bag
public int getSize()
{
return manyNodes;
}
//Returns the node that is at the head of the linked list
public Node<E> getListStart()
{
return head;
}
//Adds a node to the beginning of the list
public void add(E element)
{
head = new Node<E>(element,head); //Creates a new node pointing to the head and sets the head of the linked bag to the new Node
manyNodes++; //Increments Node counter
}
//Counts the number of times Node [target] occurs within the bag
public int countOccurences(E target)
{
int count = 0; //Initializes incrementable counter
if(head==null) //Checks if bag is empty and returns null if bag is empty
return 0;
if(head.getData().equals(target)) //Checks if the head of the linked list is [target]
count++; //Increments counter
Node<E> cursor = head; //Sets temporary Node [cursor] to the same value and pointer as head
while(cursor.getLink() != null) //Loops until the next Node contains no value
{
if(cursor.getLink().getData().equals(target)) //Checks if the value of the next Node is [target]
count++; //Increments counter
cursor=cursor.getLink(); //Cursor continues down linked list
}
return count; //Returns incremented int [count], number of occurences of [target]
}
//Checks if Node [target] exists within the bag
public boolean exists(E target)
{
if(head.getData().equals(target)) //Checks if the head of the linked list is [target]
return true;
Node<E> cursor = head; //Sets temporary Node [cursor] to the same value and pointer as head
while(cursor.getLink() != null) //Loops until the next Node contains no value
{
if(cursor.getData().equals(target)) //Checks if current Node is [target] and returns true if true
return true;
cursor=cursor.getLink(); //Cursor continues down linked list
}
return false; //Returns false if cursor goes through entire linked list and [target] isn't found
}
//Checks if Node [target] exists within the bag and removes the first occurence of it
public boolean remove(E target)
{
if(head==null) //Returns false if bag is empty
return false;
if(head.getData().equals(target)) //If the head Node's data is [target]
{
head = head.getLink(); //Make the next Node the head
manyNodes--; //Decrements Node counter
return true; //Returns true, found [target]
}
Node<E> cursor = head; //Sets temporary Node [cursor] to the same value and pointer as head
while(cursor.getLink() != null) //Loops until the next Node contains no value
{
cursor = cursor.getLink(); //Cursor continues down linked list
if(cursor.getLink().getData().equals(target)) //If the next node's data is [target]
{
cursor.setLink(cursor.getLink().getLink()); //Sets current Node's link to the next Node's link, by passing the next Node
manyNodes--; //Decrements Node counter
return true; //Returns true, found [target]
}
}
return false; //Returns false, [target] not found
}
}
Node.java
public class Node<E>
{
private E data;
private Node<E> link;
public Node(E initialData, Node<E> initialLink)
{
data = initialData;
link = initialLink;
}
public E getData()
{
return data;
}
public Node<E> getLink ()
{
return link;
}
public void setData(E element)
{
data = element;
}
public void setLink(Node<E> newLink)
{
link = newLink;
}
}
And this is the menu file that the user interacts with
ZombiesProj2.java
import java.util.Scanner;
public class ZombiesProj2
{
public static void main(String[] args) throws InterruptedException
{
LinkedBag<Zombie> zBag = new LinkedBag<Zombie>(); //Linked bag to hold Zombie Objects
String choice = "";
Scanner input = new Scanner(System.in);
while(!choice.equalsIgnoreCase("x"))
{
//Menu
System.out.println("\nSac de Zombi\n");
System.out.println("S - Display size of bag");
System.out.println("A - Add 'Zombie' to bag");
System.out.println("R - Remove 'Zombie' from bag");
System.out.println("F - Find 'Zombie' in bag");
System.out.println("D - Display contents of bag");
System.out.println("X - Exit");
System.out.print("Enter Selection: ");
//Input and Output
choice = input.nextLine();
if(choice.equalsIgnoreCase("s"))
{
System.out.println("\nSize = " + zBag.getSize() + "\n");
}
else if(choice.equalsIgnoreCase("a")) //adds zombie
{
String zAge;
String zType;
String zName;
System.out.print("How many years has this zombie ROAMED THE EARTH: ");
zAge = input.nextLine();
System.out.print("What type of zombie is it: ");
zType = input.nextLine();
System.out.print("What would you like to name this zombie: ");
zName = input.nextLine();
Zombie newZomb = new Zombie(zAge,zType,zName);
zBag.add(newZomb);
}
else if(choice.equalsIgnoreCase("r")) //removes zombie
{
String zAge;
String zType;
String zName;
System.out.print("How many years has this zombie ROAMED THE EARTH: ");
zAge = input.nextLine();
System.out.print("What type of zombie is it: ");
zType = input.nextLine();
System.out.print("What is the name of the zombie: ");
zName = input.nextLine();
Zombie rZomb = new Zombie(zAge,zType,zName);
zBag.remove(rZomb);
}
else if(choice.equalsIgnoreCase("f")) //counts number of matching zombies
{
String zAge;
String zType;
String zName;
System.out.print("How many years has this zombie ROAMED THE EARTH: ");
zAge = input.nextLine();
System.out.print("What type of zombie is it: ");
zType = input.nextLine();
System.out.print("What is the name of the zombie: ");
zName = input.nextLine();
Zombie fZomb = new Zombie(zAge,zType,zName);
System.out.println("The " + zAge + " year old zombie type " + zType + " named " + zName + " occurs " + zBag.countOccurences(fZomb)+ " time(s)");
}
else if(choice.equalsIgnoreCase("d")) //displays entire zombie 'bag'
{
Node cursor = zBag.getListStart();
Zombie dZomb;
while(cursor !=null)
{
dZomb = (Zombie)cursor.getData();
System.out.print("[Zombie "+dZomb.getZAge()+" "+dZomb.getZType()+" "+dZomb.getZName()+"],");
cursor = cursor.getLink();
}
}
else if(!choice.equalsIgnoreCase("x"))
{
System.out.println("Error: Invalid Entry");
}
}
}
}
Updated equals and hashCode
public boolean equals(Object obj)
{
if(obj==null)
return false;
if(obj==this)
return true;
if(obj.getClass() != getClass())
return false;
Zombie zomb = (Zombie)obj;
if(zomb.getZAge().equals(zAge) && zomb.getZType().equals(zType) && zomb.getZName().equals(zName))
return true;
else
return false;
}
public int hashCode() { return 0; }
I know that because you are trying to learn programming you are writing your own linked list instead of using Java's LinkedList. However, there are a few things you have missed.
Your equals method should have the same signature as that in Object Zombie.equals(Object). And, the first thing it should do is return false if the argument is not a Zombie.
Whenever you write an equals method, you must also write a hashCode method. Look at most any example for details.
Never use the equals operator for Strings. Always use the equals method. Replace zomb.getZAge() == zAge with zomb.getZAge().equals(zAge).
Why is zAge a String? You can let it be some sort of number.
There's no need to put 'Z' everywhere in your class. It's in a Zombie; your readers know. At work, I have colleagues who insist on repeating class names in all their variables.
This is not good code.
public class Document {
private Long documentId;
private String documentName;
private String documentAuthor;
private Date documentPublicationDate;
// 10 more instance variables.
// Constructors, accessors, other code.
}
And then they name variables of type Document as documentA, documentB, etc. How boring, repetitious, and redundant.
1) Why would you name a variable that contains the node count 'manyNodes' instead of 'nodeCount'. If you asked some random programmer what a variable named 'manyNodes' contained, do you think they would be able to guess? What if you asked some random programmer what the variable nodeCount contained? Do you think the random programmer could even guess the type of nodeCount? What about the type of 'manyNodes'?
2) How about trying something like this:
public void add(Node<E> element)
{
if (head == null) {
head = element;
}
else {
tail.nextNode = element;
}
tail = element;
nodeCount++; //Increments Node counter
}
public class Node<E>
{
private E data;
private Node<E> nextNode;
}
public class LinkedBag<E>
{
private Node<E> head;
private Node<E> tail;
private int nodeCount;
}
//Constructor
public LinkedBag()
{
head = tail = null;
nodeCount = 0;
}
Related
I am using a Linked list/ Iterater combo to compute the Josephus problem, and need it to only print if there is only one element left in the list, but how would I use an if statement to check a condition that references to the size of the list rather than the number in the list with "ourList" being of type "LinkedList"?
Here is a piece of the code:
if(atEnd() == true){
//System.out.println("Value removed: " + current.dData);
previous.next = current.next;
current = ourList.getFirst();
//if(ourList == Only contains one element){ <--------------
//ourList.displayList();
// }
}
for reference heres my LinkedList + Iterator:
class Link{
public int dData;
public Link next;
public Link(int data){
dData = data;
}
public void displayLink(){
System.out.print(dData + " ");
}
}
class LinkList{
private Link first;
public LinkList(){
first = null;
}
public Link getFirst(){
return first;
}
public void setFirst(Link f){
first = f;
}
public boolean isEmpty(){
return first == null;
}
public ListIterator getIterator(){
return new ListIterator(this);
}
public void displayList(){
Link current = first;
while(current != null){
current.displayLink();
current = current.next;
}
System.out.println("");
}
}
class ListIterator{
private Link current;
private Link previous;
private LinkList ourList;
public ListIterator(LinkList list){
ourList = list;
reset();
}
public void reset(){
current = ourList.getFirst();
previous = null;
}
public boolean atEnd(){
return(current.next == null);
}
public boolean atEndPrevious(){
return(previous.next == null);
}
public Link getCurrent(){
return current;
}
public void nextLink(){
previous = current;
current = current.next;
}
public void insert(int value){
Link newLink = new Link(value);
if(ourList.isEmpty() == true){
ourList.setFirst(newLink);
current = newLink;
}else{
newLink.next = current.next;
current.next = newLink;
nextLink();
}
}
public void beginningPoint(int begin){
if(begin == 1){
current = ourList.getFirst();
previous = null;
// System.out.println("Current Location: " + current.dData);
}else if(begin != 1){
current = ourList.getFirst();
previous = null;
for(int i = 1; i < begin; i++){
nextLink();
// System.out.println("Current Location: " + current.dData);
}
}
}
Adding pseudocode, since it will help you understand the process, but learn by programming it yourself. Also note you could remove some else's through the behavior of exiting.
All of this functions through the iterator.
if at end
dont print and exit (0 elements)
else
get and save next element to variable
if at end
print the variable you saved (only 1 element)
else
dont print and exit (more than 1 element)
So like the title says I'm trying to input a node in the third position of the linked list. The way I originally tried to do it was to insert two places down the list after numberOfItems was >= 3. I figured if I was getting an error it would be outputting the last 2 Players wrongly but it's just continuing to output Player 1. Can anybody point me to the right direction as to why this is happening?
Here is my linkedlist class
public class PlayerLinkedList extends ShellLinkedList
{
public PlayerLinkedList()
{
super();
}//end PlayerLinkedList constructor
public void insert(Player p)
{
if(numberOfItems >= 3)
{
PlayerNode pn = new PlayerNode(p);
head = pn;
pn.setNext(head.getNext().getNext());
numberOfItems++;
}
else
{
PlayerNode pn = new PlayerNode(p);
if(head == null)
{
head = pn;
}
pn.setNext(head);
head = pn;
numberOfItems++;
}
}//end insert method
public Player delete(int searchID) throws DataStructureException
{
PlayerNode current = head;
PlayerNode previous = null;
while(current != null && current.getPlayer().getID()!=searchID)
{
previous = current;
current = current.getNext();
}//end while
if(current == null) //not found
throw new DataStructureException(searchID + "not found: cannot be deleted");
else
{
if(current == head)
head = head.getNext(); //delete head
else
previous.setNext(current.getNext());
numberOfItems--;
return current.getPlayer();
}//end else
}//end delete
}//end class
Also just for reference here is my ShellLinkedList class
public abstract class ShellLinkedList
{
protected PlayerNode head;
protected int numberOfItems;
public ShellLinkedList()
{
head = null;
numberOfItems = 0;
}//end ShellLinkedList constructor
public int getNumberOfItems()
{
return numberOfItems;
}// end of getnumberOfItems
public boolean isEmpty()
{
return (numberOfItems==0);
}//end isEmpty
public String toString()
{
String listString="";
PlayerNode current = head;
for(int i = 0; i<numberOfItems && current != null; i++)
{
listString += current.getPlayer().toString()+"\n";
current = current.getNext();
}
return listString;
}//end toString
}//end class
My input is:
Player one = new Player(1, "Mike", "Mario");
Player two = new Player(2, "Brian", "Halo");
Player three = new Player(3, "John", "Minecraft");
Player four = new Player(4, "Thrall", "WoW");
Player five = new Player(5, "Scott", "Metroid");
list.insert(one);
list.insert(two);
list.insert(three);
list.insert(four);
list.insert(five);
System.out.println(list.toString());
And my output is:
id: 3 name: John game: Minecraft
id: 2 name: Brian game: Halo
id: 1 name: Mike game: Mario
id: 1 name: Mike game: Mario
id: 1 name: Mike game: Mario
There are a few problems with your code, your insert method behaves differently when numberOfItems >= 3 which is why you are not able to add more than 3 times. In that code block you are creating a new PlayerNode instance but you do not keep any reference to it.
You should also check whether you are expecting normal List#add behaviour which appends to the end of a list not the beginning.
I solved the issue by adding
head.getNext().setNext(pn);
after
pn.setNext(head.getNext().getNext());
I'm trying to implement the a Stack in Java with a circular singly linked list as the underlying data structure. I placed the insert function for a circular linked list in replacement of the push function for the stack and so on. I don't have any errors but I'm having troubles displaying the stack. If anyone could point me in the right direction of how to display the stack or what's going wrong I'd really appreciate it!
Here is my stack class:
public class Stack {
private int maxSize; // size of stack array
private long[] stackArray;
private int top; // top of stack
private Node current = null; // reference to current node
private int count = 0; // # of nodes on list
private long iData;
public Stack(int s) // constructor
{
maxSize = s; // set array size
stackArray = new long[maxSize]; // create array
top = -1; // no items yet
}
public void push(long j) // put item on top of stack
{
Node n = new Node(j);
if(isEmpty()){
current = n;
}
n.next = current;
current = n;
count++;
}
//--------------------------------------------------------------
public Node pop() // take item from top of stack
{
if(isEmpty()) {
return null;
}
else if(count == 1){
current.next = null;
current = null;
count--;
return null;
}else{
Node temp = current;
current = current.next;
temp.next = null;
temp = null;
count--;
}
return current;
}
//--------------------------------------------------------------
public Node peek(long key) // peek at top of stack
{
Node head = current;
while(head.iData != key){
head = head.next;
}
return head;
}
//--------------------------------------------------------------
public boolean isEmpty() // true if stack is empty
{
return (count == 0);
}
//--------------------------------------------------------------
public boolean isFull() // true if stack is full
{
return (count == maxSize-1);
}
//--------------------------------------------------------------
Here is my constructor class
public class Node{
public long iData; // data item (key)
public Node next; // next node in the list
public Node(long id){ // constructor
iData = id; // next automatically nulls
}
public void displayNode(){
System.out.print(iData + " ");
}
public static void main(String[] args) {
Stack newlist = new Stack(3);
newlist.push(1);
newlist.push(2);
newlist.push(3);
newlist.push(4);
newlist.pop();
newlist.pop();
newlist.push(4);
newlist.pop();
newlist.peek(1);
newlist.push(5);
while( !newlist.isEmpty() ) // until it’s empty,
{ // delete item from stack
Node value = newlist.pop();
System.out.print(value); // display it
System.out.print(" ");
} // end while
System.out.println("");
}
//newlist.displayList();
}
First, in your main function you are printing value using System.out.print function. This displays the object's class name representation, then "#" followed by its hashcode.
Replace following lines
System.out.print(value); // display it
System.out.print(" ");
with
value.displayNode();
Second, in pop method, you are returning null when count is 1. It should return the last element which is present in the list. Also, in last else if clause, you should return temp. Replace your code with this.
public Node pop() // take item from top of stack
{
if (isEmpty()) {
return null;
}
Node temp = current;
if (count == 1) {
current = null;
} else {
current = current.next;
}
count--;
temp.next = null;
return temp;
}
A few notes on your implementation:
1) stackArray member seems to be a leftover from another array based stack implementation.
2) is max size really a requirement? if so, you don't enforce the stack size limitation in push(..)
3) Your push(..) method doesn't keep the list circular. You should close the loop back to the new node.
4) Adding a dummy node allows you to keep the linked list circular, regardless of the stack size. This can make your push(..) method simpler (as well as any iteration for printing purposes for example)
5) The peek() method contract is unclear. Usually you want the peek method to return the value in the top of the stack, without removing it. Also, why do you return type Node? This class should be hidden from the caller - it's an internal implementation detail, not something you want to expose in your API.
Following is an alternative implementation, that also supports toString():
public class Stack {
private Node EOS;
private int count = 0;
public Stack() {
EOS = new Node(0);
EOS.next = EOS;
}
public void push(long j) {
Node newNode = new Node(j);
Node tmp = EOS.next;
EOS.next = newNode;
newNode.next = tmp;
count++;
}
public Long pop() {
if (isEmpty()) {
return null;
} else {
count--;
Node node = EOS.next;
EOS.next = node.next;
return node.iData;
}
}
public Long peek() {
if (isEmpty()) {
return null;
} else {
Node node = EOS.next;
return node.iData;
}
}
public boolean isEmpty() {
return (count == 0);
}
#Override
public String toString() {
StringBuilder sb = new StringBuilder();
Node p = EOS.next;
while (p != EOS) {
sb.append(p).append("\n");
p = p.next;
}
return sb.toString();
}
private static class Node {
public long iData;
public Node next;
public Node(long id) {
iData = id;
}
#Override
public String toString() {
return "<" + iData + ">";
}
}
}
I have this code for BinaryTree creation and traversal
class Node
{
Integer data;
Node left;
Node right;
Node()
{
data = null;
left = null;
right = null;
}
}
class BinaryTree
{
Node head;
Scanner input = new Scanner(System.in);
BinaryTree()
{
head = null;
}
public void createNode(Node temp, Integer value)
{
Node newnode= new Node();
value = getData();
newnode.data = value;
temp = newnode;
if(head==null)
{
head = temp;
}
System.out.println("If left child exits for ("+value+") enter y else n");
if(input.next().charAt(0)=='y')
{
createNode(temp.left, value);
}
System.out.println("If right child exits for ("+value+") enter y else n");
if(input.next().charAt(0)=='y')
{
createNode(temp.right, value);
}
}
public Integer getData()
{
out.println("Enter the value to insert:");
return (Integer)input.nextInt();
}
public void print()
{
inorder(head);
}
public void inorder(Node node)
{
if(node!=null)
{
inorder(node.left);
System.out.println(node.data);
inorder(node.right);
}
else
return;
}
}
class BinaryTreeWorker
{
static BinaryTree treeObj = null;
static Scanner input = new Scanner(System.in);
public static void displaymenu()
{
int choice;
do{
out.print("\n Basic operations on a tree:");
out.print("\n 1. Create tree \n 2. Insert \n 3. Search value \n 4. print list\n Else. Exit \n Choice:");
choice = input.nextInt();
switch(choice)
{
case 1:
treeObj = createBTree();
break;
case 2:
treeObj.createNode(null, null);
break;
case 3:
//searchnode();
break;
case 4:
treeObj.print();
break;
default:
return;
}
}while(true);
}
public static BinaryTree createBTree()
{
return new BinaryTree();
}
public static void main(String[] args)
{
displaymenu();
}
}
It compiles and runs. But I think there is something wrong with the inorder traversal.
I created the below tree,
2
1 3
But it prints only 2.
I have tried solving the problem your way and I have pasted the solution below.. Though I haven't tested it thoroughly so it might fail in some edge condition.. But I have tested it for one case. Kindly let me know if it fails in some scenario. I would appreciate others help in making this answer better. I agree that this solution is not the most ideal way to code a Binary Tree but it wont hurt this way if some one is just practicing..
import java.util.Scanner;
class Node
{
Integer data;
Node left;
Node right;
Node()
{
data = null;
left = null;
right = null;
}
}
class BinaryTree
{
Node head;
Scanner input = new Scanner(System.in);
BinaryTree()
{
head = null;
}
public void createNode(Node temp,Node newnode)
{
if(head==null)
{
System.out.println("No value exist in tree, the value just entered is set to Root");
head = newnode;
return;
}
if(temp==null)
temp = head;
System.out.println("where you want to insert this value, l for left of ("+temp.data+") ,r for right of ("+temp.data+")");
char inputValue=input.next().charAt(0);
if(inputValue=='l'){
if(temp.left==null)
{
temp.left=newnode;
System.out.println("value got successfully added to left of ("+temp.data+")");
return;
}else {
System.out.println("value left to ("+temp.data+") is occupied 1by ("+temp.left.data+")");
createNode(temp.left,newnode);
}
}
else if(inputValue=='r')
{
if(temp.right==null)
{
temp.right=newnode;
System.out.println("value got successfully added to right of ("+temp.data+")");
return;
}else {
System.out.println("value right to ("+temp.data+") is occupied by ("+temp.right.data+")");
createNode(temp.right,newnode);
}
}else{
System.out.println("incorrect input plz try again , correctly");
return;
}
}
public Node generateTree(){
int [] a = new int[10];
int index = 0;
while(index<a.length){
a[index]=getData();
index++;
}
if(a.length==0 ){
return null;
}
Node newnode= new Node();
/*newnode.left=null;
newnode.right=null;*/
return generateTreeWithArray(newnode,a,0);
}
public Node generateTreeWithArray(Node head,int [] a,int index){
if(index >= a.length)
return null;
System.out.println("at index "+index+" value is "+a[index]);
if(head==null)
head= new Node();
head.data = a[index];
head.left=generateTreeWithArray(head.left,a,index*2+1);
head.right=generateTreeWithArray(head.right,a,index*2+2);
return head;
}
public Integer getData()
{
System.out.println("Enter the value to insert:");
return (Integer)input.nextInt();
}
public void print()
{
inorder(head);
}
public void inorder(Node node)
{
if(node!=null)
{
inorder(node.left);
System.out.println(node.data);
inorder(node.right);
}
else
return;
}
}
public class BinaryTreeWorker
{
static BinaryTree treeObj = null;
static Scanner input = new Scanner(System.in);
public static void displaymenu()
{
int choice;
do{
System.out.print("\n Basic operations on a tree:");
System.out.print("\n 1. Create tree \n 2. Insert \n 3. Search value \n 4. print list\n 5. generate a tree \n Else. Exit \n Choice:");
choice = input.nextInt();
switch(choice)
{
case 1:
treeObj = createBTree();
break;
case 2:
Node newnode= new Node();
newnode.data = getData();
newnode.left=null;
newnode.right=null;
treeObj.createNode(treeObj.head,newnode);
break;
case 3:
//searchnode();
break;
case 4:
System.out.println("inorder traversal of list gives follows");
treeObj.print();
break;
case 5:
Node tempHead = treeObj.generateTree();
System.out.println("inorder traversal of list with head = ("+tempHead.data+")gives follows");
treeObj.inorder(tempHead);
break;
default:
return;
}
}while(true);
}
public static Integer getData()
{
System.out.println("Enter the value to insert:");
return (Integer)input.nextInt();
}
public static BinaryTree createBTree()
{
return new BinaryTree();
}
public static void main(String[] args)
{
displaymenu();
}
}
[Update] : Updated the code to generate a binary tree using an array. This will involve less user interaction.
Best way to implement Binary Tree in Java with all the traverse types and test cases as below
package com.nitin.tree;
public class Tree
{
private Node parent;
private int data;
private int size = 0;
public Tree() {
parent = new Node(data);
}
public void add(int data) {
if (size == 0) {
parent.data = data;
size++;
} else {
add(parent, new Node(data));
}
}
private void add(Node root, Node newNode) {
if (root == null) {
return;
}
if (newNode.data < root.data) {
if (root.left == null) {
root.left = newNode;
size++;
} else {
add(root.left, newNode);
}
} else {
if (root.right == null) {
root.right = newNode;
size++;
} else {
add(root.right, newNode);
}
}
}
public int getLow() {
Node current = parent;
while (current.left != null) {
current = current.left;
}
return current.data;
}
public int getHigh() {
Node current = parent;
while (current.right != null) {
current = current.right;
}
return current.data;
}
private void in(Node node) {
if (node != null) {
in(node.left);
System.out.print(node.data + " ");
in(node.right);
}
}
private void pre(Node node) {
if (node != null) {
System.out.print(node.data + " ");
pre(node.left);
pre(node.right);
}
}
private void post(Node node) {
if (node != null) {
post(node.left);
post(node.right);
System.out.print(node.data + " ");
}
}
public void preorder() {
System.out.print("Preorder Traversal->");
pre(parent);
System.out.println();
}
public void postorder() {
System.out.print("Postorder Traversal->");
post(parent);
System.out.println();
}
public void inorder() {
System.out.print("Inorder Traversal->");
in(parent);
System.out.println();
}
private class Node {
Node left;
Node right;
int data;
public Node(int data) {
this.data = data;
}
}
public String toString() {
Node current = parent;
System.out.print("Traverse From Left ");
while (current.left != null && current.right != null) {
System.out.print(current.data + "->[" + current.left.data + " " + current.right.data + "] ");
current = current.left;
}
System.out.println();
System.out.print("Traverse From Right ");
current = parent;
while (current.left != null && current.right != null) {
System.out.print(current.data + "->[" + current.left.data + " " + current.right.data + "] ");
current = current.right;
}
return "";
}
public static void main(String af[]) {
Tree t = new Tree();
t.add(40);
t.add(25);
t.add(78);
t.add(10);
t.add(32);
t.add(50);
t.add(93);
t.add(3);
t.add(17);
t.add(30);
t.add(38);
System.out.println(t.getLow());
System.out.println(t.getHigh());
System.out.println("Size-" + t.size);
System.out.println(t);
t.inorder();
t.preorder();
t.postorder();
}
}
Your problem is in public void createNodes(Node temp, T data) function. You pass in a parameter the same name as the class variable temp. First of all I don't think you need the class variable by itself. Second of all assigning to temp in this method has only local effect - you loose the information in the temp parameter, but setting temp, will not infuence its value in the called method. I suggest you rewrite the method so that it returns the pointer to the newly created node and assign this pointer to the left and right of the local temp. That way the changes will propagate out.
another type of outputting the tree:
public void inorder()
{
inorder(root);
}
protected void visit(BSTNode<T> p)
{
System.out.println("Node: " + p.el + "Left Side:" + (p.left!=null?p.left.el:"null") +
"Right Side:" + (p.right!=null?p.right.el:"null"));
}
I've changed the BinaryTree Class as below. See the change on the the createNode method in particular.
The problem, as mentioned in the post before this, is that your reference doesn't persist when it is passed as an argument to the createNode method. That change is only local. You need to return an explicit Node reference in the method itself as you're creating the node.
public Node createNode()
{
Integer value = getData();
Node temp = new Node(value);
if(head==null)
{
head = temp;
}
System.out.println("Do you want to add left branch on node("+value+")? Enter y/n");
if(input.next().charAt(0)=='y')
{
temp.left=createNode();
}
System.out.println("Do you want to add right branch on node("+value+")? Enter y/n");
if(input.next().charAt(0)=='y')
{
temp.right=createNode();
}
return temp;
}
Here is the resulting output:
Basic operations on a tree:
1. Create tree
2. Insert
3. Search value
4. print list
Else. Exit
Choice:1
Basic operations on a tree:
1. Create tree
2. Insert
3. Search value
4. print list
Else. Exit
Choice:2
Enter the value to insert:
10
Do you want to add left branch on node(10)? Enter y/n
y
Enter the value to insert:
20
Do you want to add left branch on node(20)? Enter y/n
n
Do you want to add right branch on node(20)? Enter y/n
n
Do you want to add right branch on node(10)? Enter y/n
y
Enter the value to insert:
30
Do you want to add left branch on node(30)? Enter y/n
n
Do you want to add right branch on node(30)? Enter y/n
n
Basic operations on a tree:
1. Create tree
2. Insert
3. Search value
4. print list
Else. Exit
Choice:4
20
10
30
I hope this will be of some help to someone later (even if this is 3 years late..). I just started learning about Binary Trees today myself. I'm actually planning on using this as a base to doing more involved tasks!
I changed the createNode method so that it works:
public Node createNode(Node temp, Integer value)
{
Node newnode = new Node();
value = getData();
newnode.data = value;
temp = newnode;
if(head == null)
{
head = temp;
}
System.out.println("If left child exits for ("+value+") enter y else n");
if(input.next().charAt(0) == 'y')
{
newnode.left = createNode(newnode.left, value);
}
System.out.println("If right child exits for ("+value+") enter y else n");
if(input.next().charAt(0) == 'y')
{
newnode.right = createNode(newnode.right, value);
}
return newnode;
}
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]);
}
}
}