Java Reverse a LinkedList -- Debugger wont even work - java

So basically I created my own linkedlist class, and now I'm adding a function called reverse that reverses it. The strange thing is, it's not working and I can't even debug! I have no idea whats going on, if someone could pull my code and let me know whats happening that would be amazing. I have both my Node class and LinkedList class in one file, and the reverse function is called reverse. If you try to use reverse now, it doesn't work, freezes the debugger, and doesn't even let me step through the while loop after the first iteration. (I'm using IntelliJ)
class Node<Type> {
private Type data;
private Node<Type> nextNode;
public Node(Type data) {
this.data = data;
}
public void setData(Type data) {
this.data = data;
}
public Type getData(){
return data;
}
public void setNextNode(Node<Type> nextNode) {
this.nextNode = nextNode;
}
public Node<Type> getNextNode() {
return nextNode;
}
#Override
public String toString(){
return "Data: " + this.data;
}
}
public class LinkedList<Type> {
private Node<Type> head;
private int length;
public LinkedList() {
length = 0;
}
// Returns: Pointer to the first Node in the list where Node.getData().equals(data)
// O(N)
public Node<Type> find(Type data) {
Node<Type> currentNode = head;
while(currentNode != null) {
if(currentNode.getData().equals(data)) {
return currentNode;
}
currentNode = currentNode.getNextNode();
}
return null;
}
// Returns: the length of the list
// O(1)
public int getLength() {
return length;
}
// Create a node with data and add it to the front of the list
// O(1)
public void addAtHead(Type data) {
Node<Type> newHead = new Node<Type>(data);
newHead.setNextNode(this.head);
this.head = newHead;
length += 1;
}
// Delete the head node (garbage collection)
// O(1)
public void deleteHead(){
if(this.head != null) {
this.head = this.head.getNextNode();
length -= 1;
}
}
public void reverse() {
Node<Type> rememberMe = head.getNextNode();
while(rememberMe != null) {
Node<Type> temp = head;
head = rememberMe;
rememberMe = head.getNextNode();
head.setNextNode(temp);
}
}
// Print out the node using node.toString
// Eg. { node1.toString() , node2.toString() , node3.toString() }
// O(N)
#Override
public String toString(){
String result = "{";
Node<Type> currentNode = this.head;
while(currentNode != null) {
result += " " + currentNode.toString() + " ";
currentNode = currentNode.getNextNode();
if(currentNode != null) {
result += ", ";
}
}
result += "}";
return result;
}
}

After reverse the original head still has a next that points back to what was the second element but now is the second to last so that after reversing you have a loop at the end. This means the toString() function has an infinite loop in it, which the intellij debugger is probably calling.
To fix, keep track of the original head and set its next to null.
public void reverse() {
Node<Type> orig_head = head;
Node<Type> rememberMe = head.getNextNode();
while(rememberMe != null) {
Node<Type> temp = head;
head = rememberMe;
rememberMe = head.getNextNode();
head.setNextNode(temp);
}
orig_head.setNextNode(null);
}

Related

AddFirst() method doesn't work in my Linked List

