My Java program regarding Stacks made from LinkedLists. The task at hand was to merge two sorted stacks into one. I think I figured it out but it won't show any output and also it doesn't terminate. Can anyone help?
The "next" instance is pointing to the LinkedList's next element's address in the memory.
void mergeStacks()
{
Stacks sortedMain = new Stacks();
Stacks sorted1 = new Stacks();
Stacks sorted2 = new Stacks();
sorted1.push(1);
sorted1.push(2);
sorted1.push(3);
sorted2.push(4);
sorted2.push(5);
sorted2.push(6);
System.out.println("Stack 1");
sorted1.displayStack();
System.out.println("Stack 2");
sorted2.displayStack();
Node q = sorted1.head,p = sorted2.head,x = sortedMain.head;
while(q.next != null)
{
if(x == null)
{
sortedMain.push(sorted1.pop());
}
while(x.next != null)
{
sortedMain.push(sorted1.pop());
x = x.next;
}
q = q.next;
}
while(p.next != null)
{
while(x.next != null)
{
sortedMain.push(sorted2.pop());
x = x.next;
}
p = q.next;
}
System.out.println("Merged Stack\n");
sortedMain.displayStack();
}
So, I figured out the thing that is causing the console to not show anything. Apparently, the function "pop()" is not really returning int for some reason. Here's the method:
int pop()
{
int popped = 0;
if(isEmpty())
{
System.out.println("Stack is empty");
}
else
{
Node q = head;
while(q.next != null)
{
if(q.next.next == null)
{
popped = q.data;
q.next = null;
top = q;
}
}
}
return popped;
}
Output(With Debugger)
You have this inside the first while loop, which makes no sense:
if(x == null)
{
sortedMain.push(sorted1.pop());
}
while(x.next != null)
{
sortedMain.push(sorted1.pop());
x = x.next;
}
When x is null in the first if statement, how can you then use it in the next while statement? That should produce a null reference exception...
It seems like maybe you think that x would be somehow updated to the new head when you push something into an empty sortedMain? It won't be.
Also, is the "merged" stack supposed to be sorted? Your code appears to be trying to simply push all of the first sorted stack in, followed by pushing all of the second sorted stack in. This may or may not result in an overall sorted stack...depends on the elements within.
What I think should happen is you pop just the first two from each list and do a comparison, pushing whatever is greater/smaller (you didn't specify a sort order). Then you pop the next one from the side that was pushed and repeat. If one side becomes empty, then you'd simply push all the rest from the other side.
From the comments:
I don't really have to define an order in what they are going to
merge. I just want to merge them in whatever order they are into a
third stack. My strategy is to traverse through the first stack and
push all the elements into the main stack and do the same with the
next one.
Did you implement an isEmpty() method for your Stacks class? If so, this is what most people would expect to see:
while(!sorted1.isEmpty())
{
sortedMain.push(sorted1.pop());
}
while(!sorted2.isEmpty())
{
sortedMain.push(sorted2.pop());
}
If you haven't implemented an isEmpty() type method, then you could check to see if the head is null instead? (*I'm assuming you correctly set that to null when the stack is empty!):
while(sorted1.head != null)
{
sortedMain.push(sorted1.pop());
}
while(sorted2.head != null)
{
sortedMain.push(sorted2.pop());
}
Related
I need function with parameters as (LinkedList one,LinkedList two)
so, how to set/define the head and current for both the list seperately??
I dont know why this question was closed.
But I am new to java and need to solve this so can anybody help???
to check if a list is subset of another, I have this code from GeeksforGeeks
HERE IT IS CODE IF WE PASS NODE IN THE PARAMETER LIKE (Node one,Node two) but I want parameters as (linkedlist one,liked list two) so can anyone explain algorithm to do so???
static boolean checkSubSet(Node first, Node second) {
Node ptr1 = first, ptr2 = second;
// If both linked lists are empty,
// return true
if (first == null && second == null)
return true;
// Else If one is empty and
// other is not, return false
if (first == null ||
(first != null && second == null))
return false;
// Traverse the second list by
// picking nodes one by one
while (second != null)
{
// Initialize ptr2 with
// current node of second
ptr2 = second;
// Start matching first list
// with second list
while (ptr1 != null)
{
// If second list becomes empty and
// first not then return false
if (ptr2 == null)
return false;
// If data part is same, go to next
// of both lists
else if (ptr1.data == ptr2.data)
{
ptr1 = ptr1.next;
ptr2 = ptr2.next;
}
// If not equal then break the loop
else break;
}
// Return true if first list gets traversed
// completely that means it is matched.
if (ptr1 == null)
return true;
// Initialize ptr1 with first again
ptr1 = first;
// And go to next node of second list
second = second.next;
}
return false;
}
but how to do the same thing by passing the actual linked lists as a parameter for eg
static boolean checkSubSet(Node first, Node second){}
instead of this I want to do this
static boolean checkSubSet(LinkedList<Integer> list1,LinkedList<Integer> list2){}
You are trying to refactor your code so it accepts java.util.LinkedList as an argument. Well, I see that your code is from geeksforgeeks. The geeksforgeeks assumes that you have your own linked list implementation. It also assumes you have access to the next and data parts of the linked list nodes. Unfortunately, java LinkedList does not expose those, so your code is not useful for your question.
You need to design a new algorithm for the Java LinkedList. Since LinkedList is not a Set. It is not very meaningful to execute set functions over a LinkedList. However,
if you really need, you may use something like that:
return new HashSet(a).containsAll(new HashSet(b));
or, iterate over the lists to get what you want.
Ok so i need to deleted items from a circular list,as part of a bigger program that isnt working, and i cant seem to delete the last node passed in to the delete method, if the index passed in is 1 it will delete the 1st node in list and replace it, but when there is only one node left it has nothing to reference off, been at this hours. i will leave my delete method here
public void delete(int index)
{
if(Node.numOfUsers == 1)
{
first=null;
return;
}
//make curr the same as first node
int i = 1;
curr=first;
//if index passed in is 1, make temporary node same as one after first node
// if(size<1)
// {
// System.out.println("ok so this is where we are at");
// }
if(index==1)
{
temp=first.nextNode;
while(temp.nextNode!=first)
{
temp=temp.nextNode;
}
temp.nextNode=temp.nextNode.nextNode;
first=curr.nextNode;
}
else
{
//as long as i is not equal to node index-1 move current on 1 and increment i by 1
while(i != index-1)
{
curr=curr.nextNode;
i++;
}
//curr.nextNode is pointing to the node index we want and making it equal to one index above it
curr.nextNode=curr.nextNode.nextNode;
}
Node.numOfUsers--;
int size=size();
}
}
Looks like you're keeping track globally of a number of users. If this behaves the way I think it would, you could just have a small check at the beginning of this method so that if it is zero, you don't follow through with any of the logic following it.
if(Node.numOfUsers == 0) return;
This will make it so you don't bother executing any of the other logic.
A slightly better methodology to this problem might be to use the Node you want to delete as a parameter, rather than its index. This way you can avoid having to keep track of indices inside your data structure.
e.g.
public void delete(Node n) {
if(Node.numOfUsers == 0 || n == null) return; // 0 nodes or null parameter.
Node temp = first;
if(temp.next == null) { //only one node
temp = null; //simply delete it
} else {
while(temp.next != n) {
temp = temp.next;
if(temp == first) { //if we circle the entire list and don't find n, it doesn't exist.
return;
}
}
temp.next = n.next; // perform the switch, deleting n
}
}
EDIT: The above code follows the assumption that you'll have references to the node you want to delete. If this is not the case, using indices is just as good. You may also consider comparing values, however this would require you to assume that you have unique values in your nodes (and I don't know what you're restrictions are).
The logic for comparing values would be identical to the above, however instead of comparing if(temp == n) for example, you would compare if(temp.data.equals(n.data)). The use of the .equals() method is specifically for the String type, but you could modify it to work with whatever data type you are expecting, or better yet write a custom .equals method that allows the use of Generics for your abstract data type.
Here's the code I have so far, I thought returning it out of the function if my condition wasn't met would work but its stack overflowing...I know that I need to establish a base case but not really how....
public void removeOddSubtrees() {
if (root == null) {
return;
}
removeOddSubtrees(root);
}
private void removeOddSubtrees(Node root) {
removeOddSubtrees(root);
if (root.key % 2 != 0) {
root.right = null;
root.left = null;
root = null;
} else {
return;
}
}
i changed my helper function to the following, and i think it may be working now:
private void removeOddSubtrees(Node root){
if(root != null){
removeOddSubtrees(root.left);
removeOddSubtrees(root.right);
if(root.key % 2 != 0){
root.right = null;
root.left = null;
root = null;
}else{
return;
}
}
}
the code that you posted in the answer does work, but there are some simplifications that can be applied to it. Here's how I'd write it:
private void removeOddSubtrees(Node root) {
if (root == null) {
return;
}
if (root.key % 2 != 0) {
root.right = null;
root.left = null;
return;
}
removeOddSubtrees(root.left);
removeOddSubtrees(root.right);
}
First, I am usually checking the exit condition at the very top and exit the method immediately. That is, my condition does a return if root == null.
Second, there is no need to do root = null if root.key % 2 != 0. it actually has no effect: it places null in the parameter that the function receives but as this parameter is not used after that in this method then no one will ever see this null. Note that also the calling code will not be affected. assignment to parameters do not propagate outside of the called method.
Finally, I think it makes more sense to call removeOddSubtrees() on root.left and root.right only if the key is even. when the key is odd you are removing the left and right subtrees from the tree so doing a recursive call on these subtrees is probably meaningless as this entire subtree will be removed from the tree shortly after. Thus, in my code I do the recursive calls only if the key is even.
I am attempting to remove the last iterated element, with a custom iterator/linked list class. It for some reason only does this for the first item in the list (the head condition). Is there anything wrong with the conditions?
Should I, instead of the Else after If (prev=head), write If (next != null) to find middle nodes, and If (next = null) to find the last node?
Second question: to remove the items, should I also write prev.element = null (now I only have prev = null, and I suppose that erases the node but not its content.
Quite simply, what is wrong with my remove method, as I cannot figure it out myself. Thank you guys so much in advance. I have been working many hours with this but I still haven't got it working.
public E next() {
if (!hasNext())
throw new NoSuchElementException ();
prev = next;
E element = next.element;
next = next.next;
return element;
}
public void remove() {
if(prev == null) {
throw new IllegalStateException();
}
else {
if(prev == head){
head = head.next;
next = head;
}
else {
next = prev.next;
}
sizeOfList--;
prev = null;
}
}
You would need a while loop to be able to go through every node in the list until you hit the last one. As it is now, your code simply goes past the head, and then gets into the code that says sizeOfList-- and then prev = null;
You need something like this:
while (prev.next.next != null) {
prev = prev.next;
}
prev.next = null;
I do prev.next.next so that you can set the 2nd to last node in your linked list to point to a null value (which is done by prev.next = null;). Think of it this way: prev is the 2nd to last element in the list, prev.next is the last element, and obviously prev.next.next HAS to be null (because prev.next is LAST.) So once this is the case, delete the last element by setting the 2nd to last element to point to a null value.
And then decrement your list count.
This is my best guess with the given code
if(prev == head){ should change to if(prev.equals(head)){ Use equals method.
And I think you have to override equals method in the corresponding element class might definitely help.
== only checks for whether both variables refer to same object in memory, where as equals check Object state.
I hope it helps :).
This code would convert a linkedlist like : 1-> 2 -> 3 -> 4, into 1->3-2->4 (ie odd on left and even on right), except the problem caused by oddEvenSplitter function. This code will modify references by value. How to reuse the code in such situations where input is a reference ?
public void oddEvenSplitter (Node head, Node current, Node temp) {
if (head == null) {
head = temp;
current = temp;
} else {
current.next = temp;
current = temp;
}
}
public void oddFirst( ) {
if (first == null) {
throw new NoSuchElementException();
}
Node temp = first;
Node oddhead = null;
Node odd = null;
Node evenhead = null;
Node even = null;
while (temp != null) {
if (temp.element % 2 == 0) {
oddEvenSplitter(evenhead, even, temp);
} else {
oddEvenSplitter(oddhead, odd, temp);
}
}
if (oddhead != null) {
odd.next = evenhead;
first = oddhead;
}
}
Java does not have pass by reference. It always passes values. When you pass for example oddHead variable to oddEvenSplitter() method, what really happens is that a copy of oddHead variable is passed and from that point head and oddHead variables will be two separate variables, pointing on same object in the heap. So if you assign new value to head variable inside your method, the other one (oddHead) will remain unchanged. This is true for all other passed parameters as well.
As a solution you could create another object (like a DTO) and put all needed references inside it and pass it to your method. Then whenever you change those references, you will be able to get them in caller method.