Need help on Linked list delete method - java

Right now my Linked list is in a queue form. My LList class holds two fields called head and tail which are the head and tail of the list. Head and tail are LNode objects, a LNode is an element of the list that holds a int value, and it's previous LNode and next LNode.
Here's my LNode class:
class LNode{
private int val;
private LNode next;//not recursive
private LNode prev;
public LNode(int v, LNode n, LNode p){
next = n;
prev = p;
val = v;
}
public int getVal(){
return val;
}
public LNode getNext(){
return next;
}
public LNode getPrev(){
return prev;
}
public void setVal(int v){
val = v;
}
public void setNext(LNode n){
next = n;
}
public void setPrev(LNode p){
prev = p;
}
}
I am trying to make a delete method in my LList class so that it takes a value and delete the LNode that has that value. My problem is, I don't know how I would deal with the case where the LNode I'm trying to delete is the head or the tail.
public void delete(int v){
if(head.getVal()==v){//delete head
head = head.getNext();
head.setPrev(null);
}
else if(tail.getVal()==v){//delete tail
System.out.println("boiboi");
tail = tail.getPrev();
tail.setNext(null);
}
else{//delete other element
LNode tmp = head;
while(tmp.getVal()!=v){
tmp = tmp.getNext();
}
tmp.getPrev().setNext(tmp.getNext());
tmp.getNext().setPrev(tmp.getPrev());
}
}
What i have tried is to set the new head's previous LNode to be null, but Java doesn't allow that. So what should I do?
Thank you.

Your code looks okay to me, except in the case that the value you're removing is the sole value - in which case you want to end up with both the head and the tail as null. I suspect all you need to do is change the head case:
if (head.getVal() == v) {
head = head.getNext();
if (head != null) {
head.setPrev(null);
} else {
// If head.getNext() returns null, then tail must have been equal to head.
tail = null;
}
}
You should also check for the empty list situation first:
if (head == null) {
return;
}
And in your general case, handle the situation where the value isn't found:
while (tmp != null && tmp.getVal() != v) {
tmp = tmp.getNext();
}
if (tmp == null) {
return;
}

Related

Reverse a linked list recursively in java using a temp variable

I implemented a solution to reverse a linked list in java that I found online. But it is not working in my code for some reason.
When I print the list it only prints the first node. I know the print method works because it prints the whole thing when I don't try to reverse.
Where did I go wrong in this code?
public class LinkedLists {
public static void main(String[] args) {
LinkedList list = new LinkedList();
list.addLast(10);
list.addLast(20);
list.addLast(30);
list.reverseList();
list.print();
}
public static class LinkedList{
private class Node{
private int value;
private Node next;
}
public Node first;
public Node last;
public void addLast(int item){
Node node = new Node();
node.value = item;
if(first == null) {
first = node;
last = node;
} else {
last.next = node;
last = node;
}
}
private Node reverse(Node head, Node newHead) {
//base case: when first = last you return
if(head == null) {
return newHead;
}
Node temp = head.next;
head.next = newHead; //this will initially be null
newHead = head;
head = temp;
return reverse(head, newHead);
}
public Node reverseList() {
return reverse(first, null);
}
public void print(){
Node current = first;
while (current != null){
System.out.print(current.value + " ");
current = current.next;
}
}
} //class ends
}
Although reverse returns the correct reference for the new head, the initial call of reverseList -- in the main program -- ignores this returned reference.
Your reverseList method should better not return anything, but instead update the first and last members:
public void reverseList() {
last = first;
first = reverse(first, null);
}

Deleting a node that is in the middle of a linked list

I am trying to delete a node in the middle of two other nodes in a singly linked list.
public void deleteAfter(Node del){
del.next=del.next.next;
}
where it deletes the the node that is after the specified node,del.
I get a null pointer exception .I think the problem is after deletion the link with other nodes is broken.How can I mend it .Here's my full code :
public class Node{
public Object item;
public Node next;
public Node(){
item=null;
next=null;
}
public Node(Object x){
item=x;
next=null;
}
public void insertAfter(Node after,Object x){
Node newNode=new Node(x);
newNode.next=after.next;
after.next=newNode;
}
public void deleteAfter(Node del){//Deletes the node that is after the specified node
del.next=del.next.next;
}
public static void main (String args[]){
Node front=new Node(),p=new Node(),q=new Node();
p.item="green";
q.item="red";
p.next=q;
front=p;
front.deleteAfter(p);
front.insertAfter(p,"black");
front.insertAfter(q,"blue");
front.insertAfter(q.next,"orange");
front.deleteAfter(q);
System.out.println(front.item);
System.out.println(front.next.item);
System.out.println(front.next.next.item);
System.out.println(front.next.next.next.item);
}
}
First your list should remember last element or head.
public class YourList{
Node heaed;
public YourList(){
head = null;
}
public void insert(Node node){
if(last == null){
head = node;
}
}
public void deleteAfter(Node del){
if(del.next == head)){
head = del;
}
if(del.next == null){
//do nothing because there is nothing to delete
}
else{
del.next=del.next.next;
}
}
}
At:
p.next=q;
front=p;
front.deleteAfter(p);
front.insertAfter(p,"black");
You have created a two node linked list starting at p, and pointed front to it, then you shrank it down to a one node linked list, and bumped it back to two, consisting of { "green", "black" }. q is a singleton list node which you later manipulate.
When you print starting from front, since it only has two nodes, trying to obtain the item of the third node, which doesn't exist, causes your exception.
Your question started out by asking if there was something wrong with your deleteAfter(), and there is in that it won't correctly handle any correct list of nodes, only a list that actually has something after it. Passing in an empty list or a list with only one node in it will result in an exception.
You can first find the middle node using two pointer approach and then delete the node.
public Node findMiddleNode(Node node){
Node runner = node;
while(node!=null){
node = node.next;
if(node != null){
node = node.next;
runner = runner.next;
}
}
return runner;
}
public static boolean deleteNode(Node node){
if(node==null || node.next==null) return false;
Node next = node.next;
node.data = next.data;
node.next = next.next;
return true;
}
Solution which first calculates the size of the list and deletes the n/2 element without using two pointers.
For example, if given linked list is 1->2->3->4->5 then linked list should be modified to 1->2->4->5. If there are even nodes, then there would be two middle nodes, the second middle element gets deleted. For example, if given linked list is 1->2->3->4->5->6 then it should be modified to 1->2->3->5->6.
public void deleteMiddle() {
if (head == null) {
System.out.println("List is emplty");
return;
} else if (head.next == null) {
head = null;
return;
} else {
int count = 0;
int nodeDeleteIndex = 0;
Node node = this.head;
Node temp = this.head;
// To calculate the list size
while (node != null) {
count++;
node = node.next;
}
// getting the n/2 index of the node which needs to be deleted
nodeDeleteIndex = (count / 2);
for (int i = 0; i < nodeDeleteIndex - 1; i++) {
temp = temp.next;
}
temp.next = temp.next.next;
}
}

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 );
}

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.

Java remove duplicates from linked 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);
}
}}

Categories