Don't understand why my addFirst() method doesn't work. When I ask for the size of list, it returns 1 but I added 3 words. It looks like the program takes only one element and forgets about the previous. I removed all the other irrelevant code and left only the one connected to my question with the addFirst() method. Here's the code:
Node object:
public class Node<Type> {
private Type data;
private Node<Type> next;
public Node(Type data) {
this.data = data;
next = null;
}
public Type getData() {
return data;
}
public void setData(Type data) {
this.data = data;
}
public Node getNext() {
return next;
}
public void setNext(Node next) {
this.next = next;
}
}
Main Method:
public class MyMain<Type> {
public static void main(String[] args) {
MyList<String> list = new MyList<String>();
System.out.println("The size is: " + list.size());
String s1 = "Summer";
String s2 = "Spring";
String s3 = "Winter";
list.addFirst(s2);
list.addFirst(s3);
list.addFirst(s1);
System.out.println("The size is: " + list.size());
}
}
Linked List:
public class MyList<Type> {
private Node<Type> head;
public MyList() {
head = null;
}
public int size() {
int length = 0;
Node<Type> current = head;
while (current != null) {
current = current.getNext();
length++;
}
return length;
}
public void addFirst(Type data) {
Node<Type> newFirst = new Node<Type>(data);
if (head == null) {
head = newFirst;
} else {
newFirst = newFirst.getNext();
newFirst = head;
head = newFirst.getNext();
}
}
}
Very confused and would appreciate any help, thank you!
I added comments to your original code, to explain what it actually does.
If you want addFirst to put the new element at the head of the list, you should change:
public void addFirst(Type data) {
Node<Type> newFirst = new Node<Type>(data);
if (head == null) {
head = newFirst;
} else {
newFirst = newFirst.getNext(); // here you assign null to newFirst
newFirst = head; // head you assign the old head to newFirst
head = newFirst.getNext(); // here you assign null to head, making the list empty
}
}
to:
public void addFirst(Type data) {
Node<Type> newFirst = new Node<Type>(data);
if (head == null) {
head = newFirst;
} else {
newFirst.setNext(head); // the old head of the list should be the
// next element of the new Node
head = newFirst; // make the new Node the head of the list
}
}
Your logic inside the else block of the addFirst method is not correct.
Your code in the addFirst method creates a new node, saves its reference in newFirst variable but then immediately discards the new node as a result of the following statement:
newFirst = newFirst.getNext();
Following statement then points newFirst to the node referenced by the head which is the first node inserted in the list.
newFirst = head;
Finally, you assign null to head:
head = newFirst.getNext();
Solution:
What you need to do is:
Set next of the newFirst to the node referenced by the head
newFirst.setNext(head);
Point head to the newFirst node
head = newFirst;
Full method code:
public void addFirst(Type data) {
Node<Type> newFirst = new Node<Type>(data);
if (head == null) {
head = newFirst;
} else {
newFirst.setNext(head);
head = newFirst;
}
}

Reversing a singly linked list in java

