So I wrote my own linked list (and list node) in Java as a part of a homework.
Now, I'm trying to erase entries, but the function is not working.
I know the concept:
Search for node keeping the previous;
Tell previous node to point to next node;
Return or stop using the node so GC erases it.
For some reason it is not working. I can delete the node with the same value over and over. I'm afraid it is something related to Java pointers.
The code:
Node:
public class SimpleNode<E> {
private E value;
private SimpleNode<E> next;
public SimpleNode() {
this.value = null;
this.next = null;
}
public NoSimples(E data, SimpleNode<E> ref) {
this.value = data;
this.next = ref;
}
// Getters and Setters
}
List:
public class LinkedList<E> implements Iterable<SimpleNode<E>> {
private SimpleNode<E> head;
private int size = 0;
public LinkedList() {
this.head = new SimpleNode<E>();
}
public void add(SimpleNode<E> node) {
this.addFirst(node.getValue());
}
public void addFirst(E item) {
SimpleNode<E> nonde = new SimpleNode<E>(item, this.head);
this.head = node;
size++;
}
public void add(E value) {
this.addFirst(value);
}
public SimpleNode<E> removeFirst() {
SimpleNode<E> node = this.head;
if (node == null) {
return null;
} else {
this.head = node.getNext();
node.setNext(null);
this.size--;
return node;
}
}
public SimpleNodes<E> remove(E value) {
SimpleNode<E> nodeAnt = this.head;
SimpleNode<E> node = this.head.getNext();
while (node != null) {
if (node.getValue()!= null && node.getValue().equals(value)) {
nodeAnt.setNext(node.getNext());
node.setNext(null);
return node;
}
nodeAnt = node;
node = node.getNext();
}
return null;
}
// Other irrelevant methods.
}
Multiple Problems :
Think if you have a list 1,2,3,4. Now, if you try to remove 1, your code fails.
nodeAnt = node should be nodeAnt = nodeAnt.getNext(). Remember, the're all references, not Objects
Also, a recursive way might be easier to understand. For example, Here is how I implemented it
public void remove(E e){
prev = head;
removeElement(e, head);
System.gc();
}
private void removeElement(E e, Node currentElement) {
if(currentElement==null){
return;
}
if(head.getData().equals(e)){
head = head.getNext();
size--;
}else if(currentElement.getData().equals(e)){
prev.setNext(currentElement.getNext());
size--;
}
prev = prev.getNext();
removeElement(e, currentElement.getNext());
}
Note: I delete all occurrences of the Element, as I needed it. You may need it to be different.
Related
I was working on a program to add nodes to a list, but I seem to be doing something wrong...
My java program has three Classes; Demo, Lista and Node
Class Node:
public class Node {
private int num;
private Node tail;
private Node head;
public Node (int num, Node head, Node tail) {
this.num = num;
this.head = head;
this.tail = tail;
}
}
Class Lista:
public class Lista {
private Node nil;
public Lista () {
nil = null;
}
public void add (int num) {
Node newNode = new Node(num, head, tail);
if (head == null) {
head = newNode;
tail = newNode;
}
}
public void display () {
Node current = head;
while(current != null) {
System.out.print(current.num);
}
}
}
Class Demo:
public class Demo {
public static void main ( String [] args) {
Lista lista = new Lista();
lista.add(3);
lista.add(9);
lista.add(7);
lista.display();
}
}
Demo class is to add the different nodes to the list "lista". Class Node has num, head which is the next one and tail which is the previous one. How can I go about getting Class Lista to be able to use head and tail from Class Node? And if it is possible would this code work when running Demo? What should I change/modify to get this to work?
You may want to modify your code something like this:
EDIT - This is a doubly-linked list implementation.
class Node {
int num;
Node prev;
Node next;
Node(int num) {
this.num = num;
}
Node(int num, Node prev, Node next) {
this.num = num;
this.prev = prev;
this.next = next;
}
void setPrev(Node prev) {
this.prev = prev;
}
void setNext(Node next) {
this.next = next;
}
}
class Lista {
Node root;
Node endNode;
public void add(int num) {
Node n = new Node(num);
if (root == null) {
root = n;
} else {
n.setPrev(endNode);
endNode.setNext(n);
}
endNode = n;
}
public void display() {
Node iterateeNode = root;
while (iterateeNode != null) {
System.out.print(iterateeNode.num + " ");
iterateeNode = iterateeNode.next;
}
}
}
The selected answer is technically not correct. For a (single) Linked List, all your Lista need is a single (head) node. Additionally, the Node class needs a single (next) Node field.
The following is a potential implementation of Node:
public class Node {
private Node next;
private int value;
public Node(int value) {
this.value = value;
}
public boolean hasNext() {
return next != null;
}
public Node next() {
return next;
}
public void add(Node node) {
if (next == null) {
next = node;
} else {
Node temp = next;
while (temp != null) {
temp = temp.next;
}
temp = node;
}
}
#Override
public String toString() {
return String.valueOf(value);
}
}
The add() method will insert the new node in next if it is null. Otherwise, it will traverse the nodes until it finds the tail node (the one where next is null).
The Lista has only the first element in the list (head node).
public class Lista {
private Node head;
public void add(Node node) {
if (head == null) {
head = node;
} else {
Node temp = head;
while (temp.hasNext()) {
temp = temp.next();
}
temp.add(node);
}
}
// Other methods
}
When the add() function in the list is called, it will either add the new node as the head (if the list doesn't have one already) or rely on the already added nodes to figure out where the end of the list is in order to insert the new node.
Lastly, to display the list, just override the toString() method in node and add the "toString" value to a string buffer and send the concatenated string value to the console similar to the the code below.
public void display() {
StringBuilder buff = new StringBuilder("[");
buff.append(head);
if (head != null) {
Node next = head.next();
buff.append(",");
while (next != null) {
buff.append(next);
next = next.next();
buff.append(",");
}
}
buff.append("]");
int idx = buff.lastIndexOf(",");
buff.replace(idx, idx+1, "");
System.out.println(buff.toString());
}
Executing the following displays [3,9,7] as expected.
public class Demo {
public static void main ( String [] args) {
Lista lista = new Lista();
lista.add(new Node(3));
lista.add(new Node(9));
lista.add(new Node(7));
lista.display();
}
}
I would like to ask: how to add a new node before the head of a linked list:
Here is my code:
// Definition for singly-linked list.
public class ListNode {
int val;
ListNode next;
ListNode() {}
ListNode(int val) { this.val = val; }
ListNode(int val, ListNode next) { this.val = val; this.next = next; }
public void addAfter(ListNode thisnode, int x) {
ListNode newNode = new ListNode(x);
if(thisnode == null) {
//add before the head
newNode.next = this;
}//wrong here
else {
ListNode currentNext = thisnode.next;
thisnode.next = newNode;
newNode.next = currentNext;
}
return;
}//done addAfter this node
}
For example, with the input list 2 100 300 800, l.addAfter(null,500); the output should be
500 2 100 300 800 but my output is still 2 100 300 800. Thank you.
Inserting before head would change the value of head. Which you can't do from inside the method.
public ListNode addAfter(ListNode thisnode, int x) {
ListNode newNode = new ListNode(x);
if(thisnode == null) {
//add before the head
newNode.next = this;
return newNode;
} else {
ListNode currentNext = thisnode.next;
thisnode.next = newNode;
newNode.next = currentNext;
}
return this;
}
And the caller would call it like l = l.addAfter(null,500);
First of all, make your code clear, readable and consistent. Here is what you asked for:
public class Node {
private int value;
private Node next;
public Node(int value) {
this.value = value;
next = null;
}
public int getValue() {
return value;
}
public void setValue(int value) {
this.value = value;
}
public Node getNext() {
return next;
}
public void setNext(Node next) {
this.next = next;
}
}
public class ListNode {
private Node head;
public ListNode(Node head) {
this.head = head;
}
public Node getHead(){
return head;
}
// Here is your function
public void insertBeforeHead(int value) {
Node node = new Node(value);
node.setNext(head);
head = node;
}
}
// Node Class
public class SinglyListNode {
int val;
SinglyListNode next;
SinglyListNode(int x) { val = x; }
}
//Singly Linked List class
public class SinglyLinkedList {
private SinglyListNode head;
public SinglyLinkedList() {
head = null;
}
// add at beginning
public void addAtBeginning(int value){
SinglyListNode node = new SinglyListNode(value);
if (head != null) {
node.next = head;
}
head = node;
}
// print list
public void printList(){
System.out.println("printing linked list");
SinglyListNode curr = head;
while (curr != null){
System.out.println(curr.val);
curr = curr.next;
}
}
}
//main method
public static void main(String[] args) {
SinglyLinkedList linkedList = new SinglyLinkedList();
linkedList.addAtBeginning(5);
linkedList.addAtBeginning(6);
linkedList.addAtBeginning(7);
linkedList.printList();
}
You can always make one head that is constant and add all the new elements after it.
Example:
Head - Link1 - Link2 - Link3
Whenever you want to add newLink you can just add it in this manner.
Head - newLink - Link1 - Link2 - Link3
In this way you head information is never lost and it reduce the chances of losing your entire list.
You can explore my codebase here which implements it.
https://github.com/SayefReyadh/tutorials/tree/master/LinkedList-Bangla-Tutorial/LinkedListExample/src/linkedlistexample
The method is implemented as insertFront in LinkedList.java
I am currently learning Doubly Linked Lists.
I have managed to convert write a doubly linked list that was nearly 100% functional. However I need to learn how to write it with tail recursion.
Below is my DLLNode code:
public class DLLNode
{
private DLLNode previous;
public DLLNode next;
private String value;
public DLLNode(String value)
{
this.value = value;
this.previous = previous;
this.next = next;
}
public DLLNode(String value, DLLNode next, DLLNode previous)
{
this.value = value;
this.next = next;
this.previous = previous;
}
public String GetDataItem()
{
return value;
}
public void setDataItem()
{
this.value = value;
}
public DLLNode GetPreviousNode()
{
return previous;
}
public void setPrevious(DLLNode previous)
{
this.previous = previous;
}
public DLLNode GetNextNode()
{
return next;
}
public void setNextNode(DLLNode next)
{
this.next = next;
}
public void addItem(String value) {
if(this.next == null) {
// Stopping condition
DLLNode newNode = new DLLNode(value);
this.next = newNode;
} else {
// Recurse
this.next.addItem(value);
}
}
}
I have managed to get my AddItem working using tail recursion and I'm now looking into getting delete Item working. I'm guessing that like addItem I need deleteItem adding to my DLLNode.
Below is my DoublyLinkedList class:
public class DoublyLinkedList
{
private int noOfItems;
private DLLNode head;
private DLLNode tail;
// Default constructor
public DoublyLinkedList()
{
head = null;
tail = null;
this.noOfItems = 0;
}
public void DeleteItem(int index)
{
if (index ==0)
{
System.out.println("Out of Bounds");
}
if (index > noOfItems)
{
System.out.println("Out of Bounds");
}
if (head == null)
{
System.out.println("No Item to remove");
}
else if (index == 1)
{
head = head.GetNextNode();
noOfItems--;
}
else
{
int position = 0;
DLLNode currentNode = head;
while (currentNode != null) {
if (position == index-1) {
currentNode.setNextNode(
currentNode.GetNextNode().GetNextNode());
noOfItems--;
break;
}
currentNode = currentNode.GetNextNode();
position++;
}
}
}
}
Any tips on where I can get started with converting this code would be greatly appreciated.
Kind Regards,
Ben.
P.S. Apologies for the way the code has formatted - I've tried to fix it but it won't seem to sort. Can anyone good at formatting code on her please try and sort it out?
private void DeleteItemHelper(final int indexToDelete, int curIndex, DLLNode curNode) {
if (curIndex == indexToDelete) {
// Handle removing a node with both a previous and next nodes.
}
else {
DeleteItemHelper(indexToDelete, curIndex + 1, curNode.getNextNode());
}
}
public void DeleteItem(int index) {
DeleteItemHelper(index, 0, head);
}
Without further testing I think that you are forgetting to re-set the head reference of the node following the removed node:
if (position == index-1) {
// Tail of currentNode is set to the node following
// next node, but head of that node still points to the
// node which should be removed from list
currentNode.setNextNode(
currentNode.GetNextNode().GetNextNode());
noOfItems--;
break;
}
Alright, I'm trying to implement a (Singly) Linked List via my textbook (Goodrich & Tamassia, Algorithm Design, 2001), and so far so good.
Now, the problem I'm running into, is that I cannot test it properly For example, if I would insert a node via my insertFirst method, how would I still be able to retrieve it to be able to use it for a method like swapElements?
I thought about working via elements, but then I'll run into problems when I have nodes with the same element. So, how should this work in general? I'm sorry if my question is relatively easy or vague, in that case please let me know how I can improve it as I'm fairly new to data structures.
Here's my code;
public class Node<E> implements Position<E> {
private Node<E> next;
private E element;
public Node(Node<E> next, E element) {
this.next = next;
this.element = element;
}
public Node(E element) {
this.element = element;
}
public void setNext(Node<E> next) {
this.next = next;
}
public Node<E> getNext() {
return next;
}
public void setElement(E element) {
this.element = element;
}
public E element() {
return element;
}
public String toString() {
return ("Element: " + element);
}
}
and
public class SinglyLinkedListImp<E> implements List<E> {
private Node<E> head;
private int size;
public SinglyLinkedListImp() {
this.head = null;
this.size = 0;
}
public Node<E> first() {
return head;
}
public Node<E> last() {
Node<E> current = head;
while (current.getNext() != null) {
current = current.getNext();
}
return current;
}
public boolean isFirst(Node<E> n) {
return (head == n);
}
public boolean isLast(Node<E> n) {
return (n.getNext() == null);
}
public Node<E> before(Node<E> n) {
Node<E> current = head;
while (current.getNext() != n) {
current = current.getNext();
}
return current;
}
public Node<E> after(Node<E> n) {
return n.getNext();
}
public Node<E> replaceElements(Node<E> n, E element) {
Node<E> current = head;
Node<E> previous = null;
while (current != n) {
previous = current;
current = current.getNext();
}
Node<E> newLink = new Node<E>(current.getNext(), element);
previous.setNext(newLink);
return current;
}
public void swapElements(Node<E> n, Node<E> k) {
E tmp = n.element();
n.setElement(k.element());
k.setElement(tmp);
}
public void insertFirst(E element) {
head = new Node<E>(head, element);
size++;
}
public void insertLast(E element) {
if (head == null) {
head = new Node<E>(head, element);
} else {
Node<E> current = head;
while (current.getNext() != null) {
current = current.getNext();
}
current.setNext(new Node<E>(null, element));
}
size++;
}
public void insertBefore(Node<E> n, E element) {
Node<E> current = head;
Node<E> previous = null;
while (current.getNext() != n) {
previous = current;
current = current.getNext();
}
previous.setNext(n);
}
public void insertAfter(Node<E> n, E element) {
Node<E> current = head;
while (current != n) {
current = current.getNext();
}
current.setNext(n);
}
public void remove(Node<E> n) {
Node<E> current = head;
Node<E> previous = null;
while (current != n) {
previous = current;
current = current.getNext();
}
previous.setNext(current.getNext());
size--;
}
public int size() {
return size;
}
public boolean isEmpty() {
return (size == 0);
}
public void display() {
if (head == null) {
System.out.println("Empty list.");
} else {
Node<E> current = head;
while (current != null) {
System.out.println(current.toString());
current = current.getNext();
}
}
}
}
Note that the SinglyLinkedListImp class is not totally done yet (some methods will give errors if the list is empty).
I don't think it's needed to provide the code for the two interfaces, but let me know if so.
In your implementation, you have set some methods (like getNext etc) that can be used in order to iterate the collection. A scenario that I can think of it is having retrieved any element of the list in one operation and then apply the editing on the collection based on the element (like swapElements) afterwards.
What I suggest you do though (and will probably make things clear) is add a retrieval method of an element by index:
a method get(int index) would return the element placed on the index given as argument. In fact, the LinkedList collection standard API in Java has such a method. The logic behind this is simple: get the next node till the iteration cycles number reaches the index number.
UPDATE: In order to apply element swapping, obviously the Nodes involved MUST be a part of the list, otherwise there is no meaning in this. As also suggested, swapElements might be basically used for in-class purposes, so unless you have a good reason for it, declare it private.
Hey ya'll I am having a little trouble with my singly linked list. I decided to create a simple one because we do not get enough practice during my data structures class and cannot seem to find why I am not getting the right output.
The code is:
package linked_list;
public class LinkedList {
private Node head;
private Node tail; // After figuring out head, come back to this FIXME
private int listSize;
public LinkedList() {
head = new Node(null);
tail = new Node(null);
}
public void addLast(String s) {
Node newNode = new Node(s);
if (head == null) {
addFirst(s);
} else {
while (head.next != null) {
head = head.next;
}
head.next = newNode;
tail = newNode;
}
listSize++;
}
public void addFirst(String s) {
Node newNode = new Node(s);
if (head == null) {
head = newNode;
tail = newNode;
}
else {
newNode.next = head;
head = newNode;
}
listSize++;
}
public Object getFirst() {
return head.data;
}
public Object getLast() {
return tail.data;
}
public void clear() {
head = null;
tail = null;
listSize = 0;
}
public Object peek() {
try {
if (head == null) {
throw new Exception ("The value is null");
}
else {
return head;
}
} catch (Exception e) {
System.out.println(e.getMessage());
return null;
}
}
public int size() {
return listSize;
}
// This class has the ability to create the nodes that are used
// in the Linked List.
private class Node {
Node next;
Object data;
public Node(String value) {
next = null;
data = value;
}
public Node(Object value, Node nextValue) {
next = nextValue;
data = value;
}
public Object getData() {
return data;
}
public void setData(Object dataValue) {
data = dataValue;
}
public Node getNext() {
return next;
}
public void setNext(Node nextValue) {
next = nextValue;
}
}
}
Now here is my driver that I created to run a simple little operation:
package linked_list;
public class LinkedListDriver {
public static void main(String[] args) {
LinkedList list1 = new LinkedList();
list1.clear();
list1.addLast("This goes last");
list1.addFirst("This goes first");
list1.addLast("Now this one goes last");
System.out.println(list1.getFirst());
System.out.println(list1.getLast());
}
}
My output is this:
This goes last
Now this one goes last
I guess my question is why am I not getting the answer This goes first from my getFirst() method. It seems to be something wrong with the order or structure of that method but I cannot pinpoint it.
When you are in the else in the addLast, you are changing the reference to head. You should use another reference pointer to traverse the list when adding in the else.
Also, your list size should only be incremented in the else in addLast because you are incrementing twice otherwise (once in addFirst and again after the if-else in addLast).