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;
}
}
}
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();
}
}
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).
I have been trying to utilize my previous made singly linked list to create a doubly linked list. So, in the Node class I added a previous node reference and updated the add and insert methods in the List class to accommodate going back and forth within the DoublyLinked list class. add puts the new node after the current node and insert puts the new node before the current node in the List class; this is because I want to add and insert my values in ascending order within the DoublyLinked list class. [This may sound confusing but I will post the code below] When I test my add method [in the DoublyLinked class] I get a null pointer exception.
As I said I have been working on this for a few days, so in that time I have taken in consideration these previous questions:
How do I change a singly-linked list to a doubly-linked list?
Singly linked list to doubly linked list
Null pointer when using doubly linked list
List.java
public class List<T> implements ListInterface<T> {
protected class Node {
private T value = null;
private Node prev = null;
private Node next = null;
public T getValue( ) {
return value;
}
public Node getPrev( ) {
return prev;
}
public Node getNext( ) {
return next;
}
public void setValue( T newValue ) {
value = newValue;
}
public void setPrev( Node prevNode ) {
prev = prevNode;
}
public void setNext( Node nextNode ) {
next = nextNode;
}
}
protected Node head = null;
protected Node cur = null;
protected int size = 0;
// add after cur
#Override
public void add( T value ) {
Node temp = new Node( );
temp.setValue( value );
size++ ;
if (isEmpty( )) {
head = temp;
cur = temp;
} else {
temp.setNext(cur.getNext());
temp.setPrev(cur);
cur.setNext(temp);
cur = temp;
}
}
// insert before cur
#Override
public void insert( T value ) {
Node temp = new Node( );
temp.setValue( value );
size++ ;
if (isEmpty( )) {
head = temp;
cur = temp;
} else if (head == cur) {
head = temp;
head.setNext( cur );
cur.setPrev(head);
cur = head;
} else {
Node prev = head;
while( prev.getNext( ) != cur ) {
prev = prev.getNext( );
}
temp.setNext( prev.getNext( ) );
temp.setPrev(prev);
prev.setNext( temp );
cur = temp;
}
}
}
DoublyLinked.java
public class DoublyLinked<T extends Comparable<T>>
extends List<T> implements ListInterface<T> {
private int size;
private Node tail;
DoublyLinked() {
this.size = 0;
this.tail = null;
}
#Override
public void add(T value) {
size++;
reset();
// getting Null pointer on add when doublinked list is empty
if(isEmpty()) {
super.add(value);
head = cur;
tail = head;
cur = head;
}
else {
try {
while(value.compareTo(get()) > 0 && hasNext()) { // error here
next();
if(value.compareTo(get()) <= 0) {
super.add(value);
// how to set cur to this new node?
}
}
} catch (EmptyListException | EndOfListException e) {}
super.add(value); // add at end of list
tail = cur;
cur = tail;
}
}
#Override
public T get() throws EmptyListException {
return cur.getValue();
}
#Override
public T next() throws EmptyListException, EndOfListException {
if (!hasNext( )) {
throw new EndOfListException( );
}
cur = cur.getNext( );
return cur.getValue( );
}
#Override
public boolean hasNext() {
return((!isEmpty()) && (cur.getNext() != null));
}
#Override
public void reset() {
cur = head;
}
#Override
public boolean isEmpty() {
return size == 0;
}
}
Then I have a basic JUnit test to test the code:
import static org.junit.Assert.*;
import org.junit.Test;
public class DoublyLinkedTest {
#Test
public void testAdd() {
DoublyLinked<Integer> list = new DoublyLinked<Integer>();
list.add(1);
}
}
You increment size and then call isEmpty() (which checks whether size is zero) to decide how to add the item:
size++ ;
if (isEmpty( )) {
I am trying to Implement a Linked List Using Java.
The code I have used is as follow
public class LinkNode
{
private int data;
public LinkNode next;
public LinkNode (int data)
{
this.data = data;
}
public void setData(int data)
{
this.data = data;
}
public int getData()
{
return this.data;
}
public void setNext(LinkNode next)
{
this.next = next;
}
public LinkNode getNext()
{
return this.next;
}
public static void main (String [] args)
{
LinkNode Node1 = new LinkNode(3);
LinkNode Head = Node1;
LinkNode Node2 = new LinkNode(4);
LinkNode Node3 = new LinkNode(5);
LinkNode Node4 = new LinkNode(6);
Head.setNext(Node1);
Node1.setNext(Node2);
Node2.setNext(Node3);
Node3.setNext(Node4);
int iCounter =0;
LinkNode currentNode= Head;
while (currentNode.getNext()!=null)
{
int data = currentNode.getData();
System.out.println(data);
currentNode = currentNode.getNext();
iCounter=iCounter+1;
}
System.out.println("No Of Nodes are"+iCounter);
}
}
The Problem here I am getting No of Nodes 3
The code is not counting the last Node that is Node4.
The out put is as follow
3
4
5
No Of Nodes are3
Please let me know what is the problem in the code.
To make Head point to Node1 write
Head = Node1;
If you write Head=null it means that Head doesn't point to any node, and you get a null pointer exception because you then try to get the next node from a node that doesn't exist.
The second problem is that you exit the loop when currentNode.getNext() returns null. The getNext() method returns null when you have reached the last node of the list; if you exit the loop then you won't count the last node. Change the loop condition into:
while (currentNode != null)
And please don't edit the question to ask followup questions. Nobody is notified when a question is edited, so you won't get new answers. It also makes the site less useful for future visitors. Post a new "question" for each question that you have.
Head, should not be null. Instead the data in head should be null, otherwise you have no way to find next.
Here is implementation of Singly Linked List I've developed years ago:
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* #author sergiizagriichuk
*/
public class Node<T> {
private T value;
private Node<T> next;
public Node(T value) {
this.value = value;
}
public static <T> Node<T> createLinkedListFromArray(T... array) {
if (checkIfArrayIsNullOrEmpty(array)) return new Node<T>(null);
Node<T> head = new Node<T>(array[0]);
createLinkedList(array, head);
return head;
}
private static <T> boolean checkIfArrayIsNullOrEmpty(T[] array) {
return array == null || array.length == 0;
}
private static <T> void createLinkedList(T[] array, Node<T> head) {
Node<T> node = head;
for (int index = 1; index < array.length; index++) {
T t = array[index];
node.setNext(new Node<T>(t));
node = node.getNext();
}
}
public T getValue() {
return value;
}
public void setValue(T value) {
this.value = value;
}
public Node<T> getNext() {
return next;
}
public void setNext(Node<T> next) {
this.next = next;
}
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Node node = (Node) o;
return value != null && value.equals(node.value);
}
#Override
public int hashCode() {
return value.hashCode();
}
#Override
public String toString() {
List ret = createList();
return Arrays.toString(ret.toArray());
}
private List createList() {
Node root = this;
List ret = new ArrayList();
while (root != null) {
ret.add(root.getValue());
root = root.getNext();
}
return ret;
}
}
And some Tests:
/**
* #author sergiizagriichuk
*/
public class NodeTest {
#Test
public void testCreateList() throws Exception {
Node<Integer> node = Node.createLinkedListFromArray(1, 2, 3, 4, 5);
Assert.assertEquals(Integer.valueOf(1), node.getValue());
Assert.assertEquals(Integer.valueOf(2), node.getNext().getValue());
}
#Test
public void testCreateListSize() throws Exception {
Integer[] values = new Integer[]{1, 2, 3, 4, 5};
int size = values.length - 1;
Node<Integer> node = Node.createLinkedListFromArray(values);
int count = 0;
while (node.getNext() != null) {
count++;
node = node.getNext();
}
Assert.assertEquals(size, count);
}
#Test
public void testNullNode() throws Exception {
Node<Integer> nullNode = new Node<Integer>(null);
assertNullNode(nullNode);
}
#Test
public void testNullArray() throws Exception {
Node<Integer> nullArrayNode = Node.createLinkedListFromArray();
assertNullNode(nullArrayNode);
}
#Test
public void testSetValue() throws Exception {
Node<Integer> node = new Node<Integer>(null);
assertNullNode(node);
node.setValue(1);
Assert.assertEquals(Integer.valueOf(1), node.getValue());
}
private void assertNullNode(Node<Integer> nullNode) {
Assert.assertNotNull(nullNode);
Assert.assertNull(nullNode.getValue());
}
}
Try to use or redevelop for your situation
Hey, so I wanted to insert one data after the input data (not index).
I've tried but it always at the end, the data that i want to insert end up at the dront of the link list..
**public static void insertAfter(Object o,Object c){
Node newN = new Node();
Node help = new Node();
Node help2 = new Node();
newN.data = o;
help = head.next;
if(isEmpty()){
head = newN;
newN.next=head;
newN.prev=head;
}
else{
do{
help=help.next;
System.out.println(help);
}while(help.next!=head || !help.data.equals(c));
help2 = help.next;
newN.next = help2;
help2.prev = newN;
help.next=newN;
newN.prev=help;
}**
anyone could help?
thx a bunch!
What are the objects that you are comparing? if they are something other than string than you will have to override equals() method in order to get the correct comparison.
I think you should try another ending condition:
while(help.next!=head && !help.data.equals(c));
By the way, I can only advise you to avoid do...while without serious reasons, and to use getters and setters.
Your code should also be structured diffently. Why are you not writing a private method which just make the insert, i.e. your 5 last lines? Everything would be more readable and reusable.
Also, your variables need clear and meaningful names.
Do it yourself
I begun fixing your solution but ended writing a whole new implementation when wanting to test it... so here goes:
public class DoubleLinkedList<T> {
private class Node {
private Node prev;
private Node next;
private T data;
Node(T data) {
this.data = data;
}
}
Node head;
public boolean isEmpty() {
return head == null;
}
public void insertAfter(T afterThis, T objectToAdd) {
// cannot insert after in a empty list?!
if(isEmpty())
throw new NoSuchElementException("list is empty?");
// find the node where we want to insert the element
Node after = findNodeByObject(afterThis);
// create the node and update the links
addAfter(after, new Node(objectToAdd));
}
private void add(T objectToAdd) {
if (isEmpty()) {
head = new Node(objectToAdd);
head.next = head;
head.prev = head;
}
else {
addAfter(head.prev, new Node(objectToAdd));
}
}
private void addAfter(Node after, Node toAdd) {
Node afterAfter = after.next;
after.next = toAdd;
afterAfter.prev = toAdd;
toAdd.prev = after;
toAdd.next = afterAfter;
}
private Node findNodeByObject(T object) {
Node current = head;
while (true) {
if (current.data.equals(object))
return current;
if (current.next == head)
break;
current = current.next;
}
throw new NoSuchElementException("" + object);
}
#Override
public String toString() {
List<T> printList = new LinkedList<T>();
Node current = head;
while (true) {
printList.add(current.data);
if (current.next == head)
break;
current = current.next;
}
return printList.toString();
}
public static void main(String[] args) throws Exception {
DoubleLinkedList<String> list = new DoubleLinkedList<String>();
list.add("first");
list.add("third");
list.insertAfter("first", "second");
System.out.println(list);
}
}
Extend LinkedList
... and add the insertAfter method like this:
import java.util.LinkedList;
import java.util.ListIterator;
public class MyList<T> extends LinkedList<T> {
private void insertAfter(T first, T second) {
ListIterator<T> iterator = listIterator();
while (iterator.hasNext()) {
if (iterator.next().equals(first)) {
iterator.add(second);
return;
}
}
throw new IndexOutOfBoundsException("Could not find " + first);
}
public static void main(String[] args) throws Exception {
MyList<String> list = new MyList<String>();
list.add("first");
list.add("third");
list.insertAfter("first", "second");
System.out.println(list); // prints "[first, second, third]"
}
}