Creating own delete method in a doubly Linked List - java

I need to create a delete method inside of a doubly Linked List. I am having trouble, as I think that I need to have 4 cases.
if the list is empty
if the node being deleted is the head
if the node is the tail
if the node is somewhere in the middle of the list
This is the code that I have so far.
public void delete(Node n) {
if (head == null) {
System.out.println("the list is empty");
} else if (head != null) {
head = n;
Node newHead = n.next;
newHead = head;
} else if (n.next == null) {
Node beforeTail = n.previous;
beforeTail.next = null;
} else if (n.next != null || n.previous != null) {
Node inFront = n.previous;
Node inBack = n.next;
inFront.next = inBack;
inBack.previous = inFront;
} else {
System.out.println("error");
}
}
Here is the test program:
public class TestLL {
public static void main(String[] args){
/*Create a bunch of free standing nodes */
Node n1= new Node(new Integer(11));
Node n2= new Node(new Integer(12));
Node n3= new Node(new Integer(13));
Node n4= new Node(new Integer(14));
Node n5= new Node(new Integer(15));
Node n6= new Node(new Integer(16));
Node n7= new Node(new Integer(17));
/* link them */
LL myLL =new LL();
myLL.printList(); // prints "empty list"
myLL.add(n1); //11
myLL.add(n3); //13
myLL.add(n5); //15
myLL.add(n2); //12
myLL.add(n7); //17
myLL.printList(); //should print 11, 13, 15, 12, 17; one per line
System.out.println();
myLL.delete(n3);
myLL.addAfter(n4,n1);
myLL.printList(); //should print 11,14,15,12,17 one per line
System.out.println();
myLL.delete(n7);
myLL.delete(n2);
myLL.printList();//should print 11,14,15 one per line
}
}
I am not really sure what to do at all. Also I cannot use any methods already in Java.

Hard to say but the LL approach looks wrong. Generally working with an LL will not require any awareness of "nodes" as it is up to the implementation to handle all the linking details. The code that calls should be passing in objects of it's choice.
I would expect usage of LL to look like this.
LL myLL = new LL();
myLL.add(new Integer(1));
myLL.add(new Integer(2));
// etc
myLL.remove(new Integer(1));
During a call to add a new Node (internal class to LL) would get created and appended to the end. Remove/delete would search the LL and remove the first instance that matches the passed in object.
e.g. A rough sketch of an LL implementation.
class LL
{
private Node headNode = null;
public void add(Object item)
{
// construct a new node
// iterate to the last node and add new node to the end
}
public boolean remove(Object item)
{
// starting at the head node search the list until a node with the matching item is found
// update the node pointers to "remove" the node
}
class Node
{
Node nextNode;
Node prevNode;
Object item;
}
}
I won't fill in the implementations as this is homework ;) but you are right in there are a few cases to handle
List is empty
Item is not present
Item is in the head node
Item is in another node
Good luck!

Related

Trouble sorting linked list

outputI'm doing a project for class where I have to sort a linked list using insertion sort. I am supposed to take user input, convert it into an int array and insert it into a linked list. My problem is for some reason when I go to print the linked list post sort, it only prints the first node. The code worked jsut fine when I was initially testing it(I was manually entering what integers to insert), but now that I'm using arrays it doesn't seem to work. Can anyone help?
(this is only one class from my project but let me know if more information is needed).
Edit: I added a picture of what my output lokos like
import java.util.Arrays;
public class SortLL {
static LL top;
static Node head;
static Node sorted;
//function to insert node at head
public void toHead(int newData){
Node newNode = new Node(newData);
newNode.link = head;
head = newNode;
}
public static void insertion(Node ref){ //problem right now is that i'm only passing in one node
sorted = null;
Node current = ref;
while(current != null){
Node next = current.link;
sortInsert(current);
current = next;
}
head = sorted;
}
static void sortInsert(Node newNode){ //item in this case is val
if(sorted == null || sorted.item >= newNode.item){
newNode.link = sorted;
sorted = newNode;
} else {
Node current = sorted;
while(current.link != null && current.link.item < current.item){
current = current.link;
}
newNode.link = current.link;
current.link = newNode;
}
}
void printList(Node head)
{
while (head != null)
{
System.out.print(head.item + " ");
head = head.link;
}
}
public static void sortList(int[] arrA, int[] arrB){
int[] arr = new int[arrA.length + arrB.length];
System.arraycopy(arrA, 0, arr, 0, arrA.length);
System.arraycopy(arrB, 0, arr, arrA.length, arrB.length);
System.out.println("checking array " + Arrays.toString(arr));
SortLL sort = new SortLL();
for(int i=0;i<arr.length;i++){
sort.toHead(arr[i]);
}
System.out.println("sortLL.java\n\n");
sort.printList(sort.head);
sort.sortInsert(sort.head);
System.out.println("\nLinkedList After sorting");
sort.printList(sort.head);
}
}
Inside your printList() method, you shift the head variable while iterating over the list. When you move the head variable to the end, you essentially destroy the linked list since you lose your reference to the beginning of it. Java will then automatically treat the unreferenced nodes as garbage.
From what I see, after you first call sort.printList(sort.head), you destroyed your original linked list, so it didn't work when sorting.
When calling printList(), it might help to use a temporary node (Node temp = head) so that you don't lose your original head variable.

