Program breaking block in sorting algorithm - java

I'm writing a sorting algorithm for a linked list style program, where elements in the list contain CampSite objects. Getting the site type returns a 1 or a 0, where the 0 site needs to be at the front of the list. There's other factors required in the sort but none of them cause the program to fail construction. For whatever reason, this block in the sortList() method causes the program to never reach the GUI, despite IntelliJ saying the "Build completed successfully".
while (current != null) {
index = current.getNext();
while (index != null) {
if (current.getData().getSiteType() > index.getData().getSiteType()) {
temp = current.getData();
current.setData(index.getData());
index.setData(temp);
}
}
}
Can anybody help me understand why this is?

You have never incremented the current and index in the while loop, which will make it an infinite loop. Try to increment the value of index and current so that loop may exists.
Following code changes may help you
while (current != null) {
index = current.getNext();
while (index != null) {
if (current.getData().getSiteType() > index.getData().getSiteType()) {
temp = current.getData();
current.setData(index.getData());
index.setData(temp);
}
index = index.getNext(); // increment the index of the list
}
current = current.getNext(); // increment the current of the list to avoid infinite loop
}

Related

Get Previous Element From a List // Java

I am getting data from a csv. If a row in csv doesn't contain values, I will need to update it with the previous row values. The way I am doing it is -
Parse the csv and add all the rows to a linked list.
Iterate through the list and check if a row is empty then fill it with the previous row.
Point #2 is not working as expected. Below is my code snippet:
ListIterator<Data> li = dataList.listIterator(0);
while (li.hasNext()) {
Data prev = null;
if (li.hasPrevious()) {
prev = li.previous();
System.out.println("Previous Node is: "+prev);
}
Data data = li.next();
if (data.getNumber() == null || data.getNumber().trim().isEmpty()) {
data.setPartType(prev.getPartType());
data.setNumber(prev.getNumber());
}
I believe its happening because when we call next() it moves the pointer to the next and hence the previous element will be the current element.
Question - how do I get the actual previous element?
From docs listIterator.previous() and listIterator.next() moves the cursor position backwards and forwards respectively. Hence, in your case it'll mostly result in a endless loop at 2nd index.
What you essentially need is previous element without moving cursor. listIterator.previousIndex() can help you with it.
ListIterator<Data> li = dataList.listIterator(0);
while (li.hasNext()) {
Data prev = null;
if (li.hasPrevious()) {
prev = dataList.get(li.previousIndex());
System.out.println("Previous Node is: "+prev.getNumber());
}
Data data = li.next();
if (data.getNumber() == null || data.getNumber().trim().isEmpty()) {
data.setPartType(prev.getPartType());
data.setNumber(prev.getNumber());
}
}
Although this seems to clutter the readability of code. Better to consider using a simple forEach loop. As -
Data prev = null;
for (Data data: dataList) {
if ((data.getNumber() == null || data.getNumber().trim().isEmpty()) && prev != null) {
data.setPartType(prev.getPartType());
data.setNumber(prev.getNumber());
}
prev = data;
}

Find a value in a binary tree avoiding stackoverflow exception

I'm trying to find a value in a binary tree and returning the node that has the value I'm looking for.
I did an algorithm that works well when the value is not in a very deep level of the tree, but when the value is in a deep position I get a java.lang.StackOverflowError. Here is my code:
class Nope {
Nope left, right;
int value;
public Nope find(int v){
if(v > this.value && this.right != null)
return right.find(v);
if(v < this.value && this.left != null)
return left.find(v);
if(this.value == v)
return this;
return null;
}
}
Can any one suggest me a solution about this issue (I heard about something like tail optimization recursion) but I'm not sure of it working in Java.
The simplest approach is to convert this into a while loop, which just maintains state of "the current node we're testing".
On each iteration of the loop, there are three possibilities:
The current node has the right value, in which case you can return it
The current node has a subnode on the correct "side", in which case you can continue iterating with that subnode as the new "current node"
Neither of the above is the case, in which case the value isn't found and you can return null
So something like:
public Nope find(int v) {
Nope current = this;
while (current != null) {
if (current.value == v) {
return current;
}
// This will drop out of the loop naturally if there's no appropriate subnode
current = v < current.value ? current.left : current.right;
}
return null;
}
Or with even less code, but perhaps less readably:
public Nope find(int v) {
Nope current = this;
// Keep navigating down the tree until either we've run
// out of nodes to look at, or we've found the right value.
while (current != null && current.value != v) {
current = v < current.value ? current.left : current.right;
}
return current;
}
An example of your code recast as iteration:
class Nope {
// keep these​​​​​​​​‌‌‌‌‌​​‌‌​​​​​​‌​‌​‌‌‌​ fields
Nope left, right;
int value;
public Nope find(int v){
Nope n = this;
while (n != null)
{
if (v > n.value)
n = n.right;
else if (v < n.value)
n = n.left;
else // v == n.value
return n;
}
return null;
}
}
Edit: just a note on how this works, in case it's unclear. Since you never need to remember anything about how you got to the current node, we only keep track of the root of the current subtree we need to search. At each step, we've either determined there is no subtree left to search (first condition), there might be a subtree to the left or right (middle two conditions), or that we have actually found the value at the root of the current subtree (last condition). We keep looking until we run out of subtrees (while condition) and, if we do run out, we know the value isn't in the tree and we return null.
Edit: As pointed out in the comments, the use of consecutive ifs is a problem. I have updated the code to use if/else if/else.
Tree searches are used to avoid iterating over large arrays.
The weakness of the tree approach is when the node values are ordered. As the tree is loaded, every node goes to the left or right, causing a lot of recursion. Having said that, stack overflow takes a lot of recursion.
You can either hash the values, which will tend to balance the tree, or you can enhance your tree building algorithm to balance the tree if a particular branch gets too long.
Having said that, you should also look at how many nodes are in your tree that there are enough to cause a stack overflow. You may have a bug in your code that is not shown here.
You can use Xss JVM argument to increase the memory allocated to the thread stack. This will allow you to have a larger method call stack.
-Xsssize
Sets the thread stack size (in bytes). Append the letter k or K to indicate KB, m or M to indicate MB, g or G to indicate GB. The
default value depends on virtual memory.
The following examples set the thread stack size to 1024 KB in
different units:
-Xss1m
-Xss1024k
-Xss1048576
Ref: https://docs.oracle.com/javase/8/docs/technotes/tools/windows/java.html
Otherwise you can always convert the recursion to the a loop, that would mean you would have to manage the call stack of the method (arguments and return values) yourself in a stack, that can become messy.
Note: For search operation there's no need for a stack as mentioned by Jon Skeet. Search doesn't need to keep track of where it's been. However for backtracking a reference to parent would be required, and we will have to make sure that we always start with left child.

Linked List sorting issue

YES, this is a homework project.
That being said, I'm looking to learn from my mistakes rather than just have someone do it for me.
My project is a word frequency list - I accept a text file (or website URL) and count the:
- Number of unique words, and
- How many times they appear.
All methods are provided for me except for one: the insert(E word) method, where the argument is a generic type word.
The word is stored in a Node (Linked List project) that also has a 'count' value, which is the value representing the number of times the word appears in the text being read.
What this method has to do is the following:
If the argument is already in the list, increment the count of that element. I have done this part
If the argument is not found in the list, append it to the list. I also have done this part.
sort the list by descending count value. i.e. highest -> lowest count
3.5. If two elements have the same count value, they are sorted by the dictionary order of their word.
I am VERY unfamiliar with Linked Lists, so as such I am running into a lot of NullPointerExceptions. This is my current insert method:
public void insert(E word){
if(word.equals("")){
return;
}
if(first == null){//if list is null (no elements)
/*Node item = new Node(word);
first = item;*/
first = new Node(word);
}
else{//first != null
Node itemToAdd = new Node(word);
boolean inList = false;
for(Node x = first; x != null; x=x.next){
if (x.key.equals(word)){// if word is found in list
x.count++;//incr
inList = true;//found in list
break;//get out of for
}//end IF
if(x.next == null && inList == false){//if end of list && not found
x.next = itemToAdd;//add to end of list
break;
}//end IF
}//end FOR
//EVERYTHING ABOVE THIS LINE WORKS.
if (!isSorted()){
countSort();
}
}//end ELSE
}//end method
My isSorted() method:
public boolean isSorted(){
for(Node copy = first; copy.next != null; copy = copy.next){
if (copy.count < copy.next.count){
return false;
}
}
return true;
}
and last but not least, the part where I'm struggling, the sort method:
public void countSort(){
for (Node x = first, p = x.next; p != null; x=x.next, p=p.next){
// x will start at the first Node, P will always be 1 node ahead of X.
if(x == first && (x.count < p.count)){
Node oldfirst = first;
x.next = p.next;
first = p;
first.next = oldfirst;
break;
}
if (x.count < p.count){
//copy.next == x.
Node oldfirst = first;
oldfirst.next = first.next;
x.next = p.next;
first = p;
first.next = oldfirst;
break;
}
if (x.count == p.count){
if(x.toString().charAt(0) < p.toString().charAt(0)){
//[x]->[p]->[q]
Node oldfirst = first;
x.next = p.next;
first = p;
first.next = oldfirst;
break;
}
}
}
}
Here is the output of my insert method when called by the classes/methods given to me:
Elapsed time:0.084
(the,60)
(of,49)
(a,39)
(is,46)
(to,36)
(and,31)
(can,9)
(in,19)
(more,7)
(thing,7)
(violent,3)
(things,3)
(from,9)
(collected,1)
(quotes,1)
(albert,1)
(einstein,2)
(any,2)
(intelligent,1)
(fool,1)
(make,1)
(bigger,1)
(complex,1)
(it,11)
(takes,1)
(touch,1)
(genius,1)
(lot,1)
(courage,1)
(move,1)
(opposite,1)
(direction,1)
(imagination,1)
(important,5)
(than,3)
(knowledge,3)
(gravitation,1)
(not,17)
(responsible,1)
(for,14)
(people,2)
(falling,1)
(love,2)
(i,13)
(want,1)
(know,3)
(god,4)
(s,8)
(thoughts,2)
(rest,2)
(are,11)
(details,2)
(hardest,1)
(world,7)
(understand,3)
(income,1)
(tax,1)
(reality,3)
(merely,1)
(an,7)
(illusion,2)
(albeit,1)
(very,3)
(persistent,2)
(one,12)
(only,7)
(real,1)
(valuable,1)
(intuition,1)
(person,1)
(starts,1)
(live,2)
(when,3)
(he,11)
(outside,1)
(himself,4)
(am,1)
(convinced,1)
(that,14)
(does,5)
(play,2)
(dice,1)
(subtle,1)
(but,8)
(malicious,1)
(weakness,2)
(attitude,1)
(becomes,1)
(character,1)
(never,3)
(think,1)
(future,2)
(comes,1)
(soon,1)
(enough,1)
(eternal,1)
(mystery,1)
(its,4)
(comprehensibility,1)
(sometimes,1)
My initial idea has been to try and loop the if(!isSorted()){ countSort();} part to just repeatedly run until it's sorted, but I seem to run into an infinite loop when doing that. I've tried following my professor's lecture notes, but unfortunately he posted the previous lecture's notes twice so I'm at a loss.
I'm not sure if it's worth mentioning, but they provided me an iterator with methods hasNext() and next() - how can I use this as well? I can't imagine they'd provide it if it were useless.
Where am I going wrong?
You are close. First the function to compare the items is not complete, so isSorted() could yield wrong results (if the count is the same but the words are in wrong order). This is also used to sort, so it's best to extract a method for the comparison:
// returns a value < 0 if a < b, a value > 0 if a > b and 0 if a == b
public int compare(Node a, Node b) {
if (a.count == b.count)
return a.word.compareTo(b.word);
// case-insensitive: a.word.toLoweCase().compareTo(b.word.toLowerCase())
} else {
return a.count - b.count;
}
}
Or simplified which is enough in your case:
public boolean correctOrder(Node a, Node b) {
if (a.count > b.count)
return true;
else if (a.count < b.count)
return false;
else
return a.word.compareTo(b.word) <= 0;
}
For the sort you seem to have chosen bubble sort, but you are missing the outer part:
boolean change;
do {
change = false;
Node oldX = null;
// your for:
for (Node x = first; x.next != null; x = x.next) {
if (!correctOrder(x, x.next)) {
// swap x and x.next, if oldX == null then x == first
change = true;
}
oldX = x;
}
} while (change);
We could use the help of Java native library implementation or more efficient sort algorithms, but judging from the exercise the performance of the sort algorithm is of no concern yet, first need to grasp basic concepts.
With looking your codes, it sounds like to me that two things can be done:
Firstly, you can make use of Comparable class method. So, I assume you wrote the class Node, thus you may want to inherit from Comparable class. When you inherited from that class, java will automatically provide you the compareTo method, and all you need to do is to specify in that method that "I want to compare according to your counts and I want it to be in ascending order."
**Edit(1):By the way, I forgot the mention before but after you impelement your compareTo method, you can use Collections.sort(LinkedList list), and it will be done.
The second solution came to mind is that you can sort your list during the countSort() operation with the technique of adding all to an another list with sorting and after add all them back to the real list. The sorting technique I'm trying to say is, keep going towards to the end of the list until you find a Node in the list that has a count smaller than currently adding Node's counts. Hope that doesn't confuse your head, but by this way you can achieve more clear method and less complicated view. To be clear I want to repeat the procedure:
Look the next
If (next is null), add it //You are at the end.
else{
if (count is smaller than current count), add it there
else, keep moving to the next Node. //while can be used for that.
}

