Method utilising linked list not working - java

The display method is my program is not displaying anything at all.
The program has to have someone entire names into a circular linked list, then backup the linked list into another circular linked list.
Then it user must delete names until 1 is left, and the display the winner along with the list of original names, using the backup in the order that they were entered
import java.io.*;
import java.util.*;
import java.text.*;
public class Linkedlist
{
static public class Node
{
Node prev, next;
String data;
}
public static void delete (Node tail) throws IOException
{
BufferedReader stdin = new BufferedReader (new InputStreamReader (System.in));
System.out.println ("Please input a name to be deleted");
String tobedeleted = stdin.readLine ();
Node delete = tail;
while (delete.prev != null)
{
if (delete.data.equals (tobedeleted))
{
String temp = delete.data;
delete.data = tail.data;
tail.data = temp;
tail = tail.prev;
}
delete = delete.prev;
}
}
public static String findvictor (Node tail) throws IOException
{
int size = 0;
for (Node n = tail ; n.prev != null ; n = n.prev)
{
size++;
}
if (size == 1)
{
return tail.data;
}
else
{
delete (tail);
return findvictor (tail.prev);
}
}
public static void backup (Node tail, Node backuptail)
{
Node tobebackuped = tail;
Node backuphead = null;
Node backup = new Node ();
backuptail = backup;
while (tobebackuped.prev != null)
{
backup.data = tobebackuped.data;
backuphead = backup;
backup = new Node ();
backup.next = backuphead;
backuphead.prev = backup;
tobebackuped = tobebackuped.prev;
}
}
public static void display (Node tail, Node backuptail) throws IOException
{
System.out.println ("CONGRATULATIONS, " + findvictor (tail) + ", YOU ARE THE WINNER!");
System.out.println ("");
System.out.println ("This is a list of all the contestants:");
Node current = backuptail;
while (current.prev != null)
{
System.out.println (current.data);
current = current.prev;
}
}
public static void main (String[] args) throws IOException
{
BufferedReader stdin = new BufferedReader (new InputStreamReader (System.in));
Node head = null;
Node node = new Node ();
Node tail = node;
while (true)
{
String str = stdin.readLine ();
if (!str.equals ("fin"))
{
node.data = str;
head = node;
node = new Node ();
node.next = head;
head.prev = node;
}
else
{
break;
}
}
Node backuptail = null;
backup (tail, backuptail);
display (tail, backuptail);
}
}

You've fallen into a simple trap in Java. You've passed a value that you want to update into a function, and expected the value to be updated in the calling method. Right here:
Node backuptail = null;
backup (tail, backuptail);
display (tail, backuptail);
Here's what's happening: Java is passing your pointer by value. That means it's creating a copy of your pointer (backuptail) for use within the method backup(). That means your local variable in main() never gets updated.
The fix is simple. Change your backup method to return the value instead:
public static Node backup (Node tail)
{
Node tobebackuped = tail;
Node backuphead = null;
Node backup = new Node ();
Node backuptail = backup;
while (tobebackuped.prev != null)
{
backup.data = tobebackuped.data;
backuphead = backup;
backup = new Node ();
backup.next = backuphead;
backuphead.prev = backup;
tobebackuped = tobebackuped.prev;
}
return backuptail;
}
Then change your method calls apropriately:
Node backuptail = backup (tail);
display (tail, backuptail);
Now the resulting backup pointer is stored locally within your main, and can be passed to display().

Related

Insert after specific element in LinkedList java

