swapping a given node with the next node - java

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;
}

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;
}

Difference Between Two Iterative Solutions for PreOrder Traversal of a Binary Tree

As of right now, I'm trying to get a intuitive understanding of recursion by also working on using the Stack object in Java. On GeeksForGeeks, they have practice problems on traversal methods on a binary tree. Currently I'm on PreOrder and while I've figured out the recursive solution, the iterative solution is proving to be quite troublesome to come up with. When I pulled up the actual answer to the problem, I found that my code is practically identical to the solution code. I've been going back and forth for a while trying to figure out why my Iterative solution for a PreOrder traversal is incorrect compared to the actual solution but thought that maybe I need a third set of more experienced eyes to tell me why I'm wrong.
Here's the url to the problem and the online compiler: https://practice.geeksforgeeks.org/problems/preorder-traversal/1
Here's my code:
void preorder(Node root)
{
// Your code goes here
if(root == null) return;
Stack<Node> stack = new Stack<Node>();
stack.push(root);
while(!stack.isEmpty()) {
Node cur = stack.pop();
System.out.print(cur.data + " ");
if(cur.left != null) {
stack.push(cur.left);
}
if(cur.right != null) {
stack.push(cur.right);
}
}
}
Here's the solution code:
void preorder(Node root) {
// Base Case
if (root == null) {
return;
}
// Create an empty stack and push root to it
Stack<Node> nodeStack = new Stack<Node>();
nodeStack.push(root);
/* Pop all items one by one. Do following for every popped item
a) print it
b) push its right child
c) push its left child
Note that right child is pushed first so that left is processed first
*/
while (nodeStack.empty() == false) {
// Pop the top item from stack and print it
Node mynode = nodeStack.peek();
System.out.print(mynode.data + " ");
nodeStack.pop();
// Push right and left children of the popped node to stack
if (mynode.right != null) {
nodeStack.push(mynode.right);
}
if (mynode.left != null) {
nodeStack.push(mynode.left);
}
}
}
Preorder traversal for a binary tree is Visit,Left and Right.
Your code is not similar to solution's code.
You need to push right child first to the stack and then the left child to bring left child on top of the stack and then visit that child. Hence, modify your code as shown below-
void preorder(Node root)
{
// Your code goes here
if(root == null) return;
Stack<Node> stack = new Stack<Node>();
stack.push(root);
while(!stack.isEmpty()) {
Node cur = stack.pop();
System.out.print(cur.data + " ");
if(cur.right != null) {
stack.push(cur.right);
}
if(cur.left != null) {
stack.push(cur.left);
}
}
}

LinkList, Checking for double values

I'm writing a code that returns true if the entire link list is stuttered and false if it's not. A stuttered list would be 1,1,2,2,5,5,8,8 , non-stuttered would be something like 1,1,2,2,5,6,8,8.
I have been playing around with it for quite a while, and can't seem to get it to return the correct statement OR not get a nullpointer exception.
public boolean foo(){
ListNode current = front;
ListNode runner = current.next;
while (current.next.next!=null){ //Looks two ahead for the end
if(current.data!=runner.data){ //They aren't equal, false
System.out.println(current.data); //just to see my data
System.out.println(runner.data); //debugging only
return false;
}
current = current.next.next; //increase by 2
runner = runner.next.next; // increase by 2
System.out.println(current.data + " ||" + runner.data); //again debugging
}
return true; // didn't register false, go ahead and true dat badboy.
}
public static void main (String[] args){
LinkedIntList list = new LinkedIntList();
list.add(1);
list.add(1);
list.add(3);
list.add(3);
list.add(5);
list.add(5);
System.out.println(list.foo());
}
Does someone see an obvious error here? I've tried running my while loop for current.next, as well as increasing my runner and current by one each time instead of two but none of it has worked.
You can't blindly use current.next.next without some checks first, since it's entirely possible that either current or current.next will be null.
If that's the case, you'll get a null pointer issue.
Assuming stuttered means double only (as per your example) rather than any multiple, it can be better down with the following algorithm:
def isStuttered(node):
while node != null:
# Check if only one item left.
if node.next == null:
return false
# Check if not a pair.
if node.data != node.next.data:
return false
# Advance to next pair, okay as we have 2+ items left.
node = node.next.next
return true
stuttered = isStuttered(head)
As an aside, if "stuttered" meant two or more of every item, that's a small change to the algorithm:
def isStuttered(node):
while node != null:
# Check if only one item left.
if node.next == null:
return false
# Check if not at least two.
val = node.data
if val != node.next.data:
return false
# Start with second item in set,
# advance to either new value or list end.
node = node.next
while node != null # note 'and' must short-circuit
and node.data == val:
node = node.next
return true
Instead of while (current.next.next!=null), check while (runner.next!=null). Also, You'll have to match the last two node's data after the while loop.
Assuming the list has an even number of elements as you mentioned in your question, the following changes in your code will yield correct output.
public boolean foo(){
ListNode current = front;
ListNode runner = current.next;
while (runner.next!=null){ //Looks two ahead for the end
if(current.data!=runner.data){ //They aren't equal, false
System.out.println(current.data); //just to see my data
System.out.println(runner.data); //debugging only
return false;
}
current = current.next.next; //increase by 2
runner = runner.next.next; // increase by 2
System.out.println(current.data + " ||" + runner.data); //again debugging
}
if(current.data!=runner.data){ //They aren't equal, false
System.out.println(current.data); //just to see my data
System.out.println(runner.data); //debugging only
return false;
}
return true; // didn't register false, go ahead and true dat badboy.
}
A better & clean implementation is as follows:
public boolean foo(){
ListNode current = front;
while (current != null){
if(current.next == null)
return false;
if(current.data != current.next.data)
return false;
current = current.next.next;
}
return true;
}

