I've done some exercises in Java and now I'm stuck at such a problem - my list works incorrectly. I am sure that remove works incorrectly and maybe you can help me (with advice or code) to implement a circular singly linked list in a correct way. I am not sure whether other functions work properly, but I've tried to do my best.
Here is my code:
import java.util.*;
public class Node {
private Object value;
private Object nextValue;
private Node next;
public Node(int data) {
this.value = data;
this.next = null;
}
public Object getValue() {
return this.value;
}
public Node nextItem() {
return this.next;
}
public void setNextItem(Node nextItem) {
this.next = (Node) nextItem;
this.next.setValue(nextItem.getValue());
}
public void setValue(Object arg0) {
this.value = arg0;
}
}
-------------------------------------------------------------------
import java.util.*;
public class CircularList {
private Object[] array;
private int arrSize;
private int index;
private Node head;
private Node tail;
public CircularList() {
head = null;
tail = null;
}
public boolean add(Node item) {
if (item == null) {
throw new NullPointerException("the item is null!!!");
}
if (head == null) {
head = item;
head.setNextItem(head);
arrSize++;
return true;
}
Node cur = head;
while(cur.nextItem() != head) {
if(cur.getValue() == item.getValue()) {
throw new IllegalArgumentException("the element already " +
"exists!");
}
cur = cur.nextItem();
}
head.setNextItem(item);
item.setNextItem(head);
arrSize++;
return true;
}
public Node getFirst() {
return head;
}
public void insertAfter(Node item, Node nextItem) {
if ((item == null) || (nextItem == null)) {
throw new NullPointerException("the item is nul!!!");
} else if (this.contains(nextItem) == true) {
throw new IllegalArgumentException("the item already exists!");
}
Node cur = head;
while(cur.nextItem() != head) {
if(cur.getValue() == item.getValue()) {
nextItem.setNextItem(item.nextItem());
item.setNextItem(nextItem);
} else {
cur = cur.nextItem();
}
}
}
public boolean remove(Node item) {
if(item == head) {
Node cur = head;
for(int i = 0; i < arrSize-1; i++) {
cur = cur.nextItem();
}
head = head.nextItem();
for(int i = 0; i < arrSize; i++) {
cur = cur.nextItem();
}
arrSize--;
return true;
}
Node cur = head;
int counter = 0;
while(cur.nextItem() != head) {
if(cur == item) {
item = null;
cur = cur.nextItem();
while(cur.nextItem() != head) {
cur.setNextItem(cur.nextItem().nextItem());
}
return true;
}
cur = cur.nextItem();
}
return false;
}
public int size() {
return arrSize;
}
public boolean contains(Object o) {
if ((o == null) && (arrSize == 0)) {
return false;
}
Node cur = head;
while(cur.nextItem() != head) {
if(cur.getValue() == o) {
return true;
}
cur = cur.nextItem();
}
return false;
}
}
Many of these algorithms could be simpler.
Example:
public boolean remove(Node item) {
Node current = head;
for(int i = 0; i < size; i++) {
if (current.getNext() == item) {
current.next = current.getNext().getNext();
size --;
return true;
}
current = current.getNext()
}
return false;
}
There are a variety of issues here beyond the list. You seem to be comparing your nodes with ==. This code will output 'no match'.
Node n1 = new Node(5);
Node n2 = new Node(5);
if (n1 == n2)
System.out.println("objects match");
else
System.out.println("no match");
In add(), it looks like you can only ever have two items in the list, so
head.setNextItem(item);
item.setNextItem(head);
should be this:
cur.setNextItem(item);
item.setNextItem(head);
There's a lot going on in your code, here's some advice for some of it:
In your Node class: Java naming conventions: the same way that setters should be prefixed with "set," getters should be prefixed with "get:" nextItem() should really be getNextItem().
Also in your Node class: as far as I know, the "next value" field of a node of a linked list is usually a reference to the next Node in the list, and should therefore be of type Node, not just any Object. It should work the way you have it, but using explicit typing is a lot safer. (Please correct me if using "Object" is indeed a common way to construct the next node of a linked list.)
In the first case of remove(), when removing the head: you're looping through the list to reach the last value, presumably to reset its "next value" to the new head, but you're not actually doing it. You want something like this:
if (item == head) {
head = head.nextItem();
for(int i = 0; i < arrSize-1; i++){
cur = cur.nextItem();
}
}
cur.setNextItem(head);
I'm not sure what you hope to accomplish with the second loop.
In the second case of remove(): I'm not sure what you're trying to do with the second while loop - reset all the links in the whole list? The whole point of a linked list is to make that unnecessary. Deleting a node in a linked list does not actually get rid of the object (so you don't have to set item to null). Rather, you simply "go around" the unwanted object and "ignore" it, effectively removing it from the list, as in:
Original list:
[ Value: A; Next: B ] --> [ Value: B; Next: C ] --> [ Value C; Next: D ] ...
After deleting node B:
[ Value: A; Next: C ] --> [Value C; Next: D ] ...
[ Value: B; Next: C ] still exists in memory, but nothing is pointing to it, so it will be removed in the next garbage collection cycle.
To implelement: As you walk the list, keep a reference to the previous node that you visited. Then, once you find the item you're looking for (using correct comparison, as Thomas noted), you can simply set prev.setNextItem(cur.nextItem()); (caveat: untested code):
Node prev = head;
Node cur;
while ((cur = prev.nextItem()) != head) {
if (cur.equals(item)) {
prev.setNextItem(cur.getNextItem());
return true;
}
}
I hope these tips help you along the correct path.
Related
So, I am trying to write two overloaded remove methods for LinkedList class, where one takes an index of an element that needs to be removed and another one that takes Object that needs to be removed. But when I try to make a LinkedList of integer and call the latter method, method that takes in index is called instead. Is there any way around this??
(PS. I know you can just change the name of the method, but I am given an interface file that requires me to write overloaded methods)
public E remove(int index) {
for (int i = 0; i < index;i++) {
curNode = curNode.next();
}
if (curNode == head && curNode == tail) {
head = null;
tail = null;
}
else {
URNode sucNode = curNode.next();
URNode prevNode = curNode.prev();
if (sucNode != null)
sucNode.setPrev(prevNode);
else {
prevNode.setNext(null);
tail = prevNode;
}
if (prevNode != null)
prevNode.setNext(sucNode);
else {
sucNode.setPrev(null);
head = sucNode;
}
}
numElements--;
return null;
}
public boolean remove(Object o) {
URNode curNode = head;
for (int i = 0; i < numElements;i++) {
if (curNode.element() == o) {
remove(i);
return true;
}
curNode = curNode.next();
}
return false;
}
public static void main(String args[]){
LinkedList intList = new LinkedList();
intList.add(1);
intList.add(2);
intList.add(3);
intList.remove(1); //I want this to remove node with element 1, instead of node with index of 1
//[2][3] should be returned, not [1][3]
}
intList.remove(Integer.valueOf(1)); // just make it Integer but not int
I have an issue creating a sort() method for my linked list.
This is my implementation of Comparable in the Item class.
public class Item implements Comparable <Item>{
public Date delivered;
public final String RFIDNR;
public String name;
}
public int compareTo(Item other)
{
return name.compareTo(other.getItemName());
}
This is my sort method in my linked list class
public void sort()
{
Node node = header.next;
Node tempNode = null;
boolean sorted = false;
while (!sorted)
{
sorted = true;
while (node != null)
{
if (node.itm.compareTo(node.next.itm) > 0) throw new NullPointerException();
{
tempNode = node.next;
node.next = node;
node = tempNode;
sorted = false;
}
node = node.next;
}
}
}
What i try to do here is change position of elements that are not in ascending order and switch them. Going through the whole list until sorted = true.
I am running into NullPointerException errors.
Any help is much appreciated.
Look at the following code.
while (node != null) {
if (node.itm.compareTo(node.next.itm) > 0) throw new
NullPointerException();
{
You don't check to see if node.next is null so you try to compare to something that isn't there when trying to access node.next.itm.
I can't guarantee a specific solution since you didn't post your implementation but you need to also ensure node.next is not null. Try the following:
while (node != null) {
if (mode.next != null && node.itm.compareTo(node.next.itm) > 0) {
//do the swapping
}
Solved it using the following.
for (int i = 0; i < size; i++)
{
Node node = header.next;
Item temp = null;
while (node.next != null) {
if (node.itm.compareTo(node.next.itm) > 0)
{
temp = node.next.itm;
node.next.itm = node.itm;
node.itm = temp;
}
node = node.next;
}
}
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 );
}
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.
I want to remove duplicates from sorted linked list {0 1 2 2 3 3 4 5}.
`
public Node removeDuplicates(Node header)
{
Node tempHeader = null;
if(header != null)
tempHeader = header.next;
else return header;
Node prev = header;
if((tempHeader == null)) return header ;
while(tempHeader != null)
{
if(tempHeader.data != prev.data)
{
prev.setNext(tempHeader);
}
tempHeader = tempHeader.next;
}
prev = header;
printList(prev);
return tempHeader;
}
`
prev.setNext(tempHeader) is not working correctly inside the while loop. Ideally when prev = 2 and tempHeader = 3, prev.next should be node with data = 3.
Printlist function just takes header pointer and prints the list.
Node definition is given below.
public class Node
{
int data;
Node next;
public Node getNext() {
return next;
}
public void setNext(Node next) {
this.next = next;
}
}
The loop is sorted, so you know that duplicates are going to sit next to each other. If you want to edit the list in place then, you've got to have two list pointers (which you do). The one you call tempHeader and prev, and you've got to advance them both in the the list as you go (which I don't see in the code). Otherwise, if you don't advance the prev pointer as you go, then you're always comparing the element under tempHeader to the first item in the list, which is not correct.
An easier way to do this, however, is to build a new list as you go. Simply remember the value of the last item that you appended to the list. Then if the one that you're about to insert is the same then simply don't insert it, and when you're done, just return your new list.
I can give you 2 suggestions for the above suggestion
1) Convert the linked List to Set, that will eliminate the duplicates and
Back from Set to the Linked list
Code to get this done would be
linkedList = new LinkedList<anything>(new HashSet<anything>(origList));
2) You can use LinkedHashSet, if you dont want any duplicates
In this case no return value is needed.
public void removeDuplicates(Node list) {
while (list != null) {
// Walk to next unequal node:
Node current = list.next;
while (current != null && current.data.equals(list.data)) {
current = current.next;
}
// Skip the equal nodes:
list.next = current;
// Take the next unequal node:
list = current;
}
}
public ListNode removeDuplicateElements(ListNode head) {
if (head == null || head.next == null) {
return null;
}
if (head.data.equals(head.next.data)) {
ListNode next_next = head.next.next;
head.next = null;
head.next = next_next;
removeDuplicateElements(head);
} else {
removeDuplicateElements(head.next);
}
return head;
}
By DoublyLinked List and using HashSet,
public static void deleteDups(Node n) {
HashSet<Integer> set = new HashSet<Integer>();
Node previous = null;
while (n != null) {
if (set.contains(n.data)) {
previous.next = n.next;
} else {
set.add(n.data);
previous = n;
}
n = n.next;
}
}
doublylinkedList
class Node{
public Node next;
public Node prev;
public Node last;
public int data;
public Node (int d, Node n, Node p) {
data = d;
setNext(n);
setPrevious(p);
}
public Node() { }
public void setNext(Node n) {
next = n;
if (this == last) {
last = n;
}
if (n != null && n.prev != this) {
n.setPrevious(this);
}
}
public void setPrevious(Node p) {
prev = p;
if (p != null && p.next != this) {
p.setNext(this);
}
}}