I was trying to write the function insertAfter to insert the element after specific element in the LinkedList . Below is the code. The insertAfter function is not producing the desired output. Can some one help me what mistake I have done in the below insertAfter function that I need to correct.
import java.util.Scanner;
import java.lang.Exception;
import java.lang.StringBuilder;
import java.util.ArrayList;
import java.util.*;
import java.util.regex.*;
import java.util.stream.Collectors;
class SingleLinkedList<T>
{
public class Node
{
public T data;
public Node nextNode;
}
public Node headNode;
public int size;
public SingleLinkedList()
{
headNode = null;
size = 0;
}
public boolean isEmpty()
{
if (headNode == null)
{
return true;
}
return false;
}
public void insertAtHead(T data)
{
Node node = new Node();
node.data = data;
node.nextNode = headNode;
headNode = node;
size++;
}
public void insertAtEnd(T data)
{
if (isEmpty())
{
insertAtHead(data);
return;
}
Node newNode = new Node();
newNode.data = data;
newNode.nextNode = null;
Node last = headNode;
while (last.nextNode != null)
{
last = last.nextNode;
}
last.nextNode = newNode;
size++;
}
public void insertAfter(T data1, T data2)
{
if (isEmpty())
{
System.out.println("The list is empty");
return;
}
Node insertNode = new Node();
insertNode.data = data2;
Node temp = headNode;
while (temp.data != data1)
{
temp = temp.nextNode;
}
insertNode.nextNode = temp;
temp = insertNode;
size++;
}
public void printList()
{
if (isEmpty())
{
System.out.println("The list is empty.");
return;
}
Node temp = headNode;
System.out.println("List : ");
while (temp.nextNode != null)
{
System.out.print(temp.data.toString() + "->");
temp = temp.nextNode;
}
System.out.println(" null");
}
}
public class Solution
{
//static String originalString="AbcDef";
// arguments are passed using the text field below this editor
public static void main(String[] args)
{
SingleLinkedList<Integer> sll = new SingleLinkedList<>();
sll.printList();
for (int i = 0; i <= 10; i++)
{
sll.insertAtEnd(i);
}
sll.printList();
System.out.println("The size of the list is : " + sll.size);
sll.insertAfter(3,72);
sll.printList();
System.out.println("The new size of the list is : " + sll.size);
}
}
In the insertAfter function I create a temp Node and assign the headNode address. Then I create a while loop and traverse the list until I reach the data element after which I need to insert and update the nextNode address in temp Node. Once the loop breaks I update the new Node next address to the temp Node and update the temp node address with the address of the new Node. It seems correct to me but code provides below output.
The list is empty.
List :
0->1->2->3->4->5->6->7->8->9-> null
The size of the list is : 11
List :
0->1->2->3->4->5->6->7->8->9-> null
The new size of the list is : 12
Your logic for insertAfter is not correct. Your while loop exits when it encounters a node with the same value as data1. Then, you need to point the new node to the next value of the node containing data1, and point the node containing data1 to the newly added node with the value of data2. Adding this would fix the bug.
insertNode.nextNode = temp.nextNode;
temp.nextNode = insertNode;
The new output would be something like this:
0->1->2->3->72->4->5->6->7->8->9-> null
Just to answer your second query, yes you can implement insertBefore in a singly linked list using a pointer which points to the previous node in addition to the one pointing to the current node. Here's how it looks. Please note that error handling is omitted for simplicity's sake.
public void insertBefore(T data1, T data2) {
Node p = null;
Node curr = headNode;
while (curr.data != data1) {
p = curr;
curr = curr.nextNode;
}
Node insertNode = new Node();
insertNode.data = data2;
p.nextNode = insertNode;
insertNode.nextNode = curr;
size = size + 1;
}
If you want to insert after the data1 your error is here(insertAfter method):
insertNode.nextNode = temp;
temp = insertNode;
So this is the right code:
Node next = temp.nextNode;
temp.nextNode = insertNode;
insertNode.nextNode = next;

Determine the Object (book) that appears first alphabetically