I made a singly linked list from scratch in java. The code is as follows:
public class SingleLinkedList<Item>
{
private Node head;
private int size;
private class Node
{
Item data;
Node next;
public Node(Item data)
{
this.data = data;
this.next = null;
}
public Node(Item data, Node next)
{
this.data = data;
this.next = next;
}
//Getters and setters
public Item getData()
{
return data;
}
public void setData(Item data)
{
this.data = data;
}
public Node getNext()
{
return next;
}
public void setNext(Node next)
{
this.next = next;
}
}
public SingleLinkedList()
{
head = new Node(null);
size = 0;
}
public void add(Item data)
{
Node temp = new Node(data);
Node current = head;
while(current.getNext() != null)
{
current = current.getNext();
}
current.setNext(temp);
size++;
}
public void add(Item data, int index)
{
Node temp = new Node(data);
Node current = head;
for(int i=0; i<index && current.getNext() != null; i++)
{
current = current.getNext();
}
temp.setNext(current.getNext());
current.setNext(temp);
size++;
}
public Item get(int index)
{
if(index <= 0)
{
return null;
}
Node current = head;
for(int i=1; i<index; i++)
{
if(current.getNext() == null)
{
return null;
}
current = current.getNext();
}
return current.getData();
}
public boolean remove(int index)
{
if(index < 1 || index > size())
{
return false;
}
Node current = head;
for(int i=1; i<index; i++)
{
if(current.getNext() == null)
{
return false;
}
current = current.getNext();
}
current.setNext(current.getNext().getNext());
size--;
return true;
}
public String toString()
{
Node current = head.getNext();
String output = "";
while(current != null)
{
output+=current.getData().toString()+" ";
current = current.getNext();
}
return output;
}
public int size()
{
return size;
}
public void reverse()
{
Node current = head;
Node prevNode = null;
Node nextNode;
while(current!=null)
{
nextNode = current.getNext();
current.setNext(prevNode);
prevNode = current;
current = nextNode;
System.out.println(prevNode.getData());
}
head = prevNode;
}
}
As you can see, I added the reverse function in the class only.
But when I tried actually using the class it gave NullPointerException after I tried to reverse it.
To check the functionality I used another class called TEST. The code is as follows:
public class TEST
{
public static void main(String[] args)
{
SingleLinkedList<Integer> list = new SingleLinkedList<Integer>();
list.add(1);
list.add(2);
list.add(3);
list.add(4);
list.add(5);
System.out.println(list.toString());
list.reverse();
System.out.println(list.toString());
}
}
The output is as follows:
1 2 3 4 5
null
1
2
3
4
5
Exception in thread "main" java.lang.NullPointerException
at SingleLinkedList.toString(SingleLinkedList.java:129)
at TEST.main(TEST.java:20)
I tried to print the value of prevNode to check whether its not taking values...but it is.
What to do?
Actually, your reverse method looks fine.
The problem is your toString() method.
When you create a new list, you create an initial element whose data is null.
Your toString method skips that first element, so it works fine as long as you don't reverse the list.
But when you reverse the list, that null element becomes the last element, and when you call output+=current.getData().toString()+" "; for that last element when current.getData() is null, you get NullPointerException.
You have several options :
Your reverse method can keep the initial null element first (i.e. reverse the rest of the list, but keep the head the same). This way toString can remain unchanged.
Eliminate the initial null element. Then your toString method doesn't have to skip anything.
Keeping the null element first :
public void reverse()
{
Node current = head.getNext();
Node prevNode = null;
Node nextNode;
while(current!=null)
{
nextNode = current.getNext();
current.setNext(prevNode);
prevNode = current;
current = nextNode;
System.out.println(prevNode.getData());
}
head.setNext(prevNode);
}
The problem is in your SingleLinkedList.java toString() method
Try below it is working fine
public String toString() {
Node current = head;
String output = "";
while (current != null) {
// output += current.getData().toString() + " ";
output += String.valueOf(current.getData()) + " ";
current = current.getNext();
}
return output;
}
while(current!=null)
This is your problem. When you hit the last node the 'next' node you get is actually null.
Try changing it to
while(current!=null&&current.getNext()!=null)
EDIT: Actually not sure that solution will work. Try putting a conditional at the end of your loop that says:
if(current.getNext()==null)
break;
EDIT (again :/):
ok sorry I wasn't thinking straight.
change that final if statement to:
if(current.getNext()==null){
current.setNext(prevNode);
break;
}
The actual nullpointer is in the toString. Here's what you do:
Change the while conditional to
while(current != null&&current.getData()!=null)
Because otherwise if current points to null then you get an exception.
That was exhausting.

Recursion - Reverse LinkedList with void function return type

