I'm really struggling to fix my code for this. I've created a Doubly Linked list that I am trying to traverse in reverse.
Any ideas?
Here's my code: Node.java:
public class Node {
String data;
Node next;
public Node(String data) {
super();
this.data = data;
this.next = null;
}
public String getData() {
return data;
}
public void setData(String data) {
this.data = data;
}
public Node getNext() {
if (this.next != null)
return this.next;
else
return null;
}
public void setNext(Node a) {
this.next = a;
}
#Override
public String toString() { //CHECK
if(data== null){
return "null";
}
else
return data + "-->";
}
}
Here's the second class "DNode.java":
public class DNode extends Node {
Node prev;
public DNode(String data) {
super(data);
this.prev = null;
}
public Node getPrev() {
return prev;
}
public void setPrev(Node prev) {
this.prev = prev;
}
}
Lastly, here is DoublyLinkedList.java: (Overrides "add" and "remove" methods from another class "Linked List")
public class DoublyLinkedList extends LinkedList {
DNode head, tail,current;
public DoublyLinkedList() {
this.head = this.tail = this.current = null;
}
public void add(DNode a) { //CHECK
if (this.head == null) {
this.head = tail = current= a;
this.head.prev = null;
}
else{
//a.setPrev(this.current);
this.current.next= a;
a.setPrev(this.current);
this.current = this.tail = a;
}
}
#Override
public void remove(String removestring) {
this.current = head;
this.current.prev = head;
while (this.current.getData() != removestring) {
if (this.current.next == null) {
System.out.println("not found");
return;
} else {
this.current.prev = this.current;
this.current = (DNode) current.next;
}
}
if (this.current == head) {
head = (DNode) head.next;
} else {
this.current.prev.next = (DNode) this.current.next;
}
}
public void printList() {
DNode temp = this.head;
while (temp != null) {
System.out.println(temp);
temp = (DNode) temp.getNext();
}
}
public void reverseList(){
this.current = this.tail;
this.current.setNext(this.current.getPrev());
this.current.setPrev(null);
this.current = (DNode) this.current.getNext();
while(this.current.getPrev()!= null){
if(this.current.getNext() == null){
this.current.setNext((this.current).getPrev());
this.current.setPrev(null);
this.current = (DNode)this.current.getNext();
}
else{
DNode tempprev = (DNode) this.current.getNext();
this.current.setNext(this.current.getPrev());
this.current.setPrev(tempprev);
this.current = (DNode) this.current.getNext();
}
DNode temp2 = this.tail;
this.head = this.tail;
this.tail = temp2;
}
}
I'm able to print the list going forwards, but going backwards I am running into an infinite loop. Any ideas?
Thanks!
Well, we already have a method to go forwards. Because this is doubly linked, we can just convert this code line by line and instead of moving next (forwards) we move previous (backwards). We also start at the tail instead of the head.
Whereas this was your old method for printing forwards:
public void printList() {
DNode temp = this.head;
while (temp != null) {
System.out.println(temp);
temp = (DNode) temp.getNext();
}
}
This could be your new method for printing backwards:
public void printBackwardsList() {
DNode temp = this.tail;
while(temp != null) {
System.out.println(temp);
temp = (DNode) temp.getPrev();
}
}
Notice how they are almost exactly the same, except we swapped out tail for head and getNext for getPrev.
Your class model seems overly complex. You don't need a DNode class at all to do this. Your method to print the list in reverse should be as simple as the method to print the list normally
public void printListReverse() {
Node temp = this.tail;
while (temp != null) {
System.out.println(temp);
temp = temp.getPrevious();
}
}
assuming you build and maintain the list properly.
while(this.current.getPrev()!= null)
replace with
while(this.current.getPrev()!= head)
Related
I have been debugging this for hours and I cannot see any reason why my search method cannot find anything. and my toString only ever returns the first node, then again, nothing. can someone help me?
While debugging, I can confirm that the order of the list is correct, I can switch around the addLast and addFirst and will always return what should be the first element, but otherwise, I do not know. the first is always sored in head.info and during debugging I see that but then the prev and next are still null.
thanks in advance!
public class DoubleLinkedList {
private DoubleNode head;
public DoubleLinkedList() {
head = null;
}
public class DoubleNode {
int info;
DoubleNode prev;
DoubleNode next;
public DoubleNode(int key) {
info = key;
prev = next = null;
}
}
public DoubleNode search(int key) {
DoubleNode current = this.head;
while (current != null && current.info != key) {
current = current.next;
}
return current;
}
public void addFirst(int key) {
this.head = new DoubleNode(key);
}
public void addLast(int key) {
DoubleNode node = new DoubleNode(key);
DoubleNode current;
if (head == null) {
this.head = node;
} else {
current = this.head;
while (current.next != null) {
current = current.next;
current.next = node;
node.prev = current;
}
}
}
public int delete(int key) {
DoubleNode current, sent;
current = search( key );
if (current != null) {
sent = delete( current );
return sent.info;
} else {
return -1;
}
}
private DoubleNode delete(DoubleNode node) {
if (node.prev != null) {
(node.prev).next = node.next;
} else {
this.head = node.next;
}
if (node.next != null) {
(node.next).prev = node.prev;
}
return node;
}
public String toString() {
String string = "";
while (head != null) {
string += head.info + " ";
head = head.next;
}
return string;
}
public static void main(String[] args) {
DoubleLinkedList test = new DoubleLinkedList();
test.addLast( 3 );
test.addLast( 5 );
test.addFirst( 7 );
System.out.println(test);
System.out.println( "Search: " + test.search( 1 ) );
}
}
The results come out as:
7,
Search: null
Your addFirst method isn't currently setting the new head's next property. It needs to be something more like this:
public void addFirst(int key) {
DoubleNode node = new DoubleNode(key);
node.next = this.head;
this.head = node;
}
Take a look at this example:
public class Test {
public static void main(String[] args) {
List list = new List();
list.addNode("1");
list.addNode("2");
list.addNode("3");
System.out.println(list);// not implemented
}
}
class List {
Node head;
Node tail;
class Node {
Node next;
Node previous;
String info;
public Node(String info) {
this.info = info;
}
}
void addNode(String info) {
Node node = new Node(info);
if (head == null) {
head = tail = node;
} else if(tail == head){
Node next = new Node(info);
tail.next = next;
head = next;
head.previous = tail;
} else{
Node next = new Node(info);
Node current = head;
head.next =next;
head = next;
head.previous = current;
}
}
}
I'm trying to write a method called copyAlternate which copy alternate elements from a single linked list and put them in another Single linked list sent as a parameter in the method
for example: if the first Single Linked List is( 4,6,10,12,2)
the method should generate a single linked list with (4,10,2)
here is my code:
public boolean copyAlternate(SingleLinkedList<E> list1)
{
if(head==null)
return false;
Node <E> temp = head;
ArrayList <E> a1 = new ArrayList<E>();
while(temp!=null) {
a1.add(temp.data);
temp=temp.next;
}
Node<E> tmp1=list1.head;
for(int i=0;i<a1.size();i=i+2){
if(list1.head==null) {
list1.head =new Node(a1.get(i));
tmp1=head;
size++;
}
else
{
tmp1.next=new Node(a1.get(i));
size++;
tmp1=tmp1.next;
}
}
return true;
}
I got only 4 from method not (4,10,2)
so what is the problem with my code?
Here is a full example if you need it, try not to copy it entirely but study it and understand what it's doing:
public class Main {
public static void main(String[] args) {
SingleLinkedList<Integer> list = new SingleLinkedList<>();
// (4, 6, 10, 12, 2)
list.add(4).add(6).add(10).add(12).add(2);
SingleLinkedList<Integer> newList = copyAlternate(list);
System.out.println(newList);
// prints: (14, 10, 2)
}
public static class Node<T> {
public Node<T> next;
public T data;
public Node() {}
public Node(T data) {this.data = data;}
}
public static class SingleLinkedList<T> {
private Node<T> head;
private Node<T> tail;
public SingleLinkedList<T> add(T data) {
if (tail != null) {
tail.next = new Node<>(data);
tail = tail.next;
} else {
head = new Node<>(data);
tail = head;
}
return this;
}
#Override public String toString() {
StringBuilder sb = new StringBuilder();
if (head != null) {
sb.append(head.data);
Node<T> curr = head.next;
while (curr != null) {
sb.append(", ").append(curr.data);
curr = curr.next;
}
}
return sb.toString();
}
}
/**
* Copies only the even index nodes (0, 2, 4..) into a new list and returns that list.
* Doesn't create a deep copy of data
*/
public static <T> SingleLinkedList<T> copyAlternate(SingleLinkedList<T> list) {
Objects.requireNonNull(list, "list");
SingleLinkedList<T> newList = new SingleLinkedList<>();
Node<T> other = list.head;
if (other != null) {
// copy other data to head of new list and remember that as the current node
Node<T> curr = newList.head = new Node<>(other.data);
// get the next next other node
other = other.next;
if (other != null) {
other = other.next;
}
while (other != null) {
// copy the data into the next node then remember that as the current node
curr = curr.next = new Node<>(other.data);
// get the next next other node
other = other.next;
if (other != null) {
other = other.next;
}
}
}
return newList;
}
}
Another way you can achieve it. Hope it will help.
// define the structure of a single node
class ListNode<T>
{
public T data;
public ListNode<T> next;
public ListNode(T data)
{
this.data = data;
this.next = null;
}
}
public class SingleLinkedListGenerics<T>
{
private ListNode<T> head = null;
private ListNode<T> tail = null;
// used to insert a node at the end of linked list
public void insertLast(T data)
{
ListNode<T> newNode = new ListNode<>(data);
if (head == null)
{
head = tail = newNode;
}
else
{
tail.next = newNode;
tail = newNode;
}
}
// For printing Linked List
public void displayList()
{
System.out.println("\nPrinting LinkedList (head --> last) ");
ListNode<T> current = head;
while (current != null)
{
System.out.println(current.data + ", ");
current = current.next;
}
}
public static <T> SingleLinkedListGenerics<T> copyAlternate(SingleLinkedListGenerics<T> list)
{
if (list.head == null)
return null;
SingleLinkedListGenerics<T> newList = new SingleLinkedListGenerics<>();
ListNode<T> tmp = list.head;
ListNode<T> newNode = new ListNode<>(tmp.data); // getting the first node
newList.head = newNode;
newList.tail = newNode;
tmp = tmp.next;
while (tmp != null && tmp.next != null) //
{
tmp = tmp.next; // skipping one node
newList.insertLast(tmp.data);
tmp = tmp.next;
}
return newList;
}
public static void main(String args[])
{
SingleLinkedListGenerics<Integer> myLinkedlist = new SingleLinkedListGenerics<>();
myLinkedlist.insertLast(4);
myLinkedlist.insertLast(6);
myLinkedlist.insertLast(10);
myLinkedlist.insertLast(12);
myLinkedlist.insertLast(2);
myLinkedlist.displayList();
SingleLinkedListGenerics<Integer> myLinkedlist1 = copyAlternate(myLinkedlist);
myLinkedlist1.displayList();
}
}
oldVal() method this will get to the correct if, else-if, or else statement that is needed to remove the node but then I always get a null point exception I have compared this to similar codes and cannot seem to find what is wrong with it.
please help:
enter code here// ***************************************************************
// DoubleLinked.java
//
// A class using a doubly linked list to represent a list of integers.
//
// ***************************************************************
public class DoubleLinked
{
private int size=0;
private IntNode list;
// ----------------------------------------------
// Constructor -- initializes list
// ----------------------------------------------
public DoubleLinked()
{
list = null;
}
// ----------------------------------------------
// Prints the list elements
// ----------------------------------------------
public void print()
{
for (IntNode temp = list; temp != null; temp = temp.next)
System.out.println(temp.val);
}
// ----------------------------------------------
// Adds new element to front of list
// ----------------------------------------------
public void addToFront(int val)
{
IntNode newNode = new IntNode(val);
newNode.next = list;
if (list != null)
list.prev = newNode;
list = newNode;
size++;
}
public void addToEnd(int val)
{
IntNode newNode = new IntNode(val);
IntNode current;
if (list == null)
{list= newNode;}
else
{
current=list;
while(current.next != null)
current = current.next;
current.next = newNode;
}
size++;
}
public void removeFirst()
{
IntNode test = list;
if (test == null){System.out.println("your list is emty"); size++;}
else if (list != null) { // list might be empty
IntNode temp = list.prev;
if(list.next==null && list.prev==null) {
list=null;
}
else {
list.next.prev = null;
list = list.next;
}
}
size--;
}
public void removeLast()
{
IntNode test = list;
if (test == null){System.out.println("your list is emty"); size++;}
else if(list.next==null && list.prev==null)
{
list=null;
}
else if (list != null){
IntNode current=list;
while(current.next.next != null)
current = current.next;
current.next=null;
}
size--;
}
public void oldVal(int val)
{
IntNode temp=list;
for (int i = 0; i < this.size; i++)
{
if (temp.val != val)
temp= temp.next;
else{
if (temp.prev == null)
{
list=list.next;
}
if (temp.next == null)
{
temp.prev.next=null;
}
else
{
temp.prev.next=temp.next;
temp.next.prev=temp.prev;
}
size--;
break;
}
}}
//***************************************************************
// An inner class that represents a list element.
//***************************************************************
class IntNode
{
public int val;
public IntNode next;
public IntNode prev;
public IntNode(int val)
{
this.val = val;
this.next = null;
this.prev = null;
}
}}
I am trying to implement Knuth's Dancing Links algorithm in Java.
According to Knuth, if x is a node, I can totally unlink a node by the following operations in C:
L[R[x]]<-L[x]
R[L[x]]<-R[x]
And revert the unlinking by:
L[R[x]]<-x
R[L[x]]<-x
What am I doing wrongly in my main method?
How do you implement the unlinking and revert in Java?
Here's my main method:
///////////////
DoublyLinkedList newList = new DoublyLinkedList();
for (int i = 0; i < 81; i++) {
HashSet<Integer> set = new HashSet<Integer>();
set.add(i);
newList.addFirst(set);
}
newList.displayList();
// start at 69
newList.getAt(12).displayNode();
//HOW TO IMPLEMENT UNLINK?
//newList.getAt(12).previous() = newList.getAt(12).next().previous().previous();
//newList.getAt(12).next() = newList.getAt(12).previous().next().next();
newList.displayList();
//HOW TO IMPLEMENT REVERT UNLINK?
//newList.getAt(12) = newList.getAt(12).next().previous();
//newList.getAt(12) = newList.getAt(12).previous().next();
System.out.println();
///////////////
Here's the DoublyLinkedList class:
public class DoublyLinkedList<T> {
public Node<T> first = null;
public Node<T> last = null;
static class Node<T> {
private T data;
private Node<T> next;
private Node<T> prev;
public Node(T data) {
this.data = data;
}
public Node<T> get() {
return this;
}
public Node<T> set(Node<T> node) {
return node;
}
public Node<T> next() {
return next;
}
public Node<T> previous() {
return prev;
}
public void displayNode() {
System.out.print(data + " ");
}
#Override
public String toString() {
return data.toString();
}
}
public void addFirst(T data) {
Node<T> newNode = new Node<T>(data);
if (isEmpty()) {
newNode.next = null;
newNode.prev = null;
first = newNode;
last = newNode;
} else {
first.prev = newNode;
newNode.next = first;
newNode.prev = null;
first = newNode;
}
}
public Node<T> getAt(int index) {
Node<T> current = first;
int i = 1;
while (i < index) {
current = current.next;
i++;
}
return current;
}
public boolean isEmpty() {
return (first == null);
}
public void displayList() {
Node<T> current = first;
while (current != null) {
current.displayNode();
current = current.next;
}
System.out.println();
}
public void removeFirst() {
if (!isEmpty()) {
Node<T> temp = first;
if (first.next == null) {
first = null;
last = null;
} else {
first = first.next;
first.prev = null;
}
System.out.println(temp.toString() + " is popped from the list");
}
}
public void removeLast() {
Node<T> temp = last;
if (!isEmpty()) {
if (first.next == null) {
first = null;
last = null;
} else {
last = last.prev;
last.next = null;
}
}
System.out.println(temp.toString() + " is popped from the list");
}
}
I am not familiar with Knuth's Dancing Links algorithm, but found this article which made it quiet clear. In particular I found this very helpful:
Knuth takes advantage of a basic principle of doubly-linked lists.
When removing an object from a list, only two operations are needed:
x.getRight().setLeft( x.getLeft() )
x.getLeft().setRight(> x.getRight() )
However, when putting the object back in the list, all
is needed is to do the reverse of the operation.
x.getRight().setLeft( x )
x.getLeft().setRight( x )
All that is
needed to put the object back is the object itself, because the object
still points to elements within the list. Unless x’s pointers are
changed, this operation is very simple.
To implement it I added setters for linking / unlinking. See comments:
import java.util.HashSet;
public class DoublyLinkedList<T> {
public Node<T> first = null;
public Node<T> last = null;
static class Node<T> {
private T data;
private Node<T> next;
private Node<T> prev;
public Node(T data) {
this.data = data;
}
public Node<T> get() {
return this;
}
public Node<T> set(Node<T> node) {
return node;
}
public Node<T> next() {
return next;
}
//add a setter
public void setNext(Node<T> node) {
next = node;
}
public Node<T> previous() {
return prev;
}
//add a setter
public void setPrevious(Node<T> node) {
prev = node;
}
public void displayNode() {
System.out.print(data + " ");
}
#Override
public String toString() {
return data.toString();
}
}
public void addFirst(T data) {
Node<T> newNode = new Node<T>(data);
if (isEmpty()) {
newNode.next = null;
newNode.prev = null;
first = newNode;
last = newNode;
} else {
first.prev = newNode;
newNode.next = first;
newNode.prev = null;
first = newNode;
}
}
public Node<T> getAt(int index) {
Node<T> current = first;
int i = 1;
while (i < index) {
current = current.next;
i++;
}
return current;
}
public boolean isEmpty() {
return (first == null);
}
public void displayList() {
Node<T> current = first;
while (current != null) {
current.displayNode();
current = current.next;
}
System.out.println();
}
public void removeFirst() {
if (!isEmpty()) {
Node<T> temp = first;
if (first.next == null) {
first = null;
last = null;
} else {
first = first.next;
first.prev = null;
}
System.out.println(temp.toString() + " is popped from the list");
}
}
public void removeLast() {
Node<T> temp = last;
if (!isEmpty()) {
if (first.next == null) {
first = null;
last = null;
} else {
last = last.prev;
last.next = null;
}
}
System.out.println(temp.toString() + " is popped from the list");
}
public static void main(String[] args) {
///////////////
DoublyLinkedList newList = new DoublyLinkedList();
for (int i = 0; i < 81; i++) {
HashSet<Integer> set = new HashSet<Integer>();
set.add(i);
newList.addFirst(set);
}
newList.displayList();
// start at 69
Node node = newList.getAt(12);
node.displayNode(); System.out.println();
//HOW TO IMPLEMENT UNLINK?
node.previous().setNext(node.next);
node.next().setPrevious(node.previous());
//The 2 statements above are equivalent to
//Node p = node.previous();
//Node n = node.next();
//p.setNext(n);
//n.setPrevious(p);
newList.displayList();
//HOW TO IMPLEMENT REVERT UNLINK?
node.previous().setNext(node);
node.next().setPrevious(node);
newList.displayList(); System.out.println();
///////////////
}
}
I'm wondering if this has something to do with how I specified my Singly Linked List class, but the problem is eluding me.
Here is the Singly Linked List class:
class SLList {
private static Node head;
private static long size;
public SLList() {
head = new Node(null, null);
setSize(0);
}
static class Node {
private Object data;
private Node next;
public Node(Object newData, Node n) {
data = newData;
next = n;
}
public Node getNext() {
return next;
}
public void setElement(Object element) {
data = element;
}
public void setNext(Node newNext) {
next = newNext;
}
public String toString() {
String result = data + " ";
return result;
}
public Object getObject() {
return data;
}
}
public Node getHead() {
return head;
}
public long getSize() {
return size;
}
public void setSize(long size) {
this.size = size;
}
public void addLast(Object object) {
Node temp = head;
while(temp.next != null) {
temp = temp.next;
}
temp.next = new Node(object, null);
size++;
}
public void remove(Object object) {
Node pre = head;
Node temp = head.next;
while(temp.next != null) {
pre = temp;
temp = temp.next;
if(temp.data.equals(object)) {
pre = temp.next;
temp = temp.next.next;
size--;
}
}
}
public void printElements() {
Node temp = head;
if(temp.next == null) {
System.out.println("List is empty.");
}
else {
while(temp.next != null) {
temp = temp.next;
System.out.println(temp.data);
}
}
}
}
This is the Set class with a method to add new values to the lists, barring duplicates already in the list:
public class Set {
SLinkedList aList;
SLinkedList bList;
SLinkedList cList;
SLinkedList dList;
public Set() {
aList = new SLinkedList();
bList = new SLinkedList();
cList = new SLinkedList();
dList = new SLinkedList();
}
public SLinkedList getList(char x) {
if(x == 'a') {
return aList;
}
else if(x == 'b') {
return bList;
}
else if(x == 'c') {
return cList;
}
else {
return dList;
}
}
public boolean addElement(SLinkedList list, Object newData) {
SLinkedList.Node newNode = new SLinkedList.Node(newData, null);
SLinkedList.Node traverseNode = list.getHead();
while(traverseNode.getNext() != null) {
traverseNode = traverseNode.getNext();
if(traverseNode.getObject().equals(newNode.getObject())) {
System.out.println("This data is already in the list.");
return false;
}
}
list.addLast(newData);
System.out.println("Node added!");
return true;
}
public void fillList() {
aList.addLast("dog");
aList.addLast(4);
bList.addLast("test");
System.out.println("aList: ");
aList.printElements();
System.out.println("bList: ");
bList.printElements();
}
}
This is the output when I try to use fillList() to add values to the first Singly Linked List, aList
aList:
dog 4 test
bList:
dog 4 test
As you can see, adding values to aList adds the same values to bList. Any help would be greatly appreciated!
This:
private static Node head;
means you have one head for all your instances of SLLIst. So all SLList instance share the same head.
This should be a member of your class, and as such you'll have an instance of head per instance of SLLIst.
e.g.
private Node head;
The same applies to your size field. I don't think you'll need any static members.