I'm trying to create a Linked List dequeue class that accepts nodes at the head as well as rear. My method, tailRemove() should remove only the item at the tail of the deque. However, when I print it, it's printing the address. The toString() method works fine for all the other methods, so I'm not sure what I'm doing wrong here. Thanks for your help!
public class LinkedDequeue
{
private QueueNode front; //index of current front element
private QueueNode rear; //index of current rear element
private int count; //current # of elements
class QueueNode
{
private Object data;
private QueueNode link;
}
public LinkedDequeue ()
{
front = new QueueNode();
rear = new QueueNode();
count = 0;
}
public void headAdd (Object o)
{
QueueNode temp = new QueueNode();
temp.data = o;
if (isEmpty())
{
front = temp;
rear = front;
front.link = null;
rear.link = null;
}
else
{
temp.link = front;
front = temp;
}
count++;
}
public void tailAdd (Object o)
{
QueueNode temp = new QueueNode();
temp.data = o;
temp.link = null;
if (front == null) front = rear = temp;
else
{
rear.link = temp;
rear = temp;
}
count++;
}
public Object tailPeek()
{
return rear.data;
}
public Object tailRemove()
{
QueueNode temp = new QueueNode ();
QueueNode end = new QueueNode();
if (isEmpty()) return null;
else
{
temp = front;
while (temp.link != rear)
{
temp = temp.link;
}
end = rear;
rear.data = temp.data;
rear.link = null;
count--;
return end;
}
}
public String toString()
{
QueueNode current = front;
StringBuilder elements = new StringBuilder();
while (current != null)
{
elements.append (current.data + "\n");
current = current.link;
}
return elements.toString();
}
public static void main (String [] args)
{
LinkedDequeue list = new LinkedDequeue ();
list.headAdd ("test?");
list.tailAdd("in the middle perhaps");
list.tailAdd ("yikes, does this work?");
System.out.println (list.toString());
System.out.println (list.tailPeek());
System.out.println (list.tailRemove());
}
}
The method tailRemove() returns back an Object of type QueueNode. So when you pass it to System.out.println() it invokes the toString() method of QueueNode class. Since you haven't provided a custom implementation of toString() in your QueueNode class it calls the default implementation in Object class and prints the hashCode of the Object.
Solution :
You need to override toString() method in your QueueNode class as well.
As Kakarot mentioned, creating a toString() method in the QueueNode class will solve the problem. Your end variable, which is what you are printing, doesn't have a custom toString() method.
The reason is that in Java, the default toString() method every object has only prints its memory address. If you want it to do something useful, you need to override it yourself.
Related
I am trying to return all node contents that match a given String input. What I am trying to do is essentially a very simple search engine, where the user is able to type in a String and the program returns all characteristically similar contents it can find in the linked list. The linked list itself is built from a file, formatted as
<<Game’s Name 0>>\t<<Game’s Console 0>>\n
<<Game’s Name 1>>\t<<Game’s Console 1>>\n
where the lines are delimited with a \n and the game and its corresponding console are delimited with a \t.
My current methodology follows searching the linked list with a while loop, assigning a temporary value to the head and reassigning it to it's link as it goes down the list. Once the loop finds contents within a node that matches the current input, it stops the loop and returns the data found in the node. I have yet to try if this could be done with a for loop, as the while loop more than likely would not know when to continue once it has found a match. I am also unsure if the while loop argument is the most efficient one to use, as my understanding of it is very minimal. I believe !temp.equals(query) is stating "temp does not equal query," but I have a feeling that this could be done in a more efficient manner.
This is what I have so far, I will provide the entire Generic linked list class for the sake of context, but the method I am questioning is the very last one, found at line 126.
My explicitly stated question is how can I search through a linked list's contents and return those contents through the console.
import java.io.FileNotFoundException;
import java.util.Scanner;
public class GenLL<T>
{
private class ListNode
{
T data;
ListNode link;
public ListNode(T aData, ListNode aLink)
{
data = aData;
link = aLink;
}
}
private ListNode head;
private ListNode current;
private ListNode previous;
private int size;
public GenLL()
{
head = current = previous = null;
this.size = 0;
}
public void add(T aData)
{
ListNode newNode = new ListNode(aData, null);
if (head == null)
{
head = current = newNode;
this.size = 1;
return;
}
ListNode temp = head;
while (temp.link != null)
{
temp = temp.link;
}
temp.link = newNode;
this.size++;
}
public void print()
{
ListNode temp = head;
while (temp != null)
{
System.out.println(temp.data);
temp = temp.link;
}
}
public void addAfterCurrent(T aData)
{
if (current == null)
return;
ListNode newNode = new ListNode(aData, current.link);
current.link = newNode;
this.size++;
}
public T getCurrent()
{
if(current == null)
return null;
return current.data;
}
public void setCurrent(T aData)
{
if(aData == null || current == null)
return;
current.data = aData;
}
public void gotoNext()
{
if(current == null)
return;
previous = current;
current = current.link;
}
public void reset()
{
current = head;
previous = null;
}
public boolean hasMore()
{
return current != null;
}
public void removeCurrent()
{
if (current == head)
{
head = head.link;
current = head;
}
else
{
previous.link = current.link;
current = current.link;
}
if (this.size > 0)
size--;
}
public int getSize()
{
return this.size;
}
public T getAt(int index)
{
if(index < 0 || index >= size)
return null;
ListNode temp = head;
for(int i=0;i<index;i++)
temp = temp.link;
return temp.data;
}
public void setAt(int index, T aData)
{
if(index < 0 || index >= size || aData == null)
return;
ListNode temp = head;
for (int i = 0; i < index; i++)
temp = temp.link;
temp.data = aData;
}
public T search() throws FileNotFoundException {
Scanner keyboard = new Scanner(System.in);
System.out.println("Search: ");
String query = keyboard.nextLine();
ListNode temp = head;
while(!temp.equals(query))
temp = temp.link;
return temp.data;
//plus some sort of print function to display the result in the console
}
}
You can apply regex for every node's content, if the data type is string apply it if it is of some other datatype convert it into string if possible, else throw some exceptions.
I have to write a duplicate function that duplicates every element of a linked list and returns a linked list such that if L = [2,3,4] then duplicate(L) = [2,2,3,3,4,4]. I have to do this recursively. I realize that below is not the correct solution, but I got confused. =(
public class MyList {
int value;
MyList next;
public static MyList duplicate(MyList L){
if(L.next == null){
L.next.value = L.value;
L.next.next = null;
} else {
MyList temp = L.next;
L.next.value = L.value;
L.next.next = temp;
duplicate(L.next);
}
return L;
}
}
First, check that L isn't an empty list (null). If it contains a value, return a new list that has that value repeated twice, followed by duplicating the rest of the list.
By giving MyList a constructor, this is more readable.
public class MyList {
int value;
MyList next;
public MyList(int value, MyList next) {
this.value = value;
this.next = next;
}
public static MyList duplicate(MyList list) {
if (list == null) {
return null;
} else {
return new MyList(list.value,
new MyList(list.value,
duplicate(list.next)));
}
}
}
You currently add an item and then call the recursion on it, ending at endlessly adding items.
You either need to at elements behind your recursion when processing in a forward-direction, or after the recursion when processing backwards.
Let's create a backwards-direction version. We first recursively walk to the end of the list and then resolve the recursion backwards, adding items after our current element each time.
public <E> void duplicateEntries(MyLinkedList<E> list) {
// Do nothing if list is empty
if (list.size() != 0) {
// Call the recursive method on the head node
duplicateEntriesHelper(list.head);
}
}
public <E> void duplicateEntriesHelper(Node<E> node) {
// Walk to the end of the list
if (node.next != null) {
duplicateEntriesHelper(node.next);
}
// Resolve recursion, duplicate current
// entry by inserting it after the current element
Node<E> duplicatedEntry = new Node<>();
duplicatedEntry.data = node.data;
// Insert element after current node
duplicatedEntry.next = node.next;
node.next = duplicatedEntry;
}
The classes I used should look similar to:
public class MyLinkedList<E> {
public Node<E> head = null;
#Override
public String toString() {
// Build something like "MyLinkedList[2, 3, 4]"
StringBuilder sb = new StringBuilder();
sb.append("MyLinkedList[");
StringJoiner sj = new StringJoiner(",");
Node<E> node = head;
while (node != null) {
sj.add(node);
node = node.next;
}
sb.append(sj);
sb.append("]");
return sb.toString();
}
}
public class Node<E> {
public Node next = null;
public E data = null;
#Override
public String toString() {
return E;
}
}
And here is the demo:
public static void main(String[] args) {
// Setup the list
MyLinkedList<Integer> list = new MyLinkedList<>();
Node<Integer> first = new Node<>();
first.data = 2;
Node<Integer> second = new Node<>();
second.data = 3;
Node<Integer> third = new Node<>();
third.data = 4;
list.head = data;
first.next = second;
second.next = third;
// Demonstrate the method
System.out.println("Before: " + list);
duplicateEntries(list);
System.out.println("After: " + list);
}
Of course you can add additional methods and functionality to them. For example using some constructors or getter/setter methods.
I'm having trouble with a project I have for my OOP class. I'm nearly finished, but still lack a toString method and a main method. Not really sure how to go about it and would appreciate any help.
I want my toString method to function as follows:
Returns a string representation of all the items stored in the list. A string representation of an empty list looks like head--><--tail
A string representation of a non-empty list looks like:
head-->134<-->-8<-->42<-->1<--tail
public class IntegerNode{
private IntegerNode next;
private IntegerNode prev;
private int data;
public IntegerNode(int data){
next = next;
prev = prev;
data = data;
}
public int getData(){
data = data;
return this.data;
}
public IntegerNode getNext(){
return next;
}
public IntegerNode getPrevious(){
return prev;
}
public void setNext(IntegerNode in){
prev = in;
}
public void setPrevious(IntegerNode in){
prev = in;
}
}
and here is what I have so far in my IntegerLinkedList class
public class IntegerLinkedList{
private IntegerNode head;
private IntegerNode tail;
public IntegerLinkedList(){
head = null;
tail = null;
}
public void addFirst(int x){
IntegerNode nH = new IntegerNode(x);
if (head == null) {
head = nH;
tail = nH;
}else{
head.setPrevious(nH);
nH.setNext(head);
head = nH;
}
}
public void addLast(int x){
IntegerNode t = new IntegerNode(x);
if (tail == null){
head = t;
tail = t;
}else{
tail.setNext(t);
t.setPrevious(tail);
tail = t;
}
}
public int peekFirst(){
return head.getData();
}
public int peekLast(){
return tail.getData();
}
public String toString(){
if (head == null && tail == null){
String empty = "head--><--tail";
return empty;
}else{
String h = "Head--> " + head;
String t = tail + " <--Tail";
String m = " <--> ";
// while(IntegerNode.getNext() != null)
//}
//return h + m + t;
}
}
public int pollFirst(){
int x = head.getData();
head = head.getNext();
head.setPrevious(null);
return x;
}
public int pollLast(){
int x = tail.getData();
tail = tail.getPrevious();
tail.setNext(null);
return x;
}
}
I'm thinking a while loop is the way to go here, but then again I'm not sure.
Here's how to write it:
#Override // <-- Annotate that you are overriding the toString() method
public String toString(){
if (head == null && tail == null){
String empty = "head--><--tail";
return empty;
}else{
StringBuilder sb = new StringBuilder();
sb.append("Head-->");
IntegerNode curr = head;
sb.append(curr.getData());
curr = curr.getNext();
while(curr != null) {
sb.append("<-->");
sb.append(curr.getData());
curr = curr.getNext();
}
sb.append("<--tail");
return sb.toString();
}
}
As an alternative, you can simplify the logic to not have an outer if else:
#Override // <-- Annotate that you are overriding the toString() method
public String toString(){
StringBuilder sb = new StringBuilder();
sb.append("Head-->");
IntegerNode curr = head;
if (curr == null)
{
sb.append("<--tail");
return sb.toString();
}
sb.append(curr.getData());
curr = curr.getNext();
while(curr != null) {
sb.append("<-->");
sb.append(curr.getData());
curr = curr.getNext();
}
sb.append("<--tail");
return sb.toString();
}
Yes, you have to use a loop, because you want to iterate over data of unknown length. Michael Markidis wrote the answer more quickly than me, use his solution, however I would suggest some improvements to your code.
String h = "Head--> " + head; won't work, because head is an object IntegerNode, and you want to access its data like this head.getData() (also why do you assign data = data; in this method? It should only do return)
If you want to assign data in constructor that have the same name as field, use have to use this keyword to make clear what do you want to assign. Also assigning null next and prev has no meaning, so this code
public IntegerNode(int data){
next = next;
prev = prev;
data = data;
}
should look like this
public IntegerNode(int data){
this.data = data;
}
or if you want to assign the previous and next node
public IntegerNode(int data, IntegerNode next, IntegerNode prev){
this.next = next;
this.prev = prev;
this.data = data;
}
If you are using Java 8+, StringJoiner makes it easy.
#Override
public String toString() {
StringJoiner joiner = new StringJoiner("<-->", "head-->", "<--tail");
for (IntegerNode node = this.head; node != null; node = node.getNext())
joiner.add(String.valueOf(node.getData()));
return joiner.toString();
}
If not using Java 8, a StringBuilder is the right way to go.
(Performs better than using String directly)
#Override
public String toString() {
StringBuilder buf = new StringBuilder("head-->");
boolean sep = false;
for (IntegerNode node = this.head; node != null; node = node.getNext()) {
if (sep)
buf.append("<-->");
buf.append(node.getData());
sep = true;
}
return buf.append("<--tail").toString();
}
In both cases, you use a basic for loop with a node variable to iterate through the list.
As for the rest of your code, you have some issues.
public IntegerNode(int data){
next = next;
prev = prev;
data = data;
}
Assigning next to next and prev to prev is meaningless.
Assigning the parameter to the field will only work if you qualify the field with this., otherwise you're assigning the parameter to itself (meaningless).
public IntegerNode(int data){
this.data = data;
}
public int getData(){
data = data;
return this.data;
}
Assigning data to data is meaningless.
public int getData(){
return this.data;
}
public void setNext(IntegerNode in){
prev = in;
}
Copy/paste error. You meant to assign to next.
public void setNext(IntegerNode in){
next = in;
}
public int pollFirst(){
int x = head.getData();
head = head.getNext();
head.setPrevious(null);
return x;
}
public int pollLast(){
int x = tail.getData();
tail = tail.getPrevious();
tail.setNext(null);
return x;
}
These methods will throw NullPointerException when you poll the last1 value from the list.
Add missing if statement.
public int pollFirst(){
int x = head.getData();
head = head.getNext();
if (head == null)
tail = null;
else
head.setPrevious(null);
return x;
}
public int pollLast(){
int x = tail.getData();
tail = tail.getPrevious();
if (tail == null)
head = null;
else
tail.setNext(null);
return x;
}
1) "last" refers to the "only remaining" value, not the "tail" value.
How can I use the toString method, instead of my custom print method below, in my code? My current code's output is exactly what it is supposed to be, but my instructor wants me "to use toString and get same output". I am confused and do not know how to do it.
Here is my code:
public class LinkedListIntro {
//print method
public static void print(Node temp) {
System.out.print("[");
while (temp.getNext() != null) {
System.out.print(temp.getData() + ", ");
temp = temp.getNext();
}
System.out.println(temp.getData() + "]");
}
public static void main(String[] args) {
Node start = null;
Node temp = null;
for (int i = 1; i <= 5; i++) {
if (start == null) {
start = new Node(i);
temp = start;
} else {
temp.setNext(new Node(i));
temp = temp.getNext();
}
}
//3. printing data
print(start);
//4. removing 4
temp = start;
Node n = temp.getNext();
while (n.getNext() != null) {
if ((int) n.getData() == 4) {
temp.setNext(n.getNext());
n = null;
break;
}
temp = temp.getNext();
n = n.getNext();
}
//5. printing data again after removing 4
print(start);
//6. adding 100 between 1 and 2
temp = start;
Node n1 = temp.getNext();
while (n1.getNext() != null) {
if ((int) temp.getData() == 1) {
temp.setNext(new Node(100));
temp = temp.getNext();
temp.setNext(n1);
}
temp = temp.getNext();
n1 = n1.getNext();
}
//7. printing data again after adding 100
print(start);
//8. removing first node
temp = start;
start = start.getNext();
temp = null;
//printing data after removing 1st node
print(start);
//9. add 0 to beginning
temp = start;
start = new Node(0);
start.setNext(temp);
//printing the final data
print(start);
}
}
public class Node<E>
{
private E data;
private Node next;
public Node(E data) {
this.data = data;
this.next = null;
}
public E getData(){
return data;
}
public Node getNext() {
return next;
}
public void setNext(Node next) {
this.next = next;
}
public String toString() {
return data.toString();
}
}
Use the code in you current print method to build an output string in toString() method of Node. After that, print can just pass the Node temp parameter to System.out.print(), cause it uses toString() internally.
public static void print(Node temp) { //irrelevant method by now
System.out.print(temp);
}
public class Node<E>{
private E data;
private Node next;
//...
public String toString() {
String ouput = "";
Node node = this;
while(node.getNext() != null) {
output += node.getData() +", ";
node = node.getNext();
}
return ouput;
}
}
The toString() methods returns a "string representation" of the object, which means that it returns information about an object as a string. toString() is overridden by the each class that implements it. The global superclass (Object) has a .toString() method but it usually doesn't return the information we want. I think he wants you to make your own toString() that returns a string representation of the Node object. Then you can call System.out.print() on this string to display it.
I would create a toString method which returns a string in LinkedListIntro class which would do what your print method is doing. But instead of printing it would keep appending the value to a string and return the string
I believe what your instructor means is that in the class's toString(), you have to return a string for the entire linked list, not just for the current node.
The trick is that to do it properly, you'll probably need to do it either recursively or with a helper variable. You'll basically need to prepend the current item's data's toString() result to whatever you get from next.
Once you do that, you won't need the print function.
I think your instructor wants you to implement the method toString() in your class.
Every class your create is children of Object class, since this is the superclass for every object. This class has some methods like toString(). In your new class, you should override the method toString(). This method must return a String, which should be a description or some helpfull text about every object of this class.
The purpose of this is that if your new class is cast as Object, when you call the toString() method, it gets the right representation of the new class.
You have a class:
public class SomeClass {
public String text;
public SomeClass() {
text = "hello world";
}
#Override public String toString() {
return (text);
}
}
And in your main function:
public static void main(String[] args) {
//new object of type SomeClass
SomeClass someClass = new SomeClass();
System.out.println(someClass.toString());
//casting it to superclass Object
Object someClass_cast = (Object)someClass;
System.out.println(someClass_cast.toString());
}
Your output will be:
hello world
hello world
I hope this can help you.
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 + ">";
}
}
}