I was tasked with creating my own linked list class, using a book class i made. One of the questions was to Determine the book that appears first alphabetically.
i was able to sort the Linked list alphabetically using bubble sort(i know its not efficient but im still new) here is the code.
public void alphaBubbleSort() {
int size = size();
if (size > 1) {
boolean wasChanged;
do {
Node current = head;
Node previous = null;
Node next = head.next;
wasChanged = false;
while (next != null) {
if (current.book.getName().compareToIgnoreCase(next.book.getName()) > 0) {
wasChanged = true;
if (previous != null) {
Node sig = next.next;
previous.next = next;
next.next = current;
current.next = sig;
} else {
Node temp = next.next;
head = next;
next.next = current;
current.next = temp;
}
previous = next;
next = current.next;
} else {
previous = current;
current = next;
next = next.next;
}
}
} while (wasChanged);
}
}
my problem is i only want the front node and i do not want to alter the linked list order. i tried to do this in my main.
Linky tempLinky = new Linky(); // create temp linked list
tempLinky = linky; // copy temp main linked list to temp
tempLinky.alphaBubbleSort(); // sort temp list
System.out.println(tempLinky.peek());// return object in first node
This did not seem to work. Ive tried some other code that does not work, so ive come here as a last resort.
If you need to find the first book alphabetically, there's no need to sort the entire list (and, as you commented, you don't want to alter the list's order anyway).
Instead, you could iterate over the list and keep the "first" object as you go:
public Book getFirstAlphabetically() {
Node current = head;
Book retVal = head.book;
while (current != null) {
if (current.book.getName().compareToIgnoreCase(retVal.getName()) < 0) {
retVal = current.book;
}
current = current.next;
}
return retVal;
}
Here's an example:
import java.util.Random;
class Book {
String title;
Book(String title){this.title = title;}
}
class Node {
Book b; Node next;
Node(Book b){this.b = b;}
}
public class Main {
static Book least(Node head){
if (head == null) return null;
Book least = head.b;
for(Node n=head.next; n.next!=null; n=n.next)
least = least.title.compareTo(n.b.title) > 0 ? n.b : least;
return least;
}
static void print(Node head){
for(Node n=head; n.next!=null; n=n.next)
System.out.println(n.b.title);
}
static String randString(){
Random r = new Random();
int len = r.nextInt(20)+1;
char[] chars = new char[len];
for(int i=0; i<chars.length; i++)
chars[i]= (char) (r.nextInt(26)+97);
return new String(chars);
}
public static void main(String[] args) {
Node head = new Node(new Book(randString()));
Node next = head;
for(int i = 0; i<20; i++)
next = next.next = new Node(new Book(randString()));
print(head);
System.out.println("==========");
System.out.println(least(head).title);
}
}

Linked list is only displaying the head node, not sure why

I am doing a linked list project for my class at school. Essentially we are supposed to make a linked list from scratch, and have add, delete, and find commands. No matter how hard I've been trying I cannot seem to get the list to display anything other than the head node. here are my classes starting from node
public class main {
public static void main(String args[]) {
for (int i = 0; i < 3; i++) {
LinkedList list = new LinkedList();
Node focus = new Node();
String start;
start = JOptionPane.showInputDialog("Enter 'A' to add an item"
+ "\n" + "Enter 'D' to delete an item\nEnter 'F' to find an item.");
if (start.equals("a") || start.equals("A")) {
focus.data = JOptionPane.showInputDialog("enter an item to ADD");
list.Add(focus);
while (focus != null) {
focus = list.head;
focus = focus.next;
JOptionPane.showMessageDialog(null, "your list is\n" + focus.getData());
}
}
}
}
}
public class Node {
String data;
Node next;
Node prev;
public Node(String data, Node next) {
this.data = data;
this.next = next;
}
Node() {
}
public void setData(String data) {
this.data = data;
}
public String getData() {
return this.data;
}
public void setNext(Node next) {//setnext
this.next = next;
}
public Node getNext() {
return next;
}
}
public class LinkedList extends Node {
Node head;
int listcount = 0;
public LinkedList() {
this.prev = null;
this.next = null;
this.listcount = 0;
}
LinkedList(Node Set) {
}
public void Add(Node n) {
Node current = this.prev;
if (current != null) {
current = this.prev;
this.prev = new Node();
} else {
head = this.prev = new Node();
current = head;
}
listcount++;
}
}
I think my biggest problem is the "your list is" part. I can't seem to get it to display anything other than the head node. I would really appreciate the help, as this has been giving me a huge headache. :)
First of all, why does your LinkedList extends the Node class? It's a linked list not a node. There's nothing coming before and after the linked list. So the linked list has no prev and next. All the elements are added in the list and the elements are inserted after the head node. The head of the node has a prev and a next. In the Add method, if the head of the list is null (i.e, the list is empty), the new element becomes the head of the list. Otherwise, the new node is inserted after the head.
public class LinkedList {
Node head;
int listcount = 0;
public LinkedList() {
this.head = null;
this.listcount = 0;
}
public void Add(Node n) {
Node current = this.head;
if (current == null) {
head = n;
} else {
Node prev = null;
while (current != null) {
prev = current;
current = current.next;
}
prev.next = n;
}
listcount++;
}
public String toString() {
StringBuilder builder = new StringBuilder();
Node current = this.head;
while (current != null) {
builder.append(current.data).append(", ");
current = current.next;
}
return builder.toString();
}
}
I added a toString method which loops over the list and builds a string with the content from each node.
In the main method there are a few problems. The linked list is initialised only once not every time you select a choice. If you initialise the linked list every time you select something, then the linked list will always be reinitialised and the only node that will contain will be the head node after you add the new element.
public class main {
public static void main(String args[]) {
String start;
boolean finished=false;
LinkedList list = new LinkedList();
while(!finished) {
start = JOptionPane.showInputDialog("Enter 'A' to add an item"
+ "\n" + "Enter 'D' to delete an item\nEnter 'F' to find an item.");
if (start.equals("a") || start.equals("A")) {
Node focus = new Node();
focus.data = JOptionPane.showInputDialog("enter an item to ADD");
list.Add(focus);
JOptionPane.showMessageDialog(null, "your list is\n" + list.toString());
}
else {
finished = true;
}
}
}
}
Try to go over the code and understand what is happening and why. Also use pencil and paper to understand the logic.