Add node to end of Linked List

Having a bit of trouble adding a node to the end of my linked list. It only seems to display the very last one I added before I call my addFirst method. To me it looks like on the addLast method I'm trying to first create the node to assign it 5, then for the following numbers use a while loop to assign them to the last node on the linked list. Little stuck on why I can't get my output to display 5 and 6.
class LinkedList
{
private class Node
{
private Node link;
private int x;
}
//----------------------------------
private Node first = null;
//----------------------------------
public void addFirst(int d)
{
Node newNode = new Node();
newNode.x = d;
newNode.link = first;
first = newNode;
}
//----------------------------------
public void addLast(int d)
{
first = new Node();
if (first == null)
{
first = first.link;
}
Node newLast = new Node();
while (first.link != null)
{
first = first.link;
}
newLast.x = d;
first.link = newLast;
first = newLast;
}
//----------------------------------
public void traverse()
{
Node p = first;
while (p != null)
{
System.out.println(p.x);
p = p.link;
}
}
}
//==============================================
class test123
{
public static void main(String[] args)
{
LinkedList list = new LinkedList();
list.addLast(5);
list.addLast(6);
list.addLast(7);
list.addFirst(1);
list.addFirst(2);
list.addFirst(3);
System.out.println("Numbers on list");
list.traverse();
}
}
I've also tried creating a last Node and in the traverse method using a separate loop to traverse the last node. I end up with the same output!
public void addLast(int d)
{
Node newLast = new Node();
while (last.link != null)
{
last = newLast.link;
}
newLast.x = d;
newLast.link = last;
last = newLast;
}
The logic of your addLast method was wrong. Your method was reassigning first with every call the logic falls apart from that point forward. This method will create the Node for last and if the list is empty simply assign first to the new node last. If first is not null it will traverse the list until it finds a Node with a null link and make the assignment for that Nodes link.
public void addLast(int d) {
Node last = new Node();
last.x = d;
Node node = first;
if (first == null) {
first = last;
} else {
while (node.link != null) {
node = node.link;
}
node.link = last;
}
}
Your addLast() method displays the value of the last node because every time you append a node to the end of your list, you are overwriting the reference to "first". You are also doing this when you assign a new reference to first in the following line:
first = new Node();
Try the following:
public void addLast(int d)
{
Node newLast = new Node();
if (first == null)
{
newLast.x = d;
first = newLast;
return;
}
Node curr = first;
while (curr.link != null)
{
curr = curr.link;
}
newLast.x = d;
curr.link = newLast;
}
The method creates a new node and it is added to the end of the list after checking two conditions:
1.) If first is null: in this case the list is empty and the first node should be
initialized to the new node you are creating, then it will return (or you could do
an if-else).
2.) If first is not null: If the list is not empty you'll loop through your list until you
end up with a reference to the last node, after which you will set its next node to the
one you just created.
If you wanted to keep track of the tail of your list called "last", like you mentioned above, then add:
last = newLast
at the end of your method. Hope this helps!