Skip list searching null pointer exception

I keep seeing null pointer exceptions in my search method for the skip list I'm implementing.
public V find(K key, SkiplistMapNode<K,V> header, int level){
SkiplistMapNode<K,V> N = header;
for (int i = level-1; i >= 0; i--){
if ((N != null) && (N.getNext()[i] != null)){
while (N.getNext()[i].getKey().compareTo(key) < 0){
N = N.getNext()[i];
}
}
}
N = N.getNext()[0];
if ((N != null) && (N.getKey().compareTo(key) == 0)) return N.getValue();
else return null;
}
The line with the exception is:
while (N.getNext()[i].getKey().compareTo(key) < 0)
I pretty much copied this from this page though, so I'm not sure what would be wrong with it.
Supposing that N.getNext() advances to the next node, you need to memorize its value without advancing if you access the value more than once.
Same with iterator:
while (iterator.hasNext()) {
if (iterator.next()!=null) {
iterator.next().toString() // advances to the next item, which may be null
}
}
Fixed:
while (iterator.hasNext()) {
Object next=iterator.next(); // advance once
if (next!=null) { // check value
next.toString() // use same value, without advancing
}
}
It's hard to tell from your code where you really want to advance to the next element, and where you need the elements values again. Store the next value in a variable, and check and use this value afterwards, same as in the Iterator example above.
If you access an objects method, you should really make sure that the object isn't null. In your case, in...
while (N.getNext()[i].getKey().compareTo(key) < 0)
These...
N.getNext() //the only really important one you seem not to be checking
N.getNext()[i]
could be null and should be checked and possibly even (though less likely and debatably)
N
N.getNext()[i].getKey()
key