I was trying to reverse a linked list using recursion. I got the solution, but can't get it to work for below question found on internet.
Reverse a linked list using recursion but function should have void
return type.
I was able to implement the function with return type as Node. Below is my solution.
public static Node recursive(Node start) {
// exit condition
if(start == null || start.next == null)
return start;
Node remainingNode = recursive(start.next);
Node current = remainingNode;
while(current.next != null)
current = current.next;
current.next = start;
start.next = null;
return remainingNode;
}
I cannot imagine if there will be such a solution to this problem.
Any suggestions ?
Tested, it works (assuming you have your own implementation of a linked list with Nodes that know the next node).
public static void reverse(Node previous, Node current) {
//if there is next node...
if (current.next != null) {
//...go forth and pwn
reverse(current, current.next);
}
if (previous == null) {
// this was the start node
current.next= null;
} else {
//reverse
current.next= previous;
}
}
You call it with
reverse(null, startNode);
public void recursiveDisplay(Link current){
if(current== null)
return ;
recursiveDisplay(current.next);
current.display();
}
static StringBuilder reverseStr = new StringBuilder();
public static void main(String args[]) {
String str = "9876543210";
reverse(str, str.length() - 1);
}
public static void reverse(String str, int index) {
if (index < 0) {
System.out.println(reverseStr.toString());
} else {
reverseStr.append(str.charAt(index));
reverse(str, index - 1);
index--;
}
}
This should work
static void reverse(List list, int p) {
if (p == list.size() / 2) {
return;
}
Object o1 = list.get(p);
Object o2 = list.get(list.size() - p - 1);
list.set(p, o2);
list.set(list.size() - p - 1, o1);
reverse(list, p + 1);
}
though to be efficient with LinkedList it should be refactored to use ListIterator
I am not familiar with Java, but here is a C++ version. After reversing the list, the head of list is still preserved, which means that the list can still be accessible from the old list head List* h.
void reverse(List* h) {
if (!h || !h->next) {
return;
}
if (!h->next->next) {
swap(h->value, h->next->value);
return;
}
auto next_of_next = h->next->next;
auto new_head = h->next;
reverse(h->next);
swap(h->value, new_head->value);
next_of_next->next = new_head;
h->next = new_head->next;
new_head->next = nullptr;
}
Try this code instead - it actually works
public static ListElement reverseListConstantStorage(ListElement head) {
return reverse(null,head);
}
private static ListElement reverse(ListElement previous, ListElement current) {
ListElement newHead = null;
if (current.getNext() != null) {
newHead = reverse(current, current.getNext());
} else {//end of the list
newHead=current;
newHead.setNext(previous);
}
current.setNext(previous);
return newHead;
}
public static Node recurse2(Node node){
Node head =null;
if(node.next == null) return node;
Node previous=node, current = node.next;
head = recurse2(node.next);
current.next = previous;
previous.next = null;
return head;
}
While calling the function assign the return value as below:
list.head=recurse2(list.head);
The function below is based on the chosen answer from darijan, all I did is adding 2 lines of code so that it'd fit in the code you guys want to work:
public void reverse(Node previous, Node current) {
//if there is next node...
if (current.next != null) {
//...go forth and pwn
reverse(current, current.next);
}
else this.head = current;/*end of the list <-- This line alone would be the fix
since you will now have the former tail of the Linked List set as the new head*/
if (previous == null) {
// this was the start node
current.next= null;
this.tail = current; /*No need for that one if you're not using a Node in
your class to represent the last Node in the given list*/
} else {
//reverse
current.next= previous;
}
}
Also, I've changed it to a non static function so then the way to use it would be: myLinkedList.reverse(null, myLinkedList.head);
Here is my version - void ReverseWithRecursion(Node currentNode)
- It is method of LinkListDemo Class so head is accessible
Base Case - If Node is null, then do nothing and return.
If Node->Next is null, "Make it head" and return.
Other Case - Reverse the Next of currentNode.
public void ReverseWithRecursion(Node currentNode){
if(currentNode == null) return;
if(currentNode.next == null) {head = currentNode; return;}
Node first = currentNode;
Node rest = currentNode.next;
RevereseWithRecursion(rest);
first.next.next = first;
first.next = null;
}
You Call it like this -
LinkListDemo ll = new LinkListDemo(); // assueme class is available
ll.insert(1); // Assume method is available
ll.insert(2);
ll.insert(3);
ll.ReverseWithRecursion(ll.head);
Given that you have a Node class as below:
public class Node
{
public int data;
public Node next;
public Node(int d) //constructor.
{
data = d;
next = null;
}
}
And a linkedList class where you have declared a head node, so that it can be accessed by the methods that you create inside LinkedList class. The method 'ReverseLinkedList' takes a Node as an argument and reverses the ll.
You may do a dry run of the code by considering 1->2 as the linkedList. Where node = 1, node.next = 2.
public class LinkedList
{
public Node? head; //head of list
public LinkedList()
{
head = null;
}
public void ReverseLinkedList(Node node)
{
if(node==null)
{
return;
}
if(node.next==null)
{
head = node;
return;
}
ReverseLinkedList(node.next); // node.next = rest of the linkedList
node.next.next = node; // consider node as the first part of linkedList
node.next = null;
}
}
The simplest method that I can think of it's:
public static <T> void reverse( LinkedList<T> list )
{
if (list.size() <= 1) {
return;
}
T first = list.removeFirst();
reverse( list);
list.addLast( first );
}