How can I remove a node from a circular linked list?

I am a beginner in java and I cannot understand linked lists in Java because of their complication. So my code is very simple.
Node node, head, tail;
head = null; // initializes the head of the linked list to null
int counter = 0;
String inputdata; // input
do
{
System.out.print ("What name would you like stored? (\"quit\" to end) ");
inputdata = stdin.readLine ();
if (!inputdata.equals ("quit"))
{
node = new Node (inputdata);
node.next = head;
// update the head to point to the new front of the list
head = node;
count++;
}
}
while (!inputdata.equals ("quit")); // loop continues until "quit" selected
System.out.println ();
node = head;
///////////////////////////////
String delete;
boolean found;
System.out.println ("What node to delete?");
delete = stdin.readLine ();
do
{
for (int i = 0 ; i <= count ; i++)
{
if (delete.equals (node.data))
{
found = true;
System.out.println ("It is found!");
}
}
}
while (found = false);
This is the class
public class Node
{
Node next;
String data;
public Node (String data)
{
this.data = data;
}
}
I understand how the algorithm works. A node is searched and when its found it points the node previous to it to the node after the one being searched.
Whenever I search for the node I get java.lang.nullpointer exceptions which basically translates into my code is terrible.
I need help because whenever I search how to do this I always ask to myself"why put this" or "what is LS" or "why are there multiple methods and what number are the variables n within it".
Please tell me what Im doing wrong and what I need to do.
node = new Node (inputdata);
node.next = head;
// update the head to point to the new front of the list
head = node;
count++;
1st you make a node, then you say the next one from this node is the head...
and then you go and say thet the head is this node... so you're basically making the head == node == node.next
That just doesn't do :D
I suggest this:
//Init head and tail...
if(head==null){
head = new Node("Head"); //use whatever data you want/need
tail= new Node("Tail");
tail.next=head;
head.next = tail;
}
//add a new node...
newnode = new Node("Some data");
//since this is a one-way linked list, i suggest you walk from the head
//and go until you meet the tail
currNode = head;
while( currNode.next.data.compareTo("Tail") != 0 )
{
currNode = currNode.next;
}
//now add the new node here...
newnode.next = currNode.next;
currNode.next = newNode;
This way you always add it to the "end" of the list...
If you want to add it at the begining, so just after the head use this:
newNode = new Node("Some data");
newNode.next = head.next;
head.next = newNode;
It's adviseable that you have a "limiter" like a tail to know when you're at the end of your list...
So now your delete should work, but i recommend a few more things:
currentNode = head;
do
{
if(currentNode.next.data.compareTo(delete)==0){ //if the next one is the one i'm looking for, remove it and let the garbage collector take care of it
currentNode.next = currentNode.next.next;
break; //leave the loop
else
currentNode = currentNode.next;
}
while (currentNode.next.data.compareTo("Tail") != 0);
With this while loop you'll traverse your list until the end/tail and stop if it wasn't found...
In your example it would go around and around the list for ever, since the searched node wasn't found

Add to front of linked list

I am confused as to how to add to the front of the linked list.
/**
* data is added to the front of the list
* #modifies this
* #ffects 2-->4-->6 becomes data-->2-->4-->6
*/
public void insert(E data) {
if (front == null)
front = new Node(data, null);
else {
Node temp = new Node(data, front);
front = temp;
}
}
This creates a cycle. How do I avoid that?
I have a LinkedList class which holds the front Node, in a variable called front.
I have a Node class within this LinkedList class.
Any help would be appreciated.
Thank you.
Don't you have access to "Next" node ?
In that case
public void insert(E data) {
if (front == null) {
front = new Node(data, null);
} else {
Node temp = new Node(data, null);
temp.next = front;
front = temp;
}
}
--
class LinkedList {
Node front;
LinkedList() {
front = null;
}
public void AddToFront(String v) {
if (front == null) {
front = new Node(v);
} else {
Node n = new Node(v);
n.next = front;
front = n;
}
}
}
class Node {
public Node next;
private String _val;
public Node(String val) {
_val = val;
}
}
I'm assuming that the Node constructor takes a next pointer as its 2nd argument, in which case I don't see anything obvious wrong with this code. This really sounds like a homework question. If it is, you should tag it as such.
With my limited linked list knowledge, I would venture this:
Node temp = new Node(data);
temp.next = front;
front = temp;
You might want to wait around for somebody to confirm though.
This creates a cycle. How do I avoid that?
It is not possible to know for sure without the rest of the code for your linked list implementation, but the code that you have supplied doesn't look like it creates a cycle at all.
If a cycle is being created, it is most likely being created elsewhere. Alternatively, you / your tests are misdiagnosing some other failure as being caused by a cycle.
If you need more help, post more code / evidence ... particularly the Node constructor, and the code that makes you think you have a cycle.
Add a new node and if the current head is not null, then point the current head to the newly created node as the next node.
Node insert(Node head,int x) {
Node node = new Node();
node.data = x;
if(head != null) {
node.next = head;}
return node;
}
This is my Implementation of Inserting a node to front or head of the Linked List in Java.
void insertAtHead(Object data){
if(head==null) {
head = new Node(data);
}
Node tempNode = new Node(data);
Node currentNode = head;
tempNode.setNext(currentNode.getNext());
head.setNext(tempNode);
incrementCounter();
}
A simple and quick [ may not be efficient ] solution is to create a temporary new LinkedList with the new element and merge the two lists together with the temp-list in the front.
see the example below
import java.util.*;
public class Main
{
public static Queue<Integer> addFirst(Queue<Integer> intQueue, Integer i){
Queue<Integer> intQueue2 = new LinkedList<Integer>();
intQueue2.add(i);
intQueue2.addAll(intQueue);
intQueue = intQueue2;
return intQueue;
}
public static void main(String[] args) {
System.out.println("Hello LinkedList");
Queue<Integer> intQueue = new LinkedList<Integer>();
intQueue.add(3);
intQueue.add(4);
intQueue.add(5);
intQueue = addFirst(intQueue,2);
intQueue = addFirst(intQueue,1);
System.out.println(intQueue);
}
}

Invert linear linked list

a linear linked list is a set of nodes. This is how a node is defined (to keep it easy we do not distinguish between node an list):
class Node{
Object data;
Node link;
public Node(Object pData, Node pLink){
this.data = pData;
this.link = pLink;
}
public String toString(){
if(this.link != null){
return this.data.toString() + this.link.toString();
}else{
return this.data.toString() ;
}
}
public void inc(){
this.data = new Integer((Integer)this.data + 1);
}
public void lappend(Node list){
Node child = this.link;
while(child != null){
child = child.link;
}
child.link = list;
}
public Node copy(){
if(this.link != null){
return new Node(new Integer((Integer)this.data), this.link.copy());
}else{
return new Node(new Integer((Integer)this.data), null);
}
}
public Node invert(){
Node child = this.link;
while(child != null){
child = child.link;
}
child.link = this;....
}
}
I am able to make a deep copy of the list. Now I want to invert the list so that the first node is the last and the last the first. The inverted list has to be a deep copy.
I started developing the invert function but I am not sure. Any Ideas?
Update: Maybe there is a recursive way since the linear linked list is a recursive data structure.
I would take the first element, iterate through the list until I get to a node that has no child and append the first element, I would repeat this for the second, third....
I sometimes ask this question in interviews...
I would not recommend using a recursive solution, or using a stack to solve this. There's no point in allocating O(n) memory for such a task.
Here's a simple O(1) solution (I didn't run it right now, so I apologize if it needs some correction).
Node reverse (Node current) {
Node prev = null;
while (current != null) {
Node nextNode = current.next;
current.next = prev;
prev = current;
current = nextNode;
}
return prev;
}
BTW: Does the lappend method works? It seems like it would always throw a NullReferenceException.
There's a great recursive solution to this problem based on the following observations:
The reverse of the empty list is the empty list.
The reverse of a singleton list is itself.
The reverse of a list of a node N followed by a list L is the reverse of the list L followed by the node N.
You can therefore implement the reverse function using pseudocode along these lines:
void reverseList(Node node) {
if (node == null) return; // Reverse of empty list is itself.
if (node.next == null) return; // Reverse of singleton list is itself.
reverseList(node.next); // Reverse the rest of the list
appendNodeToList(node, node.next); // Append the new value.
}
A naive implementation of this algorithm runs in O(n2), since each reversal requires an append, which requires an O(n) scan over the rest of the list. However, you can actually get this working in O(n) using a clever observation. Suppose that you have a linked list that looks like this:
n1 --> n2 --> [rest of the list]
If you reverse the list beginning at n2, then you end up with this setup:
n1 [reverse of rest of the list] --> n2
| ^
+------------------------------------------+
So you can append n1 to the reverse of the rest of the list by setting n1.next.next = n1, which changes n2, the new end of the reverse list, to point at n1:
[reverse of the rest of the list] --> n2 --> n1
And you're golden! Again more pseudocode:
void reverseList(Node node) {
if (node == null) return; // Reverse of empty list is itself.
if (node.next == null) return; // Reverse of singleton list is itself.
reverseList(node.next); // Reverse the rest of the list
node.next.next = node; // Append the new value.
}
EDIT: As Ran pointed out, this uses the call stack for its storage space and thus risks a stack overflow. If you want to use an explicit stack instead, you can do so like this:
void reverseList(Node node) {
/* Make a stack of the reverse of the nodes. */
Stack<Node> s = new Stack<Node>();
for (Node curr = node; node != null; node = node.next)
s.push(curr);
/* Start unwinding it. */
Node curr = null;
while (!s.empty()) {
Node top = s.pop();
/* If there is no node in the list yet, set it to the current node. */
if (curr == null)
curr = top;
/* Otherwise, have the current node point to this next node. */
else
curr.next = top;
/* Update the current pointer to be this new node. */
curr = top;
}
}
I believe that this similarly inverts the linked list elements.
I would treat the current list as a stack (here's my pseudo code):
Node x = copyOf(list.head);
x.link = null;
foreach(node in list){
Node temp = copyOf(list.head);
temp.link = x;
x = temp;
}
At the end x will be the head of the reversed list.
I more fammiliar whit C, but still let me try. ( I just do not sure if this runs in Java, but it should)
node n = (well first one)
node prev = NULL;
node t;
while(n != NULL)
{
t = n.next;
n.next = prev;
prev = n;
n = t;
}
Reversing a single-linked list is sort of a classic question. It's answered here as well (and well answered), it does not requires recursion nor extra memory, besides a register (or 2) for reference keeping.
However to the OP, I guess it's a school project/homework and some piece of advice, if you ever get to use single linked list for some real data storage, consider using a tail node as well. (as of now single linked lists are almost extinct, HashMap buckets comes to mind, though).
Unless you have to check all the nodes for some condition during 'add', tail is quite an improvement. Below there is some code that features the reverse method and a tail node.
package t1;
public class SList {
Node head = new Node();
Node tail = head;
private static class Node{
Node link;
int data;
}
void add(int i){
Node n = new Node();
n.data = i;
tail = tail.link =n;
}
void reverse(){
tail = head;
head = reverse(head);
tail.link = null;//former head still links back, so clear it
}
private static Node reverse(Node head){
for (Node n=head.link, link; n!=null; n=link){//essentially replace head w/ the next and relink
link = n.link;
n.link = head;
head = n;
}
return head;
}
void print(){
for (Node n=head; n!=null;n=n.link){
System.out.println(n.data);
}
}
public static void main(String[] args) {
SList l = new SList();
l.add(1);l.add(2);l.add(3);l.add(4);
l.print();
System.out.println("==");
l.reverse();
l.print();
}
}
I was wondering something like that(I didnt test it, so):
invert(){
m(firstNode, null);
}
m(Node v, Node bef){
if(v.link != null)
m(v.link,v);
else
v.link=bef;
}
Without much testing,
Node head = this;
Node middle = null;
Node trail = null;
while (head != null) {
trail = middle;
middle = head;
head = head.link;
middle.link = trail;
}
head = middle;
return head;
public ListNode Reverse(ListNode list)
{
if (list == null) return null;
if (list.next == null) return list;
ListNode secondElem = list.next;
ListNode reverseRest = Reverse(secondElem);
secondElem.Next = list;
return reverseRest;
}
Hope this helps.

Categories