I have a doubly linked list in my case. And I want to find the max and min element. So I want to use the Collections to find it. Here is my code below for Node first:
public class Node<T> {
Node<T> prev;
Node<T> next;
T data;
public Node(T _data)
{
data = _data;
prev = null;
next = null;
}
public Node(T _data, Node<T> _prev, Node<T> _next)
{
data = _data;
prev = _prev;
next = _next;
}
T getData()
{
return data;
}
public void setNext(Node<T> _next)
{
next = _next;
}
public void setPrev(Node<T> _prev)
{
prev = _prev;
}
public Node<T> getNext()
{
return next;
}
public Node<T> getPrev()
{
return prev;
}
}
And here is my Doubly Linked List class:
public class DoublyLinkedList<T> {
private Node<T> head;
private Node<T> tail;
int listCount = 0;
public void traverseF()
{
Node<T> temp = head;
while(temp != null)
{
System.out.print(temp.getData() + " ");
temp = temp.getNext();
}
}
public void traverseB()
{
Node<T> temp = tail;
while(temp != null)
{
System.out.print(temp.getData() + " ");
temp = temp.getPrev();
}
}
public void insertFirst(T data)
{
Node<T> temp = new Node<T>(data);
if(head == null)
{
head = temp;
tail = temp;
temp.setNext(null);
temp.setPrev(null);
}
else
{
temp.setNext(head);
head.setPrev(temp);
head = temp;
}
}
}
So, my main code is:
import java.util.Collections;
public class glavna {
public static void main(String[] args) {
DoublyLinkedList<Integer> DLL = new DoublyLinkedList<Integer>();
DLL.insertFirst(32);
DLL.insertFirst(22);
DLL.insertFirst(55);
DLL.insertFirst(10);
DLL.traverseF();
Integer max = Collections.max(DLL);
}
}
How exactly do I call the Collections.max or Collections.min method? Isn't the list only necessary to find the max/min elements?
public T getMin()
{
Node<T> temp = head;
T min = head.getData();
while(temp.getNext() != null)
{
if(temp.getData() < min) // error
{
//min = temp.getData();
}
}
}
To implement getMin with generics you need to be able to compare them. You can, for instance, provide a custom Comparator to your method:
public T getMin(Comparator<? super T> comparator) {
Node<T> temp = head.getNext();
T min = head.getData();
while(temp != null) {
T candidateValue = temp.getData();
if (comparator.compare(candidateValue, min) < 0) { // equivalent to candidate < min
min = candidateValue;
}
temp = temp.getNext();
}
return min;
}
Then, calling your method for Integer :
getMin(new Comparator<Integer>() {
#Override
public int compare(Integer arg0, Integer arg1) {
return arg0.compareTo(arg1);
}
});
Another approach is to make your list only keep Comparable items :
public class DoublyLinkedList<T extends Comparable<? super T>> {
and then have your getMin() method use compareTo method :
public T getMin() {
Node<T> temp = head.getNext();
T min = head.getData();
while(temp != null) {
T candidateValue = temp.getData();
if (candidateValue.compareTo(min) < 0) { // equivalent to candidate < min
min = candidateValue;
}
temp = temp.getNext();
}
return min;
}
Second approach is less verbose, as Integer is Comparable (i.e. implements Comparable for you already), so you won't need to change any other code.
You list is not a Collection, so you cannot use Collections with it.
The Collections.max method expects an argument which implements Collection. The easiest way would probably be to extend AbstractCollection and add these methods:
#Override
public Iterator<T> iterator() {
return new Iterator<T>() {
private Node<T> node = head;
#Override
public boolean hasNext() {
return node != null;
}
#Override
public T next() {
T next = node.data;
node = node.getNext();
return next;
}
};
}
#Override
public int size() {
int size = 0;
Node<T> node = head;
while (node != null) {
size++;
node = node.getNext();
}
return size;
}
Related
I am new to Java and I am trying to implement the Comparable interface for a linked list. I have a standard linked list.
public class LinkedList<E extends Comparable<E>>{
private static class Node<T> {
private T value;
private Node<T> next;
private Node(T value, Node<T> next) {
this.value = value;
this.next = next;
}
}
private Node<E> head;
private int size=0;
public boolean isEmpty() {
return head == null;
//or
//return size == 0;
}
public void addFirst(E elem) {
if (elem == null) {
throw new NullPointerException();
}
head = new Node<E>(elem, head);
size++;
}
public void addLast(E elem) {
if (elem == null) {
throw new NullPointerException();
}
if (head == null) {
head = new Node<E>(elem, null);
} else {
Node<E> current = head;
while (current.next != null) {
current = current.next;
}
current.next = new Node<E>(elem, null);
}
size++;
}
//adding at a specific index
public void add(E elem, int index) {
if (elem == null) {
throw new NullPointerException();
}
if (index < 0 || index > size) {
throw new IndexOutOfBoundsException(Integer.toString(index));
}
if (index == 0) {
head = new Node<E>(elem, head);
} else {
Node<E> p = head;
for (int i=0; i<(index-1); i++) {
p = p.next;
}
p.next = new Node<E>(elem, p.next);
}
size++;
}
public E removeFirst() {
if (head == null) {
throw new NullPointerException();
}
E saved = head.value;
head = head.next;
size--;
return saved;
}
public E removeLast() {
if (head == null) {
throw new NullPointerException();
}
E saved;
if (head.next == null) {
saved = head.value;
head = null;
} else {
Node<E> p = head;
while (p.next.next != null) {
p = p.next;
}
saved = p.next.value;
p.next = null;
}
size--;
return saved;
}
public int size() {
return size;
}
public String toString() {
String str = "[";
Node<E> p = head;
while (p!=null) {
if (p != head) {
str += ", ";
}
str += p.value;
p = p.next;
}
str += "]";
return str;
}
public int compareTo(Node<E> other){
return Integer.compare(this.value,other.value);
}
}
Currently I am assuming the contents of the list are of type int. When I try to compile, I get the error as
LinkedList.java:144: error: cannot find symbol
return Integer.compare(this.value,other.value);
^
Based on what I can understand, it's because I am trying to compare Objects of type Node and not linkedList, therefore "this" is referring linkedList. I am not sure how I can change my code to be able to compare two nodes. Any help or suggestions is appreciated.
Edit:
Is my general methodology incorrect or just my implementation? Is there another way I should implement compareTo? e.g. Add it as a method in the class node?
value is a field in Node and this in your current compareTo method refers to a the linked list object.
You could make the Node class to implement Comparable as below:
public static class Node<T> implements Comparable<Node<T>> {
// rest of the code
#Override
public int compareTo(Node<T> other) {
// this.value is accessible.
}
}
Now in your LinkedList class write another compareTo method (or any other name as this method is not related to Comparable.compareTo) which would invoke the above.
public int compareTo(Node<E> other) {
return this.head.compareTo(other);
}
NOTE: In your current code, you haven't actually "implemented" the Comparable interface. You have only mentioned that the generic type E is a Comparable type.
You didn't understand this<E extends Comparable<E>>,There are two solutions
1.
public class LinkedList<E extends Comparable<E>>{
//public class LinkedList<E extends Integer>{
private static class Node<T> {
private T value;
private Node<T> next;
private Node(T value, Node<T> next) {
this.value = value;
this.next = next;
}
}
private Node<E> head;
private int size=0;
public int compareTo(Node<E> other){
return this.head.value.compareTo(other.value);
//return Integer.compare(this.head.value, other.value);
}
}
//public class LinkedList<E extends Comparable<E>>{
public class LinkedList<E extends Integer>{
private static class Node<T> {
private T value;
private Node<T> next;
private Node(T value, Node<T> next) {
this.value = value;
this.next = next;
}
}
private Node<E> head;
private int size=0;
public int compareTo(Node<E> other){
//return this.head.value.compareTo(other.value);
return Integer.compare(this.head.value, other.value);
}
}
I've created a sorted linked list class, and the only part I'm struggling with is implementing the toArray() method properly.
public class SortedLinkedList<T extends Comparable<T>> implements ListInterface<T>
{
// container class
private class LinkedNode<T>
{
public T data;
public LinkedNode<T> next;
public LinkedNode(T data, LinkedNode<T> next)
{
this.data = data;
this.next = next;
}
}
// private variables
private LinkedNode<T> head, tail;
private int size;
private String name;
// constructor
public SortedLinkedList(String name)
{
head = null;
tail = null;
size = 0;
this.name = name;
}
// core functions
public void Add(T data)
{
size++;
// creation of new node to be added
LinkedNode<T> newNode = new LinkedNode<T>(data, null);
// check for empty list; adds node at head if so
if (head == null)
{
head = newNode;
return;
}
if (head.data.compareTo(data) < 0)
{
head = newNode;
return;
}
// insertion in middle
LinkedNode<T> current = head;
LinkedNode<T> prev = null;
while (current != null)
{
if (current.data.compareTo(data) > 0)
{
prev.next = newNode;
newNode.next = current;
return;
}
prev = current;
current = current.next;
}
// insertion at end
prev.next = newNode;
return;
}
public void Remove(T data)
{
if (head == null)
{
return;
}
LinkedNode<T> current = head.next;
while (current != null && current.next != null)
{
if (current.data.compareTo(current.next.data) == 0)
{
current.next = current.next.next;
} else {
current = current.next;
}
}
size--;
}
public int size()
{
return size;
}
#SuppressWarnings("unchecked")
public T[] toArray()
{
T[] result = (T[])(new Comparable[size()]);
int counter = 0;
for ( T item : )
{
result[counter++] = item;
}
return result;
}
The problem I'm having is what I should include after "T item : " in my for/each line. I had no problem with implementing a similar toArray() method in a set class recently, as that was "for each item in the set", but for some reason I'm blanking on what to place there for the linked list.
Try this.
#SuppressWarnings("unchecked")
public T[] toArray()
{
T[] result = (T[])(new Comparable[size()]);
int counter = 0;
for ( LinkedNode<T> cursor = head; cursor != null; cursor = cursor.next )
{
result[counter++] = cursor.data;
}
return result;
}
Actually, the answer to your question is this:
#SuppressWarnings("unchecked")
public T[] toArray() {
T[] result = (T[])(new Comparable[size()]);
int counter = 0;
for (T item : this) {
result[counter++] = item;
}
return result;
}
This is correct, but to do this you have to implement Iterable<T> interface:
public class SortedLinkedList<T extends Comparable<T>> implements ListInterface<T>, Iterable<T> {
#Override
public Iterator<T> iterator() {
return null;
}
// ...
}
Don't use for loop with linked-lists. Try something like below:
LinkedNode cursor = head;
int index = 0;
while (cursor != null ){
result[index] = cursor.data;
cursor = cursor.next;
index++;
}
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 am learning algorithms myself, and I tried to implement LinkedList in Java with generic types from scratch. I had a version with Object which works well, but when I updated it with generic types, it gives warnings. Can anybody help where does the "unchecked or unsafe operations" come from?
class LinkedListGeneric <T> {
private Node<T> head;
private int size;
public LinkedListGeneric() {
head = null;
size = 0;
}
public int size() {
return size;
}
public void add (T data) {
if (head == null) {
head = new Node<T> (data);
size = 1;
}
else {
Node<T> temp = new Node<T> (data);
search(size).setNext(temp);
size++;
}
}
public void add (T data, int position) {
if (position > size + 1 || position <= 0) {
System.out.println ("error.");
return;
}
Node<T> temp = new Node<T> (data);
if (position == 1) {
temp.setNext(head);
head = temp;
return;
}
Node<T> prev = search(position - 1);
temp.setNext(prev.getNext());
prev.setNext(temp);
}
public void delete (int position) {
if (position > size || position <= 0) {
System.out.println ("error.");
return;
}
if (position == 1) {
size--;
head = head.getNext();
return;
}
Node<T> prev = search(position - 1);
prev.setNext(prev.getNext().getNext());
size--;
}
public T getValue (int position) {
if (position > size || position <= 0) {
System.out.println ("error.");
return null;
}
Node<T> temp = search(position);
return temp.getData();
//return search(position).getData();
}
public int searchData(T data) {
Node<T> temp = head;
int position = 1;
boolean flag = false;
while (temp != null) {
if (temp.getData() == data) {
flag = true;
break;
}
else {
temp = temp.getNext();
position++;
}
}
if (flag) return position;
else return -1;
}
public void print() {
Node<T> temp = head;
int position = 1;
while (temp != null) {
System.out.println("Node " + position + ": " + temp.getData());
temp = temp.getNext();
position++;
}
}
private Node<T> search (int position) {
Node temp = head;
while (position > 0) {
temp = temp.getNext();
}
return temp;
}
private class Node<T> {
private T data;
private Node<T> next;
public Node() {
this.data = null;
next = null;
}
public Node(T data) {
this.data = data;
next = null;
}
public T getData() {
return data;
}
public Node getNext() {
return next;
}
public void setNext(Node next) {
this.next = next;
}
}
}
The problem I see is your Node.getNext call is returning a Node instead of a Node<T>. This is equivalent to the method returning Node<Object> instead of the generic type.
So, you should change:
public Node getNext() {
return next;
}
to
public Node<T> getNext() {
return next;
}
Although sbochin's answer will fix some of your warnings, doing the following will fix all of them:
Replace all instances of T within your Node class, including the one in the class declaration, with T2.
Change the return of getNext to Node<T2>
Change the argument type in setNext to Node<T2>.
Change the type of temp in search to Node<T>.
You might also want to add an #SuppressWarnings("unused") to public Node() since that also generates a compiler warning.
You might also want to make your Node class a static class as none of it's methods depend on the LinkedListGeneric<T> object it is in.
Completely alternatively, you could just get rid of the type parameter from Node, which gets rid of all your warnings except the unused warning. You'd have to keep your class nonstatic however.
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.