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();
}
}
Related
I am implementing a version of singly linked list in Java with a dummy node.
public class Node{
private String data;
private Node nextNode;
public Node(String data){
this.data = data;
this.nextNode = null;
}
//getters, setters, toString()
}
public class LinkedList {
private Node header;
private Node lastNode;
private int size;
public LinkedList() {
this.header = new Node(null);
this.lastNode = this.header;
size = 0;
}
public void prepend(String data) {
if (data == null || data.trim().length() == 0) {
return;
}
Node newNode = new Node(data);
// when the linked list is empty
if (size == 0) {
this.header.setNext(newNode);
this.lastNode = newNode;
} else { // when the list has nodes
Node existingNode = this.header.getNext();
newNode.setNext(existingNode);
this.header.setNext(newNode);
}
size++;
}
}
I am mainly concentrating on this part.
public LinkedList() {
this.header = new Node(null);
this.lastNode = this.header;
size = 0;
}
When a linked list object is created and initialized, header and last node point to a dummy node.
Would this be an efficient way to implement a linked list? Or, do I have to alter my code in prepend() method as follows?
public void prepend(String data) {
if (data == null || data.trim().length() == 0) {
return;
}
Node newNode = new Node(data);
// when the linked list is empty
if (size == 0) {
this.header = new Node(null);
this.header.setNext(newNode);
this.lastNode = newNode;
} else { // when the list has nodes
Node existingNode = this.header.getNext();
newNode.setNext(existingNode);
this.header.setNext(newNode);
}
size++;
}
Also, is it really necessary to use a dummy node as the header? Can we use the first node itself as the header? Under what circumstances should we be using a dummy node, if at all used?
A dummy node is useful if you want to enforce a non-null constraint for the link fields of the node. Further, it allows to implement all operations without the need to implement special cases for the first and last node, e.g.
public class LinkedList {
static final Node REMOVED = new Node();
public static class Node {
Node next, prev;
String data;
Node() {
next = prev = this;
}
Node(String s, Node n, Node p) {
data = s;
next = n;
prev = p;
}
public Node insertBefore(String s) {
if(next == REMOVED) throw new IllegalStateException("removed node");
Node node = new Node(s, this, prev);
prev.next = node;
prev = node;
return node;
}
public Node insertAfter(String s) {
return next.insertBefore(s);
}
public void remove() {
if(next == REMOVED) throw new IllegalStateException("already removed");
prev.next = next;
next.prev = prev;
next = prev = REMOVED;
}
#Override
public String toString() {
return data;
}
}
final Node content = new Node();
private Node first() {
return content.next;
}
private Node last() {
return content.prev;
}
public Node getFirst() {
Node f = first();
if(f == content)
return null; // or throw new NoSuchElementException(string);
return f;
}
public Node getLast() {
Node f = last();
if(f == content)
return null; // or throw new NoSuchElementException(string);
return f;
}
public Node prepend(String s) {
return first().insertBefore(s);
}
public Node append(String s) {
return last().insertAfter(s);
}
public Node findFirst(String string) {
for(Node n = first(); n != content; n = n.next) {
if(n.data.equals(string)) return n;
}
return null; // or throw new NoSuchElementException(string);
}
public Node findLast(String string) {
for(Node n = last(); n != content; n = n.prev) {
if(n.data.equals(string)) return n;
}
return null; // or throw new NoSuchElementException(string);
}
void printForward() {
for(Node n = first(); n != content; n = n.next) {
System.out.println(n.data);
}
}
void printBackward() {
for(Node n = last(); n != content; n = n.prev) {
System.out.println(n.data);
}
}
}
This is a doubly linked list whose internally used dummy node’s next and prev fields become the “first” and “last” fields of the list. This way, all modification methods only have to operate on the Node class and its next and prev fields and the references to the first and last node are treated the right way automatically. Note how all modification methods settle atop only two implementation methods, insertBefore and remove.
It can be use like
LinkedList l = new LinkedList();
l.append("H").insertAfter("l").insertAfter("l");
l.findFirst("l").insertBefore("e");
l.findLast("l").insertAfter("o");
l.printForward();
System.out.println();
l.getFirst().remove();
l.findFirst("l").remove();
l.getFirst().remove();
l.getLast().insertBefore("r");
l.getFirst().insertBefore("d");
l.append("W");
l.printBackward();
for example. For a single linked list, a dummy node might be less useful. If, like in your example, you’re not drawing a benefit from it but have all the special case handling, you should not use a dummy node which only makes the code even more complicated.
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
public class Node<E> {
private E element;
public Node<E> next;
int data;
Node(int d)
{
data = d;
next = null;
}
public Node(E element, Node<E> next) {
this.element = element;
this.next = next;
}
public E getElement() {
return element;
}
public Node<E> getNext() {
return next;
}
public void setElement(E element) {
this.element=element;
}
public void setNext(Node<E> n) {
next = n;
}
public void displayNode(){
System.out.print(element+ " ");
}
}
public class SinglyLinkedList<E> {
private Node<E> head;
private Node<E> tail;
private int size;
public SinglyLinkedList() {
head = tail = null;
size = 0;
}
public SinglyLinkedList(Node<E> head, Node<E> tail) {
this.head = head;
this.tail = tail;
}
public Node<E> getHead() {
return head;
}
public Node<E> getTail() {
return tail;
}
public void setHead(Node<E> head) {
this.head = head;
}
public void setTail(Node<E> tail) {
this.tail = tail;
}
public boolean isEmpty() {
if (head == null) {
return true;
}
return false;
}
public E first() {
return head.getElement();
}
public E last() {
return tail.getElement();
}
public void addFirst(E e) {
if (head == null) {
head = tail = new Node(e, null);
} else {
Node<E> newest = new Node(e, head);
head = newest;
}
size++;
}
public void addLast(E e) {
if (tail == null) {
head = tail = new Node(e, null);
} else {
Node<E> newest = new Node(e, null);
tail.setNext(newest);
tail = newest;
}
size++;
}
public E removeFirst() {
E e = head.getElement();
head = head.getNext();
size--;
return e;
}
#Override
public String toString() {
Node<E> tmp = head;
String s = "";
while (tmp != null) {
s += tmp.getElement();
tmp=tmp.getNext();
}
return s;
}
public void displayList() {
Node current = head;
while (current != null) {
current.displayNode();
current = current.next;
}
}
}
public interface Queue<E> {
int size();
boolean isEmpty();
void enqueue( );
E first();
E dequeue();
}
public class LinkedQueue<E> implements Queue<E> {
private SinglyLinkedList<E> list = new SinglyLinkedList<>();
public LinkedQueue() {
}
public int size() {
return list.size();
}
public boolean isEmpty() {
return list.isEmpty();
}
public void enqueue(E element) {
list.addLast(element);
}
public E first() {
return list.first();
}
public E dequeue() {
return list.removeFirst();
}
#Override
public void enqueue() {
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools |list.addLast(element);
}
public void displayQueue() {
list.displayList();
System.out.println();
}
public class Main {
public static void main(String[] args) {
LinkedQueue list = new LinkedQueue();
list.enqueue(sam);
list.enqueue(adams);
list.enqueue(john);
list.enqueue(isac);
list.enqueue(gad);
System.out.print("\n Linked list before calling swapNodes() ");
list.displayQueue();
}}
How to change the order of these names in the queue?
I have try to put function that swap nodes in the singlylinkedlist class but it didn't work.i m confused in which layer should i make this function in the linkedqueue class or the singlylinkedlist class or in the main class. yes i want just to swap names in the queue as simple as that.
UPDATED ANSWER
I modified your Node and NodeList Classes in a way which is easier to understand. I also kept similar private values and similar methods for those classes.
public class JavaApplication287 {
public static class Node{
private Node node;
private Node nextNode;
int data;
Node(int d){
data = d;
nextNode = null;
}
public Node getNode(){return node;}
public void setNode(Node someNode){node = someNode;}
public Node getNextNode(){return nextNode;}
public void setNextNode(Node someNextNode){nextNode = someNextNode;}
public int getData(){return data;}
public void setData(int d){data = d;}
public void printNode(){System.out.println(data);}
}
public static class NodeLinkedList{
private Node head;
private Node tail;
private int size;
NodeLinkedList(Node nodeHead, Node nodeTail, int s){
this.head = nodeHead;
this.tail = nodeTail;
this.size = s;
}
public Node getHead(){return head;}
public void setHead(Node n){head = n;}
public Node getTail(){return tail;}
public void setTail(Node n){tail = n;}
public int getSize(){return size;}
public void setSize(int n){size = n;}
public void printNodeList(){
System.out.println("Head: " + head.getData());
Node current = head;
while (current.nextNode != null){
System.out.println(current.data);
current = current.getNextNode();
}
System.out.println("Tail: " + tail.getData());
}
}
public static void main(String[] args) {
// create Sample Nodes
Node zero = new Node(0);
Node one = new Node(1);
Node two = new Node(2);
Node three = new Node(3);
Node four = new Node(4);
Node five = new Node(5);
//Link Them
zero.setNextNode(one);
one.setNextNode(two);
two.setNextNode(three);
three.setNextNode(four);
four.setNextNode(five);
//Create the Linked Node List with head = one & tail = five
NodeLinkedList myNodeLinkedList = new NodeLinkedList(zero, five, 6);
//Print Current LinkedNodes
myNodeLinkedList.printNodeList();
//Invert the NodeLinkedList
Node position = myNodeLinkedList.getHead(); //Node we look at
Node prev = null; // Store the prev Node
Node node = null; // Temp Node of the next Node in the Linked List
for (int i=0; i< myNodeLinkedList.getSize(); i++){
node = position.getNextNode(); //Store the Next Node so we do not lose access to it
position.setNextNode(prev); // Update current Node's NextNode value
prev = position; // Set previous Node as the Node we are currently looking at
position = node; // Move our position to the next Node
}
//Invert Head and Tail
Node temp = myNodeLinkedList.getHead();
myNodeLinkedList.setHead(myNodeLinkedList.getTail());
myNodeLinkedList.setTail(temp);
//Print Current LinkedNodes
myNodeLinkedList.printNodeList();
}
}
This is working code and here is the output I get,
run:
Head: 0
0
1
2
3
4
Tail: 5
Head: 5
5
4
3
2
1
Tail: 0
BUILD SUCCESSFUL (total time: 0 seconds)
Hope it helps,
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.
I have been diligently watching YouTube videos in an effort to understand linked lists before my fall classes start and I am uncertain how to proceed with iterating over the following linked list. The 'node' class is from a series of videos (same author), but the 'main' method was written by me. Am I approaching the design of a linked list in an illogical fashion (assuming of course one does not wish to use the predefined LinkedList class since the professor will expect each of us to write our own implementation)?:
class Node
{
private String data;
private Node next;
public Node(String data, Node next)
{
this.data = data;
this.next = next;
}
public String getData()
{
return data;
}
public Node getNext()
{
return next;
}
public void setData(String d)
{
data = d;
}
public void setNext(Node n)
{
next = n;
}
public static String getThird(Node list)
{
return list.getNext().getNext().getData();
}
public static void insertSecond(Node list, String s)
{
Node temp = new Node(s, list.getNext());
list.setNext(temp);
}
public static int size(Node list)
{
int count = 0;
while (list != null)
{
count++;
list = list.getNext();
}
return count;
}
}
public class LL2
{
public static void main(String[] args)
{
Node n4 = new Node("Tom", null);
Node n3 = new Node("Caitlin", n4);
Node n2 = new Node("Bob", n3);
Node n1 = new Node("Janet", n2);
}
}
Thanks for the help,
Caitlin
There are some flaws in your linked list as stated by some of the other comments. But you got a good start there that grasps the idea of a linked list and looks functional. To answer your base question of how to loop over this particular implemention of the linked list you do this
Node currentNode = n1; // start at your first node
while(currentNode != null) {
// do logic, for now lets print the value of the node
System.out.println(currentNode.getData());
// proceed to get the next node in the chain and continue on our loop
currentNode = currentNode.getNext();
}
Maybe this will be useful:
static void iterate(Node head) {
Node current = head;
while (current != null) {
System.out.println(current.getData());
current = current.getNext();
}
}
// or through recursion
static void iterateRecursive(Node head) {
if (head != null) {
System.out.println(head.getData());
iterateRecursive(head.getNext());
}
}
class List {
Item head;
class Item {
String value; Item next;
Item ( String s ) { value = s; next = head; head = this; }
}
void print () {
for( Item cursor = head; cursor != null; cursor = cursor.next )
System.out.println ( cursor.value );
}
List () {
Item one = new Item ( "one" );
Item two = new Item ( "three" );
Item three = new Item ( "Two" );
Item four = new Item ( "four" );
}
}
public class HomeWork {
public static void main( String[] none ) { new List().print(); }
}
Good luck!!
You can have your linked list DS class implement 'Iterable' interface and override hasNext(), next() methods or create an inner class to do it for you. Take a look at below implementation:
public class SinglyLinkedList<T>{
private Node<T> head;
public SinglyLinkedList(){
head = null;
}
public void addFirst(T item){
head = new Node<T>(item, head);
}
public void addLast(T item){
if(head == null){
addFirst(item);
}
else{
Node<T> temp = head;
while(temp.next != null){
temp = temp.next;
}
temp.next = new Node<T>(item, null);
}
}
private static class Node<T>{
private T data;
private Node<T> next;
public Node(T data, Node<T> next){
this.data = data;
this.next = next;
}
}
private class LinkedListIterator implements Iterator<T>{
private Node<T> nextNode;
public LinkedListIterator(){
nextNode = head;
}
#Override
public boolean hasNext() {
return (nextNode.next != null);
}
#Override
public T next() {
if(!hasNext()) throw new NoSuchElementException();
T result = nextNode.data;
nextNode = nextNode.next;
return result;
}
}
}