Adding nodes to end of linked list

Having trouble adding nodes to the end of a linked
The code is pretty self explanatory, the addToEnd method adds a single node to the end of a linkedlist.
public class ll5 {
// Private inner class Node
private class Node{
int data;
Node link;
public Node(int x, Node p){
data = x;
link = p;
}
}
// End of Node class
public Node head;
public ll5(){
head = null;
}
public void addToEnd(int data) {
Node p = head;
while (p.link != null)
p=p.link;
p.link=new Node(data, null);
}
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
ll5 list = new ll5();
list.printList();
System.out.println("How many values do you want to add to the list");
int toAdd = input.nextInt();
for(int i = 0; i < toAdd; i++) {
System.out.println("Enter value " + (i + 1));
list.addToEnd(input.nextInt());
}
System.out.println("The list is:");
list.printList();
input.close();
}
}
Why is it giving me an NullPointerException error?? The error is somewhere in the while loop in the addToEnd method.
You haven't handled the initial condition when list has nothing and head is null. Because of that you're getting NPE.
Following method should work.
public void addToEnd(int data) {
Node p = head;
if( p == null) {
head = new Node(data, null);
} else {
while (p.link != null)
p=p.link;
p.link=new Node(data, null);
}
}
That's because the head is null at the beginning
public ll5(){
head = null; // <-- head is null
}
public void addToEnd(int data) {
Node p = head; //<-- you assigned head, which is null, to p
while (p.link != null) //<-- p is null, p.link causes NullException
p=p.link;
p.link=new Node(data, null);
}

Append two linked list

I wrote a simple method to append a linked list at the end of another linked list.So what the program should ideally do is when I give it two lists
list1 ===>1->2->3
list2 ===>4->5->6
updatedList ==>1->2->3->4->5->6
But when I run the method appendList it goes into an infinite loop printing 1 to 6 indefinitely.What am I doing wrong out here?
public static Node appendList(Node head1, Node head2) {
Node prev = null;
Node current = head1;
while (current != null) {
prev = current;
current = current.next;
}
prev.next = head2;
return head1;
}
Oh and I forgot to add the Node class and how I call the method from my main .I know its bit cumbersome but here it is
public class ReverseLinkedList {
class Node {
int data;
Node next;
Node(int data) {
this.data = data;
}
public void displayData() {
System.out.println(data);
}
}
public static void main(String args[]) {
ReverseLinkedList reversedList = new ReverseLinkedList();
Scanner scanner = new Scanner(System.in);
System.out.println("Enter the length of the linked list!!");
int listSize = scanner.nextInt();
System.out.println("Enter the Numbers you want to insert!!");
int count = 0;
while (scanner.hasNextLine()) {
if (count == listSize)
break;
reversedList.insert(scanner.nextInt());
count++;
}
System.out.println("Inserted List !!");
reversedList.displayList();
/*
* Node reverseNodeStart =
* reversedList.reverseList1(reversedList.first);
* System.out.println("Reversed List !!"); while (reverseNodeStart !=
* null) { reverseNodeStart.displayData(); reverseNodeStart =
* reverseNodeStart.next; }
*/
Node reverseNodeStart = reversedList.appendList(reversedList.first,
reversedList.first);
while (reverseNodeStart != null) {
reverseNodeStart.displayData();
reverseNodeStart = reverseNodeStart.next;
}
}
}
The problem was I was using the same List which was causing the circular reference.It works fine now.You knew the problem even before I posted the code now that's impressive. Thanks!!I solved it by creating a new List2 and passing in List1 and List2.
appendList(Node lis1head, Node list2head)

Categories

Resources