Is my implementation of Floyd's cycle detection algorithm incorrect?

I have the following code for detecting a cycle in a linked list:
public Class Node {
Object data;
Node next = null;
}
boolean containCycle() {
boolean retVal = true;
Node head = this;
Node slower = head;
Node faster = head;
if(faster != null && faster.next != null) {
faster = faster.next;
} else { // there is only one element or zero element
retVal = false;
}
if (faster.next != null) {
faster = faster.next;
} else { // there are only 2 elements
retVal = false;
}
while (slower != faster && slower != null && faster != null) {
faster = (faster.next != null && faster.next.next != null) ? faster.next.next : null;
slower = (slower.next != null) ? slower.next : null;
}
if (slower == faster) {
retVal = true;
System.out.printf("The two pointers meet at: %d\n", faster.data);
} else {
retVal = false;
}
if (retVal) { // this is the part for detecting where the loop begins
slower = head;
while(slower.next != faster.next) {
slower = slower.next;
faster = faster.next;
}
System.out.println("The cycle starts at: " + slower.data);
}
return retVal;
}
This code runs fine up until the part where I actually start detecting where the loop begins, which I commented in the code. Somehow, this runs into an infinite loop.
I suspect that this is somehow related to pass by reference in Java? Am I updating the value that head refers to while I was detecting the loop? I am really out of ideas here. Please help!
I dont know the exact algorithm, but you could use the following way to find the meeting point.
Let us call the Node at which slower and faster meet as meeting point.
Have two pointers one starting from head, another starting from meeting point .
And keep count of how many nodes you need to traverse from head to meeting point(let us call this count as a) and
meeting point's next node to meeting point. (Lets call this count b)
Now the difference |a-b| in these two counts represents the common part -right? (ie part between the start of the loop and the meeting point of slower and faster).
So now again start afresh.Reset the two pointers, one to head and other to meeting point + 1.
for example if a>b, move pointer from head |a-b| times else move pointer from meeting piont + 1 |a-b| times.
Now move two pointers together till they meet.
ANOTHER Way of explaining this
Since what you are looking for is similar to the case where you have two linked lists and they merge at some node and you need to identify that node.
All you have is the starting points of the two linked lists.
So you start from head1 and count till end of list.
Next you start from head2 and count till end of list.
The calculate the diff in the lengths. Increment the longer path diff times. And then start moving pointers starting from shorter paths head and the diff till the two pointers meet.
This is essentially the same thing what you are doing in the other case.

Categories

Resources