Issues adding objects before/after in double linked list - java

I'm trying to add items to a double linked list and I'm try to add them in the correct order defined by comparing their strings.
public boolean add(Book book)
{
Node current = new Node(book);
if(firstNode == null)
{
firstNode = current;
lastNode = current;
numElements++;
return true;
}
else
{
Node tempNode = firstNode;
int val = -1;
while(tempNode != null)
{
if(tempNode.bookElement.compareTo(book) > 0)
{
val = 1;
break;
}
else if(tempNode.bookElement.compareTo(book) == 0)
return false;
else
{
val = -1;
tempNode = tempNode.next;
}
}
if(val > 0)
{
System.out.println("next: " + tempNode.bookElement.getISBN());
current.next = tempNode;
if(tempNode == firstNode)
tempNode.previous = current;
if(current.previous == null)
firstNode = current;
numElements++;
return true;
}
else
{
current.previous = tempNode;
tempNode.next = current;
lastNode = current;
numElements++;
return true;
}
}
}
and here is how i'm adding the objects:
Book[] books = new Book[4];
books[0] = new Book("a", "charles g", "book1");
books[1] = new Book("b", "michael b", "book2");
books[2] = new Book("c", "james k", "book3");
books[3] = new Book("d", "gsdgsdgg g", "book4");
BookList booklist = new BookList();
booklist.add(books[0]);
booklist.add(books[1]);
booklist.add(books[2]);
booklist.add(books[3]);
The objects are compared using the String compareTo on the first parameter i.e "a" or "b"
At the moment I can get the the list to sort properly if I switch the order i.e "a" = "d", "b" = "c" etc, but if I keep it in it the way it is now and try sort i get a null pointer on:
tempNode.next = current;
if I make the line
while(tempNode != null)
to
while(tempNode.next != null)
then the list sorts in order and I can keep it as a,b,c,d. But I'm wanting to be able to sort it correctly regardless of the order I add them in so I think there is something very wrong in the way I'm adding them.
EDIT:
I got the list adding backwards so adding d,c,b,a first works as intended since it wasn't checking the if statements in the while block for the first node since the first nodes next was null so I put it into a dowhile so that it checks it, but I am still getting a null pointer when I try to run it normally by a,b,c,d. The null pointer is happening on the while(tempNode.next != null)
do
{
if(tempNode.bookElement.compareTo(book) > 0)
{
val = 1;
break;
}
else if(tempNode.bookElement.compareTo(book) == 0)
return false;
else
{
val = -1;
tempNode = tempNode.next;
}
}
while(tempNode.next != null);

Your current code fails to add nodes to the end of the list, since in that case tempNode becomes null, and tempNode.next gives you NullPointerException.
You should change your condition to while(tempNode.next != null), but if after the loop val < 0, you have to compare current to tempNode, to determine whether current should be inserted before or after tempNode.

Related

What's wrong with sorted set code? My output should match sample