Should BST remove method remove a node's subtree aswell?

So I got an assignment of creating a BST in Java and so far it has all went well. However I got a question about the remove method. As I have implemented, if I remove node X, all of node X's subtrees will also be deleted. And I just wondered if this is a common implementation, or should I rearrange the nodes if I delete one? I am also to make a AVL tree out of this class, so I will need a trinodeRestructering method. I guess This would need some modification aswell if I go in and deletenodes?
Thiis is how my remove method works:
private TreeNode remove(TreeNode currN, int dataToRemove) {
if (dataToRemove < currN.getData()) {
if (currN.getLeft() != null) {
if (currN.getLeft().getData() == dataToRemove) {
currN.setLeft(null);
} else {
remove(currN.getLeft(), dataToRemove);
}
}
} else if (dataToRemove > currN.getData()) {
if (currN.getRight() != null) {
if (currN.getRight().getData() == dataToRemove) {
currN.setRight(null);
} else {
remove(currN.getRight(), dataToRemove);
}
}
}
return currN;
}
//visual representation
/--------85
/--------25
/--------20
10
********************************************************************
*******removed 20******
10
*******************************************************************
Added tree for post:
/--------85
/--------25
\--------24
/--------20
| /--------13
\--------12
| \--------11
10(root)
Here is some swapping I tried, it looks like really crappy, hard to read code:
if (dataToRemove < currN.getData()) {
if (currN.getLeft() != null) {
if (currN.getLeft().getData() == dataToRemove) {
//Om inga barn, sätt noden till null.
if(currN.getLeft().getLeft() == null && currN.getLeft().getRight() == null){
currN.setLeft(null);
}//Om noden enbart har höger barn
else if(currN.getLeft().getLeft() == null){
TreeNode old = currN.getLeft().getRight();// Gamla höger
currN.setLeft(currN.getLeft().getLeft()); //
currN.getLeft().getRight().setRight((old)); //
}//Om noden enbart har vänster barn.
else if(currN.getLeft().getRight() == null){
TreeNode old = currN.getLeft().getRight();// Gamla vänster
currN.setLeft(currN.getLeft().getLeft()); //
currN.getLeft().getLeft().setRight((old)); //
}//om två barn
else{
TreeNode oldRight = currN.getLeft().getRight();// null
currN.setLeft(currN.getLeft().getLeft()); //sätt current left till 11
currN.getLeft().setRight((oldRight)); // current left, right till 13
}
} else {
remove(currN.getLeft(), dataToRemove);
}
}
yeah there is a known implementation for that , when you want to delete node in the binary search tree you swap it with the right most leaf of its left subtree, or the left most leaf of its right subtree then delete that leaf.
For the AVL you will have to keep track in you recursive operations of the balance condition , whenever that balance condition is violated you will need to do some kind of rotation depending on the structure of this violation , if you do some research you will find a decent amount of resources explaining the exact algorithms for this.

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.
}

Categories

Resources