Finding the right place and storing in LinkedList - java

I am trying to store the strings in a LinkedList. I am not allowed to pre-sort, but find the place and pass the string to the linked list. When i pass the strings through text file, the string do not go through the last else condition.
My input file has
joe
appy
appz
zebra
cat
When it reaches appz, it doesn't go through any statement. It is supposed to insert the last else condition and print 5, but doesn't do that.
/**
* Gets the string and arranges them in order
* #param newString
*/
public void store(String newString) {
LinkedListNode current = head;
System.out.println(newString);
// if no element in the list
if (current==null){
System.out.println("1");
makeNode(newString);
}
// if only 1 elements in the list
else if(current.getNext()==null ){
System.out.println("2");
if(newString.compareTo(current.getName())<0){
insertBefore(current.getName(),newString);
} else{
insertAfter(current.getName(),newString);
}
}
// if the element is smaller than the head in the list
else if(newString.compareTo(current.getName()) < 0){
System.out.println("3");
LinkedListNode temp = makeNode(newString);
temp.setNext(current);
head=temp;
}
// if the element is greater than the tail in the list
else if(newString.compareTo(findTail().getName()) > 0){
System.out.println("4");
insertAfter(findTail().getName(),newString);
}
// for more than two elements in the list
else{
System.out.println("5");
while(!(newString.compareTo(current.getName())>0 && newString.compareTo(current.getNext().getName())<0 ) && current.getNext()!=null){
current=current.getNext();
}
if(newString.compareTo(current.getName())<0){
insertBefore(current.getName(),newString);
}
else{
insertAfter(current.getName(),newString);
}
}
} // end of store()

You have some issue with the insertBefore. I updated it.
public void insertBefore(String later, String name){
if(head==null){
head = new LinkedListNode(name,null);
}
else if(head.getName()==later){
LinkedListNode newNode = makeNode(name);
newNode.setNext(head);
head=newNode;
}
else{
LinkedListNode current = head;
while(current.getNext().getName()!=later){
current=current.getNext();
}
LinkedListNode newNode = makeNode(name); // create the new node
newNode.setNext(current.getNext());
current.setNext(newNode);
}
} // end of insertBefore()

When you are traversing, you are not supposed to change the head reference. To traverse, simply do this:
Node tmp = head;
while(tmp != null) tmp = tmp.next;
This will become very handy to figure out where to insert new nodes or where to go to remove existing nodes.
Your class should also have methods to addFirst, addLast, insertBefore, insertAfter. In the code below, Object is whatever data type your need (in your case, String)
public void addLast(Object item)
{
if(head == null)
{
addFirst(item);
}
else
{
Node<Object> tmp = head;
while(tmp.next != null)
{
tmp = tmp.next;
}
tmp.next = new Node<Object>(item, null);
}
}
public void addFirst(Object item)
{
head = new Node<Object>(item, head);
}
public void insertAfter(Object key, Object item)
{
Node<Object> tmp = head;
while(tmp != null && !tmp.data.equals(key))
{
tmp = tmp.next;
}
if(tmp != null)
{
tmp.next = new Node<Object>(item, tmp.next);
}
}
public void insertBefore(Object key, Object item)
{
if(head == null)
{
return null;
}
if(head.data.equals(key))
{
addFirst(item);
return;
}
Node<Object> previous = null;
Node<Object> current = head;
while(current != null && !current.data.equals(key))
{
previous = current;
current = current.next;
}
//insert between current and previous
if(current != null)
{
previous.next = new Node<Object>(item, current);
}
}
In my opinion, you should not have a nested if/else construct to figure out where to insert. That should be up to the method you are invoking.
Secondly, the conditions you are using to control the flow of execution in your code are disparate. Your IF condition is if the list is empty. If it is, create a new node and add it to the list. That condition is followed by checking for a list containing only one node. After that, you are not checking for the length of the list. The expected logic is that you should be checking for a list size greater than one; and yet this is your fall through case (the last else). If you are going to be doing that kind of check outside the insert methods, then do something like this (stubbing your code):
if (current==null){
System.out.println("1");
makeNode(newString);
}
// if only 1 elements in the list
else if(current.getNext()==null ){
System.out.println("2");
if(newString.compareTo(current.getName())<0){
insertBefore(current.getName(),newString);
} else{
insertAfter(current.getName(),newString);
}
}
// if the list has more than one element
else
{
// figure out where it goes (before or after) and insert
}
If you notice, the else/if and else blocks do basically the same thing. Therefore, your code can (and should) be simplified as follows:
if (current==null){
System.out.println("1");
makeNode(newString);
}
// if the list has one or more elements
else
{
// figure out where it goes (before or after) and insert
}