Can anyone help on what's wrong with my code? Only the first input number shows up when I run it (it doesn't create a sorted list), the delete command isn't working, and the 'true' 'false' in exists command doesn't show up. My output should match the given sample I put at the end.
The areas I had to fill in to make the code work are the areas after the TODOTODOTODO symbols which would be 44-61, 75-83, 97-105. I'm not sure where I went wrong in those areas and why it is not working correctly to give the desired output?
import java.util.Scanner;
// Defines the a Sorted Set collection and implements a driver program in main
public class SortedSet {
// Define a basic element of a linked list
private class LinkedNode {
int x; // Value stored in the node
LinkedNode next; // Reference to the next node in the list
}
LinkedNode front = null; // Reference to the front of the singly linked list
// Adds the integer x to the collection.
// The resulting collection is sorted in increasing order and
// does not contain any duplicate values.
public void add(int x) {
// Initialize a new node to be added to the collection
LinkedNode newNode = new LinkedNode();
LinkedNode cur = front;
newNode.x = x;
// Check if list is empty
if (cur == null) {
front = newNode;
}
// If list is not empty, check if node should be placed in front
else if (front != null) {
if (newNode.x < front.x) {
newNode.next = front;
front = newNode;
}
// If not in front, check for the middle or the end, or duplicate.
else {
// <TODO><TODO><TODO>
LinkedNode temp = cur;
LinkedNode prev = cur;
int middle = x;
while (temp != null) {
if(temp.x > newNode.x) {
middle = 1;
newNode.next = temp;
prev.next = newNode;
}
prev = temp;
temp = temp.next;
}
if (middle == 0) {
prev = newNode;
}
}
}
}
// Deletes the integer x from the sorted set.
// The remaining collection remains sorted and without duplicates.
public void delete(int x){
// Declare a new reference and initialize it to the front of the list
LinkedNode cur = front;
// Check if list is empty
if (front == null) {
System.out.print("There is nothing to delete!");
} else { // Not empty
// Go through list, checking whether node is in the list, and delete if found
// <TODO><TODO><TODO>
LinkedNode prev = new LinkedNode();
while (cur.x != x && cur != null) {
prev = cur;
cur = cur.next;
}
if (cur != null)
prev.next = cur.next;
}
}
// Returns true if the integer x exists in the sorted set and false otherwise.
public void exists(int x) {
// Declare a new reference and initialize it to the front of the list
LinkedNode cur = front;
// Check if list is empty.
if (front == null) {
System.out.println("false");
}
// If not empty, check for the node.
// <TODO><TODO><TODO>
else {
while (cur != null) {
if (cur.x==x)
return;
cur=cur.next;
}
return;
}
}
// Returns a string representing the sorted set as a space separated list.
public String toString() {
String s = "";
LinkedNode cur = front;
while (cur!=null) {
s+= cur.x + " ";
cur = cur.next;
}
return s;
}
// Driver method
public static void main(String[] args) {
// Declare variables
SortedSet sortedSet = new SortedSet();
Scanner scan = new Scanner(System.in);
String[] tokens;
String command;
int num;
// Print header info
System.out.println("Programming Fundamentals\n"
+ "NAME: Andres Reyes\n"
+ "PROGRAMMING ASSIGNMENT 4\n");
// Enter command loop
while (true) {
// Prompt the user for a command
System.out.print("Enter command: ");
String input = scan.nextLine();
// Parse input
if (input.equals("q")) break; // user quits
tokens = input.split("\\s");
if (tokens.length < 2) continue; // invalid input
command = tokens[0];
num = Integer.parseInt(tokens[1]);
// Execute command
if (command.equals("add")){
sortedSet.add(num);
System.out.println(sortedSet);
} else if (command.equals("del")) {
sortedSet.delete(num);
System.out.println(sortedSet);
} else if (command.equals("exists")) {
sortedSet.exists(num);
} else {
System.out.print("Command does not exist");
}
}
System.out.println("\nGood bye!");
}
}
I made following changes in the add-function and they got it working for me:
// If not in front, check for the middle or the end, or duplicate.
else {
// <TODO><TODO><TODO>
LinkedNode temp = cur.next; // start at cur.next as your temp-variable
LinkedNode prev = cur;
int middle = 0; // set middle to 0
while (temp != null) {
if(temp.x > newNode.x) {
middle = 1;
newNode.next = temp;
prev.next = newNode;
}
prev = temp;
temp = temp.next;
}
if (middle == 0) {
// add node to the end
prev.next = newNode;
}
}
}
You have to start at cur.next as your temp-variable.
As far as I can see, you're not yet checking if there are any duplicate values in your list.
Edit: I didn't work on the exists-method, which is not giving you any output at the moment. The problem is simply that you're generating any output while you're checking if a value exists in your list. You could either write a System.out.print which prints "true" in case the value was found or "false" in case if wasn't. Or you change the return type of the exists-function to boolean, return a boolean according to the result and print the return value.
It might also help you to visualize a linked list to unterstand why you have to change the temp-variable to cur.next. I think https://www.tutorialspoint.com/data_structures_algorithms/linked_lists_algorithm.htm gives a good explaination of the insertion process.
I can give you some hints. The main problem I see with this code is that you really need a reference to the start of the LinkedList (the head) would be the only way to print the list and check for duplicates.
The following should be added to your class
LinkedList head = null; //start of the list
Then you have to update your toString() or you will never print the correct elements in your list no matter what you do. Try this:
public String toString(){
StringBuilder output = new StringBuilder();
LinkedNode current = head;
while(current != null){
output.append(current.x).append(" ");
current = current.next;
}
return output.toString();
}
You have to be really careful when you are appending to a String in a loop because Strings are immutable. Everytime you are appending to a list you are creating a new String. Instead, use StringBuilder.
//s+= cur.x + " ";
Your add method should handle the following cases:
Case 1: List is empty: ( don't forget to set ref to head)
Case 2: new element is great than front of list
Case 3: new element is less than current head
Case 4: new element is less than current and greater than head

Creating a linked list from scratch in java but remove method isn't working

Creating a linked list but have become stumped at my remove method. My list contains:
Node<String> text1 = new Node<>();
text1.setData("Hello");
Node<String> text2 = new Node<>();
text2.setData("World");
Node<String> text3 = new Node<>();
text3.setData("Test");
having the list be removed would be:
card.remove(text1);
Once executed, the method should display true after a message prompting that the node has indeed been removed however, the method would never reach within the while statement and go straight to returning it to false.
I know the problem is my while statement but I have tried changing it numerous times to:
while (current != null)
while (current != node)
while (current.getNext() != null || current == tail)
while (current != null && current.getNext != node)
etc.
It would either return false or just show a NullPointerException Error
public boolean remove(Node node) {
if (listSize == 0) {
throw new IllegalStateException("nothing to delete here :/");
}
boolean result = false;
Node prev = head;
Node current = head;
while (current != null) {
if (node.equals(current.getData())) {
if (listSize == 1) {
head = null;
tail = null;
} else if (current.equals(head)) {
head = head.getNext();
} else if (current.equals(tail)) {
tail = prev;
tail.setNext(null);
} else {
prev.setNext(current.getNext());
}
current.setNext(current.getNext());
listSize--;
result = true;
}
prev = current;
current = prev.getNext();
}
return result;
}
The expected output should look like something like this after the method runs smoothly
removed text 3: true (removed)
right now it shows:
remove text 3: false (removed)
Here, node is a Node object but you are comparing it with a String object. Try
node.getData().equals(current.getData()) in stead of node.equals(current.getData()) for comparing.

Find least common ancestor of two nodes in java

I have looked at a lot of other answers on stackoverflow and can't find anything that works, I either get the root, or node1 itself returned, I'm not sure how to do this recursively and have tried it many times all ending the same way. Any help would be greatly appreciated!
Here's my code:
private static Node findLCA(Node node1, Node node2) {
Node temp1 = node1, temp2 = node2, currentLargest = null;
int largestDepth = 0;
boolean found = false;
if(node1 == null || node2 == null){
return null;
} else{
while(found == false){
if(temp1.getParent() != null && temp2.getParent() != null && temp1.getParent() == temp2.getParent() && nodeDepth(temp1.getParent()) > largestDepth){
largestDepth = nodeDepth(temp1.getParent());
currentLargest = temp1;
temp1 = temp1.getParent();
temp2 = temp2.getParent();
} else if(temp1.getParent() != null){
temp1 = temp1.getParent();
} else if(temp2.getParent() != null){
temp2 = temp2.getParent();
}
if(temp1.getParent() == null && temp2.getParent() == null){
found = true;
}
}
if(nodeDepth(temp1) >= largestDepth){
return temp1;
} else{
return currentLargest;
}
}
}
I edited it to make a list of ancestors of each node, but I'm not sure how to go around checking each one to see if the elements in the list's match up since they are usually different sizes.
Heres the new code:
ArrayList<PhyloTreeNode> list1 = new ArrayList<PhyloTreeNode>();
ArrayList<PhyloTreeNode> list2 = new ArrayList<PhyloTreeNode>();
if(node1 == null || node2 == null){
return null;
} else{
if(node1.getParent() != null){
list1.add(node1.getParent());
findLeastCommonAncestor(node1.getParent(), node2);
}
if(node2.getParent() != null){
list2.add(node2.getParent());
findLeastCommonAncestor(node1, node2.getParent());
}
}
We can use recursive post order traversal for computing lowest common ancestor,
Here is my Java implementation
Here a & b are given input data for which i have to find lowest common ancestors.
public static int lowestcommanancestors(Node root,int a,int b){
if(root==null)
return 0;
int x=lowestcommanancestors(root.left,a,b);
int y=lowestcommanancestors(root.right,a,b);
if(x+y==2){
System.out.println(root.getData());
return 0;
}
if(root.getData()==a || root.getData()==b){
return x+y+1;
}
else{
return x+y;
}
}
First i am checking whether given input node presenting in left subtree or not,if yes just return 1 else 0,Similarly for right sub tree.When sum becomes 2 first time that node will be lowest common ancestors.
Tell me if i am wrong or you are getting difficulties to understanding the code

java Delete a Binary Tree node containing two children

This is the last case where the node to be deleted has two children. I cant figure out what I am doing wrong . Please help.
//BTNode has two children
else if (u.getLeft() != null && u.getRight() != null){
//if node to delete is root
BTNode<MyEntry<K,V>> pred = u.getRight();
while (pred.getLeft().element() != null){
pred = pred.getLeft();
}
BTNode<MyEntry<K,V>> predParent = pred.getParent();
if (!hasRightChild(pred)){
predParent.setLeft(new BTNode<MyEntry<K,V>>(null,predParent,null,null));}
if (hasRightChild(pred)){
BTNode<MyEntry<K,V>> predChild = pred.getRight();
predParent.setLeft(predChild);
predChild.setParent(predParent);
}
return returnValue;
ok so modify it like this ??
u.setElement(succ.element());
BTNode<MyEntry<K,V>> succParent = succ.getParent();
if (!hasLeftChild(succ)){
succParent.setRight(new BTNode<MyEntry<K,V>>(null,succParent,null,null));}
if (hasLeftChild(succ)){
BTNode<MyEntry<K,V>> predChild = succ.getLeft();
succParent.setRight(predChild);
predChild.setParent(succParent);
}
return returnValue;
From wikipedia:
Deleting a node with two children: Call the node to be deleted N. Do
not delete N. Instead, choose either its in-order successor node or
its in-order predecessor node, R. Replace the value of N with the
value of R, then delete R.
So, take for example the left children, and then find the rightmost leaf in that subtree, then replace the information of the node to delete with that of the leaf, and then delete that leaf easily.
You might want to create a function that returns the rightmost leaf from a subtree.
I have given the code for deletion of a node in a BST which would work for any condition and that too using a for loop.
public void delete(int key) {
Node<E> temp = find(key);
System.out.println(temp.key);
for (;;) {
// case 1 : external node
if (temp.isExternal()) {
if (temp.getParent().getrChild() == temp) {
temp.parent.rightchild = null;
temp = null;
} else {
temp = null;
}
break;
}
// case2 : one child is null
else if ((temp.getlChild() == null) || (temp.getrChild() == null)) {
if ((temp.parent.leftchild != null) && temp.getParent().getlChild().key == temp.key) {
if (temp.getlChild() == null) {
temp.getParent().setLeft(temp.getrChild());
temp.getrChild().setParent(temp.getParent());
break;
}
else
temp.getParent().setLeft(temp.getlChild());
temp.getlChild().setParent(temp.getParent());
}
else {
if (temp.rightchild != null) {
System.out.println("in");
temp.getParent().setRight(temp.getrChild());
temp.getrChild().setParent(temp.getParent());
break;
}
else
temp.getParent().setRight(temp.getlChild());
temp.getlChild().setParent(temp.getParent());
}
break;
}
// case 3 : has both the children
else {
int t = temp.key;
temp.key = temp.getlChild().key;
temp.getlChild().key = t;
temp = temp.getlChild();
continue;
}
}
}

NullPointerException with while loop using compareTo

For our homework, I have to take in Chair objects and add them to the DoublyLinkedList that we made; it has to be sorted by alphabetical order, if style is the same alphabetically, we sort by color
When I try to go through the loop, I keep getting a NullPointerException.
public void add(Chair element){
if(isEmpty() || first.object.style.compareTo(element.style) > 0 || (first.object.style.compareTo(element.style) == 0 && first.object.color.compareTo(element.color) >= 0){
addFirst(element);
}else if(first.object.style.compareTo(element.style) <= 0){
Node temp = first;
Node insert = new Node(); insert.object = element;
while(temp.object.style.compareTo(element.style) <= 0) //This is where the nullPointerException occurs
if(temp.hasNext())
temp = temp.next;
while(temp.object.style.compareTo(element.style) == 0 && temp.object.color.compareTo(element.color) <= 0)
if(temp.hasNext())
temp = temp.next;
insert.prev = temp.prev;
insert.next = temp;
temp.prev.next = insert;
temp.prev = insert;
}
}
This is the code where I put the information into the DoublyLinkedList
try{
FileReader fr = new FileReader(filename);
Scanner sc = new Scanner(fr);
String[] temp;
while(sc.hasNext()){
temp = sc.nextLine().split(" ");
if(temp[0].equals("Bed")){}
else if(temp[0].equals("Table")){
// tables.add(new Table(Integer.parseInt(temp[1]), Integer.parseInt(temp[2]), Integer.parseInt(temp[3]), temp[4]));
}else if(temp[0].equals("Desk")){}
else if(temp[0].equals("Chair")){
chairs.add(new Chair(temp[1], temp[2]));
}else if(temp[0].equals("Bookshelves")){}
else{
color = temp[0];
}
}
while(!chairs.isEmpty())
System.out.println(chairs.removeFirst().info());
System.out.println();
//while(!tables.isEmpty())
// System.out.println(tables.removeFirst().info());
}catch(Exception e){e.printStackTrace();}
This is the DoublyLinkedList class that I've made:
class CDoublyLinkedList{
Node first, last;
public CDoublyLinkedList(){
first = new Node(); last = new Node();
first.prev = last.next = null;
first.object = last.object = null;
first.next = last;
last.prev = first;
}
public boolean isEmpty(){
return first.object == null;
}
public void addFirst(Chair element){
Node insert = new Node();
insert.object = element;
insert.prev = null;
insert.next = first;
first.prev = insert;
first = insert;
}
public void add(Chair element){
if(isEmpty() || first.object.style.compareTo(element.style) > 0 || (first.object.style.compareTo(element.style) == 0 && first.object.color.compareTo(element.color) >= 0){
addFirst(element);
}else if(first.object.style.compareTo(element.style) <= 0){
Node temp = first;
Node insert = new Node(); insert.object = element;
while(first.object.style.compareTo(element.style) <= 0)
if(temp.hasNext())
temp = temp.next;
while(first.object.style.compareTo(element.style) == 0 && first.object.color.compareTo(element.color) <= 0)
if(temp.hasNext())
temp = temp.next;
insert.prev = temp.prev;
insert.next = temp;
temp.prev.next = insert;
temp.prev = insert;
}
}
public Chair removeFirst(){
Chair tobedeleted = first.object;
Node temp = first.next;
first = temp;
first.prev = null;
return tobedeleted;
}
private class Node{
Node next, prev;
Chair object;
public boolean hasNext(){
return next != null;
}
}
}
The Chair class:
class Chair extends Furniture{
public String style, color;
public Chair(String s, String c){
style = s; color = c;
}
public String toString(){
return color;
}
public String getType(){
return "Chair";
}
public String info(){
return (color+", "+style);
}
}
Can someone please explain to me why I keep getting this error? Thank you!
EDIT:
while(temp.object.style.compareTo(element.style) <= 0) //This is where the nullPointerException occurs
chairs.add(new Chair(temp[1], temp[2]));
java.lang.NullPointerException
at CDoublyLinkedList.add(Furnish2SS.java:119)
at Furnish2SS.main(Furnish2SS.java:23)
java.lang.NullPointerException
at CDoublyLinkedList.add(Furnish2SS.java:119)
at Furnish2SS.main(Furnish2SS.java:23)
EDIT2: SOLVED!
I changed my while loop to:
while(temp.object != null && element != null && (temp.object.compareTo(element) == 0 || temp.object.compareTo(element) == -1))
The reason I got the error was because I wasn't checking for null every iteration.
You say this is the line of code causing the exception:
while(temp.object.style.compareTo(element.style) <= 0)
You probably should set a debugger breakpoint on that line and use a debugger to determine which of the values is null. But it's hard for me to explain here full instructions on how to setup and use a debugger (that doesn't mean you shouldn't learn! You should. There are lots of tutorials. Google it.) So instead of writing a tutorial on debuggers, I'll just post code that will tell you which variable is null:
if (temp == null) {
System.out.println("temp is null");
} else if (temp.object == null) {
System.out.println("temp.object is null");
} else if (temp.object.style == null) {
System.out.println("temp.object.style is null");
}
if (element == null) {
System.out.println("element is null");
} else if (element.style == null) {
System.out.println("element.style is null");
}
while(temp.object.style.compareTo(element.style) <= 0) //This is where the nullPointerException occurs
{
if(temp.hasNext())
temp = temp.next;
if (temp == null) {
System.out.println("loop: temp is null");
} else if (temp.object == null) {
System.out.println("loop: temp.object is null");
} else if (temp.object.style == null) {
System.out.println("loop: temp.object.style is null");
}
if (element == null) {
System.out.println("loop: element is null");
} else if (element.style == null) {
System.out.println("loop: element.style is null");
}
}
If you use the above code statements to replace these three lines of your code:
while(temp.object.style.compareTo(element.style) <= 0) //This is where the nullPointerException occurs
if(temp.hasNext())
temp = temp.next;
you will know which variable is null based on which statement is printed. Hopefully you can take it from there. (The usual way to fix a NullPointerException is to take the steps necessary to ensure the offending null variable actually has a valid, non-null value by the time the program reaches the line of the NullPointerException).
Take a look at addFirst(Chair element). That method is really screwed up. It creates a new Node which contains the correct Chair. It then sets its prev to null. Then it sets next to first. And this is what's causing all of your troubles. Because first points to an empty Node. You end up with this:
first points to your new Node. That one points to a Node which holds no Chair. That one again points to last.
e:
Your whole code looks like you had at least two different approaches on implementing your list and threw them toghether. There are some more errors but since this is homework I guess it's not that bad if you try fixing it first.
If you can't figure out how to correct that, ask here.
PS: Sorry for all of the editing and (un)deleting my answeres (if you noticed). I'm a bit tired and kept causing new errors by fixing old ones until I finally figured out what was the true cause of all this.

Categories