Reversing a Doubly-Linked-List

Hey I'm currently stuck on the reverse method of my DoublyLinkedList. Everything is working fine (somehow) except for the reverse method. I'm not receiving any errors - System.out.println(list.reverse()) simply has no output.
Any suggestions? Thank you very much in advance. :)
Okay: I have edited my code now. So far everyhing is working correctly. However, the recursive method simply prints the list in the same order, instead of actually reversing it.
Updated Code:
public class DoublyLinkedStringList {
private String content;
private DoublyLinkedStringList prev;
private DoublyLinkedStringList next;
public DoublyLinkedStringList(String info) {
content = info;
prev = null;
next = null;
}
private DoublyLinkedStringList(String content, DoublyLinkedStringList prev, DoublyLinkedStringList next) {
this.content = content;
this.prev = prev;
this.next = next;
}
public DoublyLinkedStringList prepend(String info) {
DoublyLinkedStringList newNode = new DoublyLinkedStringList(info);
prev = newNode;
newNode.next = this;
return newNode;
}
public DoublyLinkedStringList delete(int index) {
DoublyLinkedStringList curr = this;
if (index == 0) {
next.prev = null;
return next;
}
for (int i = 0; i < index; i++) {
curr = curr.next;
}
curr.prev.next = curr.next;
if (curr.prev.next != null) {
curr.prev.next.prev = curr.prev;
}
return this;
}
public DoublyLinkedStringList reverse() {
DoublyLinkedStringList currNode = this;
while (currNode != null) {
DoublyLinkedStringList temp = currNode.next;
currNode.next = currNode.prev;
currNode.prev = temp;
if (currNode.prev != null) {
currNode = currNode.prev;
}
}
return this;
}
#Override
public String toString() {
StringBuilder sb = new StringBuilder();
for (DoublyLinkedStringList currNode = this; currNode != null; currNode = currNode.next) {
sb.append(currNode.content);
if (currNode.next != null) {
sb.append(", ");
}
}
return sb.toString();
}
public static void main(String argv[]) {
DoublyLinkedStringList list = new DoublyLinkedStringList("Testliste");
list = list.prepend("6");
list = list.prepend("5");
list = list.prepend("4");
list = list.prepend("3");
list = list.prepend("2");
list = list.prepend("1");
list = list.prepend("0");
list = list.delete(1);
System.out.println(list);
list = list.reverse();
System.out.println(list);
}
}
One of the problems you are going to have with your design is when you reverse the list the head becomes the tail and the tail becomes the head. But the client is pointing to the head, and not the tail. Even if you did this operation 100% correct, you can't change the reference the client has. What you'll want to do is separate the concepts of the List as an object, and the Nodes that make up that object (currently you have combined these two concepts together because the nodes are the list and vice versa). By separating them the reference to the list is always the same regardless of what's in it, order, etc. The List contains the head and tail references, and the nodes only contain the next/prev. Right now you have head and tail in every node in your list which can make nasty bugs pop up if you don't replace every reference whenever head/tail changes (ie prepend, delete, or reverse). If you moved those two instances out of each node then you don't have to do as much maintenance to the list on changes. I think if you do that then you'll find it much easier to implement reverse.
Your error is exactly the problem I'm saying. At the end you return this, well the reference the client has was the head (ie this). However, after iterating over and reversing everything what was the head is now the tail so you've returned the new tail by returning this. And toString() on tail is NOTHING.
Normally I would implement the interface Iteratable and use an Iterator to reverse the list but I kept my revision in line with your current model. I changed the return types of the Node's getNext() and getPrev() methods to be dependent on the forward variable. Now the list never changes linkage when "reversed" but it is traversed in reverse order via the variable getNext() and getPrev() behavior.
IDEONE link to code
Consider this edit:
class DoublyLinkedStringList {
private Node head, tail;
boolean forward;
/**
* Diese Klasse repraesentiert einen Knoten in der Doubly Linked List der
* Klasse
* <code>DoublyLinkedStringList</code>
*
*/
private class Node {
private String content;
private Node next;
private Node prev;
public Node(String content) { this.content = content; }
public Node(String content, Node next) {
this.content = content;
if(forward) { this.next = next; } //EDITED
else { this.prev = next; } //EDITED
}
public Node getNext() { return (forward) ? next : prev; } //EDITED
public Node getPrev() { return (forward) ? prev : next; } //EDITED
public void setNext(Node next) {
if(forward) { this.next = next; } //EDITED
else { this.prev = next; } //EDITED
}
public void setPrev(Node prev) {
if(forward) { this.prev = prev; } //EDITED
else { this.next = prev; } //EDITED
}
}
public DoublyLinkedStringList() {
this.head = null;
this.tail = null;
}
public Node prepend(String info) {
Node newNode = new Node(info);
newNode.setPrev(null);
newNode.setNext(getHead());
if(newNode.getNext()!=null) {
newNode.getNext().setPrev(newNode); //EDITED
}
if(forward) { head = newNode; } //EDITED
else { tail = newNode; } //EDITED
if(getTail() == null) { //EDITED
if(forward) { tail = newNode; } //EDITED
else { head = newNode; } //EDITED
}
return head;
}
public Node delete(int index) {
Node currNode = getHead();
int count = 0;
if (index == 0) {
if(forward) { head = head.next; } //EDITED
else { tail = tail.prev; } //EDITED
return head;
}
while (currNode != null) {
if (count + 1 == index) {
currNode.next.prev = currNode.prev;
currNode.prev.next = currNode.next; //EDITED
break;
}
currNode = currNode.getNext(); //EDITED
count++;
}
return currNode;
}
private Node next() {
Node currNode = head;
if (forward) {
return currNode.getNext();
} else {
return currNode.getPrev();
}
}
public Node getHead() { return (forward) ? head : tail; } //EDITED
public Node getTail() { return (forward) ? tail : head; } //EDITED
public DoublyLinkedStringList reverse() { forward = !forward; return this; }
#Override
public String toString() {
StringBuilder sb = new StringBuilder();
//EDITED LOOP STRUCTURE
for (Node currNode = getHead(); currNode != null; currNode = currNode.getNext()) {
sb.append(currNode.content);
if (currNode.getNext() != null) {
sb.append(", ");
}
}
return sb.toString();
}
public static void main(String argv[]) {
DoublyLinkedStringList list = new DoublyLinkedStringList();
list.prepend("6");
list.prepend("5");
list.prepend("4");
list.prepend("3");
list.prepend("2");
list.prepend("1");
list.prepend("0");
list.delete(3);
System.out.println(list);
System.out.println(list.reverse());
}
}
you simply have to set head and tail too. then it should work. but see chubbsondubs answer for further improvement!
Since you have a DoublyLinkedStringList as return type, I think you want to return a new object. In this case I suggest you to cycle over your object and build a new List using the prepend method you already implemented (that anycase has some other error). You can start with a empty list, and, as you scan the original object, prepend current element.
Otherwise, if you want to reverse the list "in place" you should return void, change the head with the last element, and, since is double linked, your should do anything else, since there are pointers to nodes in both directions.
try this for the reverse method:
public class DoublyLinkedList {
Node first, current;
boolean forward;
//constructors... methods...
private Node next() {
if(forward) return current.next();
else return current.previous();
}
public void reverse() {
while(true) {
if(next() == null) {
first = current;
forward = !forward;
return;
}
current = next();
}
}
}
Here is just my solution. I unfortunately do not have more time for explanatory notes.
public class DoublyLinkedStringList {
private String info;
private DoublyLinkedStringList prev;
private DoublyLinkedStringList next;
public DoublyLinkedStringList(String pInfo)
{
info = pInfo;
prev = null;
next = null;
}
private DoublyLinkedStringList(String pInfo, DoublyLinkedStringList pPrev, DoublyLinkedStringList pNext)
{
info = pInfo;
prev = pPrev;
next = pNext;
}
public DoublyLinkedStringList prepend(String info)
{
DoublyLinkedStringList n = new DoublyLinkedStringList(info);
prev = n;
n.next = this;
return n;
}
public DoublyLinkedStringList delete(int index)
{
if (index == 0)
{
next.prev = null;
return next;
}
DoublyLinkedStringList d = this;
for (int i = 0; i<index; i++)
d = d.next;
// d is now the node which should be deleted
// after delete(x) "next" schould be on pos x
d.prev.next = d.next; // take the next of the prev and set the new next to the next of d
if (d.prev.next != null) // if the next of d was not set to null, it must get to know his new prev (d's prev)
d.prev.next.prev = d.prev;
return this;
}
public DoublyLinkedStringList reverse() // moe or less less similar to my implementation in IntList.java
{
DoublyLinkedStringList oldLast = getLast();
next.reverse(this);
prev = next;
next = null;
return oldLast;
}
public void reverse(DoublyLinkedStringList last)
{
if (next != null)
next.reverse(this);
prev = next;
next = last;
}
public DoublyLinkedStringList getLast()
{
if (next == null)
return this;
return next.getLast();
}
#Override
public String toString()
{
String r = "";
for (DoublyLinkedStringList i = this; i != null; i = i.next)
{
r += i.info;
if (i.next != null)
r += ", ";
}
return r;
}
public String reverseToString() // uses prev; just for testing issues :)
{
String r = "";
for (DoublyLinkedStringList i = getLast(); i != null; i = i.prev)
{
r += i.info;
if (i.prev != null)
r += ", ";
}
return r;
}
public static void main(String argv[])
{
DoublyLinkedStringList list = new DoublyLinkedStringList("Test");
list = list.prepend("6");
list = list.prepend("5");
list = list.prepend("4");
list = list.prepend("3");
list = list.prepend("2");
list = list.prepend("1");
list = list.prepend("0");
list = list.delete(1);
System.out.println(list);
System.out.println(list.reverseToString()+"\n");
list = list.reverse();
System.out.println(list);
System.out.println(list.reverseToString());
list = list.delete(6);
list = list.delete(0);
System.out.println(list);
list = list.reverse();
list = list.prepend("1");
System.out.println(list);
}

Linked list node pointing to nodes of different type

This is my first post here, but I'm not new to the site (call me a lurker).
Unfortunately this time I cannot seem to find an answer to my question without asking.
Anyway, to the point.
I am writing a small snakes and ladders (aka chutes and ladders) program in java for a data structures course. I had to write my own Linked List (LL) class, (I know that there is a java util that does it better, but I have to learn about the workings of the data structure) and that is not a problem. My LL is 'semi-Double linked' as I like to call it, since it links forward, but has another pointer field for other links, which is not necessarily used in every node.
What I want to know is if it is possible to link a node from a list to another list, which is of a different type.
Poor example:
(eg.) How would one link a node of type to a node of type ? Let us say we have a LL of 7 int values [1,2,3,4,5,6,7], and a LL of 7 Strings [Monday, Tuesday, Wednesday,Thursday, Friday, Saturday, Sunday]. We want to link the node containing 1 to the node containing Monday.
To be exact the problem I am having is as follows:
I have 100 nodes forward-linked, forming the game board, and a circularly linked list of 4 . I want to link the player nodes to their respective positions on the board, so that as they traverse the board, they can also follow the "snakes" and "ladders" links.
Thanks in advance!
My LLNode.java and LL.java are attached.
// LLNode.java
// node in a generic linked list class, with a link
public class LLNode<T>
{
public T info;
public LLNode<T> next, link;
public LLNode()
{
next = null;
link= null;
}
public LLNode(T element)
{
info = element;
next = null;
link = null;
}
public LLNode(T element, LLNode<T> n)
{
info = element;
next = n;
link = null;
}
public T getInfo()
{
return info;
}
public void setInfo(T element)
{
info = element;
}
public LLNode<T> getNext()
{
return next;
}
public void setNext(LLNode<T> newNext)
{
next = newNext;
}
public LLNode<T> getLink()
{
return link;
}
public void setLink(LLNode<T> newLink)
{
link = newLink;
}
}
// SLL.java
// a generic linked list class
public class LL<T>
{
private LLNode<T> head, tail;
public LLNode<T> current = head;
public LL()
{
head = tail = null;
}
public boolean isEmpty()
{
return head == tail;
}
public void setToNull()
{
head = tail = null;
}
public boolean isNull()
{
if(head == tail)
if(head == null || tail == null)
return true;
else
return false;
else
return false;
}
public void addToHead(T element)
{
head = new LLNode<T>(element, head);
if (tail == null)
tail = head;
}
public void addNodeToHead(LLNode<T> newNode)
{
head = newNode;
if (tail == null)
tail = head;
}
public void addToTail(T element)
{
if (!isNull())
{
tail.next= new LLNode<T>(element);
tail = tail.next;
}
else head = tail = new LLNode<T>(element);
}
public void addNodeToTail(LLNode<T> newNode)
{
if (!isNull())
{
tail.next= newNode;
tail = tail.next;
}
else head = tail = newNode;
}
public void addBefore(T element, T X)
{
if (!isEmpty()) // Case 1
{
LLNode<T> temp, n;
temp = head;
while( temp.next != null )
{
if( temp.next.info == X )
{
n = new LLNode<T>(element, temp.next);
temp.next = n;
return;
}
else
temp = temp.next;
}
}
else // Case 2
head = new LLNode<T>(element, head);
}
public void addBefore(T element, LLNode<T> X)
{
if (!isEmpty()) // Case 1
{
LLNode<T> temp, n;
temp = head;
while( temp.next != null )
{
if( temp.next == X )
{
n = new LLNode<T>(element, X);
temp.next = n;
return;
}
else
temp = temp.next;
}
}
else // Case 2
head = new LLNode<T>(element, head);
}
public T deleteFromHead()
{
if (isEmpty())
return null;
T element = head.info;
if (head == tail)
head = tail = null;
else head = head.next;
return element;
}
public T deleteFromTail()
{
if (isEmpty())
return null;
T element = tail.info;
if (head == tail)
head = tail = null;
else
{
LLNode<T> temp;
for (temp = head; temp.next != tail; temp = temp.next);
tail = temp;
tail.next = null;
}
return element;
}
public void delete(T element)
{
if (!isEmpty())
if (head == tail && (element.toString()).equals(head.info.toString()))
head = tail = null;
else if ((element.toString()).equals(head.info.toString()))
head = head.next;
else
{
LLNode<T> pred, temp;
for (pred = head, temp = head.next; temp != null && !((temp.info.toString()).equals(element.toString())); pred = pred.next, temp = temp.next);
if (temp != null)
pred.next = temp.next;
if (temp == tail)
tail = pred;
}
}
public void listAll()
{
if(isNull())
System.out.println("\tEmpty");
else
{
for ( LLNode<T> temp = head; temp!= tail.next; temp = temp.next)
System.out.println(temp.info);
}
}
public LLNode<T> isInList(T element)
{
LLNode<T> temp;
for ( temp = head; temp != null && !((temp.info.toString()).equals(element.toString())); temp = temp.next);
return temp ;
}
public LLNode<T> getHead()
{
return head;
}
public LLNode<T> getTail()
{
return tail;
}
public LLNode<T> getCurrent()
{
return current;
}
public void incrementCurrent()
{
current = current.next;
}
public void followCurrentLink()
{
current = current.link;
}
}
Any specific reason you want to generics for the specific problem domain of the node objects?
If you want to have this effect, another way to do it might be have an interface for node object (maybe call it ILinkNode), have the getInfo and setInfo overridden in two different node classes. Then the nodeLink can point to interface object without special type casting everywhere in the code.
Use in the first list, i.e. the one containing the node you want to link to the node in the other list, Object as the generic type instantiation.
Something like:
LL<Object> ll = new LL<Object>();
If you do this, you have to take care to cast to the specific type, each time you retrieve a node's value from the list.

Categories