Related

How can I get my next pointer of my LinkedList class without using built in function?

I'm newbie in programming and I'm practicing a Java Programming Language. I was having a rough day in finding the solution of my program because I cannot get my "next" pointer and I really want to print my last value. Could someone help me to fix this and explain to me? Thank you in advance. Here's my code.
Note: The output of my program is 5.
public class Node {
private int data;
private Node next;
public Node (int data){
this.data = data;
}
public int getData() {
return this.data;
}
public void setNext(Node n) {
this.next = n;
}
public Node getNext() {
return this.next;
}
}
public class LinkedList {
private static Node head, next;
public LinkedList (int data) {
head = new Node (data);
}
public void addLast(int data) {
Node n = new Node (data);
if (head == null) {
head = n;
}
else {
Node temp = head;
temp.setNext(next);
while (temp.getNext() != null) {
temp = temp.getNext();
}
Node t = temp.getNext();
t = n;
}
}
public void printList() {
head.setNext(next);
while (head.getNext() != null) {
System.out.println(head.getData());
head = head.getNext();
}
System.out.println(head.getData());
}
public static void main(String[] args) {
LinkedList l = new LinkedList(5);
l.addLast(7);
l.printList();
}
}
I suggest following two amendment to your code.
with following else block in addLast method.
Node temp = head;
temp.setNext(next); // this line causing the next object to be set to null all the time. commenting this line will help in making sure the follwing loop reaches to end of the list, otherwise the while loop will always exit without any iteration.
while (temp.getNext() != null) {
temp = temp.getNext();
}
Node t = temp.getNext();
t = n; // this will also not change the linking. Its basically assigned a new value to t.
use following suggestion
Node temp = head;
while (temp.getNext() != null) {
temp = temp.getNext();
}
// now we reached end of list and temp.next is null.
// assign newly createdd node to temp.next
temp.setNext(n);
While iterating the element in printList same problem exist as mentioned in point 1. try to use following suggestion for printList method.
// head.setNext(next); // This line will always set head.next to null and whole list will be lost. Instead of this use following line
Node temp = head;
while (temp.getNext() != null) { // here if you use head its position will move to end. So use temp variable for iteration
System.out.println(temp.getData());
temp= temp.getNext();
}
System.out.println(temp.getData());
You may also need to study list iteration algorithm to have better understanding.
I've made some amendments to make your code work. The If statement in your addLast method:
if (head == null) {
is redundant since your LinkedList can only be initialized by passing some data, hence head will never be null, it will always point to the Node containing data
Also the line
head.setNext(next);
in your printList() was problematic, it was always pointing to null
public class LinkedList {
private static Node head, next;
public LinkedList(int data) {
head = new Node(data);
}
public void addLast(int data) {
Node n = new Node(data);
Node temp = head;
temp.setNext(next);
while (temp.getNext() != null) {
temp = temp.getNext();
}
temp.setNext(n);
}
public void printList() {
while (head.getNext() != null) {
System.out.println(head.getData());
head = head.getNext();
}
System.out.println(head.getData());
}
public static void main(String[] args) {
LinkedList l = new LinkedList(5);
l.addLast(7);
l.printList();
}
}
TL;DR:
You set null as the next node in your printList() method;
Your addLast does not work either (you do not set the next node (see details below);
You should never set the node (or do any logical alteration whatsoever) in your print method. Print must just print, as the name suggests, and it should not contain any side-effect, amending your data structure. That is: you have to clearly separate your concerns.
In your current addLast, you do:
public void addLast(int data) {
Node n = new Node (data);
if (head == null) {
head = n;
}
else {
Node temp = head;
temp.setNext(next);
while (temp.getNext() != null) {
temp = temp.getNext();
}
Node t = temp.getNext();
t = n;
}
}
which means, that when your temp's next node is null, you never add the Node you instantiate with your int argument.
Change the else block as follows:
else {
Node temp = head;
temp.setNext(next);
while (temp.getNext() != null) {
temp = temp.getNext();
}
temp.setNext(n);
//two redundant lines removed
}
Correspondingly, remove head.setNext(next); (and possibly unnecessary System.out.println() statement) from your printList() method.
P. S. I would really recommend you to spend some time on the Linked List Data Structure (Data Structure, and not the Java code), as your current design, shows that you need to have a better grasp of it.

queue implementation does not return first element

I want to emulate a queue by using linked lists in Java. My general schema is to have a list of nodes, with two nodes that points to the first and last element of my queue. When I perform the dequeue() I want to get ride of the first element. So far what I have done is the following:
public class Node {
public Object e;
Node next;
public Node(Object e) {
this.e = e;
}
}
public class Queue {
Node queueList;
Node first, last;
int count;
public void enQueue(Object n) {
Node temp = new Node(n);
temp.next = last;
last = temp;
if (queueList == null) {
first = temp;
}
count++;
queueList=temp;
}
public Object deQueue() {
Node previous = last;
Node current = last.next;
Object num = null;
if (count == 0)
System.out.println("empty queue");
else {
while (current.next != null) {
previous = previous.next;
current = current.next;
}
num = first.e;
first = previous;
count--;
}
return num;
}
public void print() {
Node current = last;
while (current != null) {
System.out.println(current.e);
current = current.next;
}
}
}
I do not want to use double linked lists, so for the dequeue() operation what I do is to traverse my list with two pointers like this:
So when the current.next points to a null, I want that previous to be the first node. The problem that I got is when I print the elements of my queue it stills prints me: 10,15,5,18, but the 18 value is not deleted. Any help?
Thanks
There are basically two things I would correct in your code.
First of all, the Queue field was not assigned any value, and I also doubt its utility, basically its logic can be applied using first
public void enQueue(Object n) {
Node temp = new Node(n);
temp.next = last;
last = temp;
if (first == null) { <--- HERE
first = temp;
}
count++;
}
The second one is that you never put the value of the new head of the queue next to null which is needed in that case
public Object deQueue() {
Node previous = last;
Node current = last.next;
Object num = null;
if (count == 0) System.out.println("empty queue");
else {
while (current.next != null) {
previous = previous.next;
current = current.next;
}
num = first.e;
first = previous;
first.next = null; <--- HERE
count--;
}
return num;
}

Construct a no recursive insert method for binary tree

I have completed the recursive insert function and it works perfectly, but I can not get the non recursive solution to work.
public void insert(T item){
root= nonRecursive(root,item);
}
public BinaryTreeNode<T> nonRecursive(BinaryTreeNode<T> tree, T item){
if(root==null){
root=new BinaryTreeNode<T>(item);
return root;
}
else{
BinaryTreeNode<T> next = new BinaryTreeNode<T>();
Comparable<T> temp = (Comparable<T>) root.info;
if(temp.compareTo(item)== 0){
return null;
}
else if(temp.compareTo(item) > 0){
next=root.lLink;
}
else{
next=root.rLink;
}
while(next != null){
Comparable<T> temp2 = (Comparable<T>) next.info;
if(temp.compareTo(item) == 0){
return null;
}
else if(temp2.compareTo(item) > 0){
next=next.lLink;
}
else{
next=next.rLink;
}
}
next=new BinaryTreeNode<T>(item);
return root;
}
}
and then the recursive one is:
public void insert(T item) {
root = recInsert(root, item);
}
public BinaryTreeNode<T> recInsert(BinaryTreeNode<T> tree, T item) {
if(tree == null) {
//create new node
tree = new BinaryTreeNode<T>(item);
}
else {
Comparable<T> temp = (Comparable<T>) tree.info;
if (temp.compareTo(item) == 0) {
System.err.print("Already in ­ duplicates are not allowed.");
return null;
}
else if (temp.compareTo(item) > 0)
tree.lLink = recInsert(tree.lLink, item);
else
tree.rLink = recInsert(tree.rLink, item);
}
return tree;
}
does anyone know what I am doing wrong?
I thought I had gotten it but now it only returns the first number I enter in
here you go then
in your code,
if(current == null){
current.lLink=node;
if current is null, then how can it have a iLink ?
maybe you need to do
if(current == null){
current = new Node ();
current.lLink=node;
Your code is not even close to finish.
You haven't even done one comparison. What you did is simply meaningless loops.
If you are looking for a non-recursive logic, here is the pseudo code. Your job is to understand it and write it in Java.
insert(item) {
Node itemNode = new Node(item);
if root is null {
root = itemNode
return
}
currentNode = root;
keep looping until node is inserted {
if currentNode is equals to itemNode {
show error and exit
} else if itemNode is smaller than currentNode {
if (currentNode has no left){
set currentNode's left to itemNode
// Item Inserted!!!!
} else { // there are node at currentNode's left
set currentNode to currentNode's left (and continue lookup)
}
} else { // item node is greater than current node
// do similar thing as the "itemNode < currentNode logic",
// of course on currentNode's right
}
}
}

Removing the end node from a linked list

What am I missing to allow me to remove a node(boxcar) to the end of my linked list?
public void removeBoxcarFromEnd() {
Boxcar prevcar = head;
Boxcar nextcar = head;
if (head.next == null) {
int result = head.data;
head = null;
return result;
}
else {
while (nextcar.next() > 2)
prevcar = nextcar;
nextcar = nextcar.next();
}
prevcar.setNext(null);
size--;
}
There are a few problems with this approach:
you're method is a void whereas you want to return the data of the last item?
your while loop doesn't use brackets ({}) nor indentation, therefore only prevcar = nextcar will be executed an infinite amount of times.
you use >2;
there is a cornercase where the linked list can be empty as well.
A probably better way to handle this:
public String removeBoxcarFromEnd() {
String result;
if(head == null) { //empty list
return null; //or do something else? throw an exception?
} else if (head.next() == null) { //one element, remove it
int result = head.data();
head = null;
}
else { //more elements
Boxcar prevcar = head, nextcar = head.next(), ffcar = nextcar.next();
while (ffcar != null) { //double next iteration
prevcar = nextcar;
nextcar = ffcar;
ffcar = ffcar.next();
}
int result = nextcar.data(); //get result
prevcar.setNext(null); //remove it from the linked list
}
size--;
return result;
}
Assuming you don't need to fetch data, only remove the last Boxcar:
public void removeBoxcarFromEnd() {
Boxcar prevcar = head;
Boxcar nextcar = head;
if (head == null || head.next() == null) {
return;
}
while (nextcar.next() != null) {
prevcar = nextcar;
nextcar = nextcar.next();
}
prevcar.setNext(null);
}
First we check for a null or one-element list; in those cases, there's nothing to do.
Next we walk the list until we get to the end (i.e. nextCar.next() returns null). At each step, we save the Boxcar that we're passsing.
When we exit the loop, prevcar points to the second-to-last car, and we can safely set its next variable to null.

Method to remove nodes

I have a *, and I'm trying to get my remove method to removes and returns a specific targeted items. I tried a lot of different way trying to make it work, but it keeps giving me the NPE.
Here is my first remove():
Here is my second remove() that was able to make the code compile:
Here is my LinearNode:
Student class:
To remove should be fairly straightforward and you already have the general idea:
public Student remove(Student items) {
LinearNode previous = null,
current = head;
// iterate over all the nodes starting at the head, maintaining a reference to the previous node as you go
while (current != null && current.items.compareTo(items) != 0) {
previous = current;
current = current.next;
}
// At this point you have either a) found the Node with matching items or b) not found it
if (current == null) {
// not found in the list
return null;
}
// At this point you know where the Node is, and you have a reference previous node as well
// so it's easy to reattach the linked list to remove the node
if (previous == null) {
// The head node was the match if previous is not set, so make sure to update the head Node accordingly
head = current.next;
}
else {
previous.next = current.next
}
return current.items;
}
Use try catch on the suspicious code, till you find which line causing the problem.
This will tell you if you are looking at the right place.
For Example:
while (current != null) {
try{//1st level try
if(current.items.compareTo(items) == 0) {
try{ //2nd level try
if(previous == null) {
head = head.next;
return items;
}
else {
previous.next = current.next;
return items;
}
}catch(NullPointerException e ){
StackTraceElement t = e.getStackTrace()[0];
System.out.println("catch lvl 2 at line: " + t.getLineNumber());
}
}
else {
previous = current;
current = current.next;
}
}catch(NullPointerException e){
StackTraceElement t = e.getStackTrace()[0];
System.out.println("catch lvl 1 at line: " + t.getLineNumber());
}
}
EDIT:
You can try to put this "try catch" and wrap all your main function:
try{
...
}catch(NullPointerException e ){
int i=0
for( StackTraceElement t : e.getStackTrace()){
System.out.println("stack[" + i + "]: " + t.getLineNumber());
i++;
}
}
EDIT2
public Student remove(Integer studentId)
{
LinearNode previous = null;
LinearNode current = head;
while (current != null) {
//if everything is OK you can remove the 2 ifs
if(current.items == null){
//something is really wrong on insert
}
else if(current.items.getId() == null){
//something is really wrong on insert
}
else if( studentId.compareTo(curent.items.getId()) == 0) {
//return value is curent.items;
if(previous == null) {
head = head.next;
return curent.items;
}
else {
previous.next = current.next;
return curent.items;
}
}
else {
previous = current;
current = current.next;
}
}
//not found!
return null;
}

Categories

Resources