Get Previous Element From a List // Java - 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;
}

Related

swapping a given node with the next node

I want to swap two nodes. The given node will be swapped with the next node (it's a singly LinkedList. However, the node has two fields).
My code isn't working in the node position as before
public void swapNodes(int given_d1, double given_d2) {
Node pointer = first;
Node previous=null;
while (pointer != null&& pointer.next != null) {
previous=pointer;
pointer=pointer.next;
if (pointer.data1 == given_d1 && pointer.data2 == given_d2) {
Node temp= pointer.next.next;
previous.next=pointer.next;
previous=previous.next;
previous.next=pointer.next;
pointer.next=temp;
}
}
}
I don't think you're helping yourself by with your choice of temp and pointer as a variable names, but let's see if we can figure this out :)
You're starting out with 4 nodes under consideration:
previous -> pointer -> ? -> temp
I think you are hoping to end up with the following:
previous -> ? -> pointer -> temp
When you set previous.next = pointer.next the first time, I think you've correctly started the swap process.
The problem is in the next couple of lines. What you want to have happen is you make previous.next.next = pointer and then pointer.next = temp.
So you were close, but here's what I think the body of the if statement needs to be:
if (pointer.data1 == given_d1 && pointer.data2 == given_d2) {
Node temp = pointer.next.next;
previous.next = pointer.next;
previous.next.next = pointer;
pointer.next = temp;
}

Program breaking block in sorting algorithm

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
}

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