Java Circular Linked List,Remove Node not working properly - java

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.

Related

Can someone explain the algorithm?

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.

Finding the maximum value of a linked list recursively

I need to write a Java method called findMax within a class called Node, which has two instance variables: int value and Node next. The method takes no parameters, and must return the greatest value of a linked list. Within the context of the program, the method will always be called by the first Node of a linked list (except for the recursive calls). I was struggling to complete the method when I accidentally found a working solution:
public int findMax(){
int max = value;
if(next == null){
return max;
}
else{
if(max <= next.findMax()){
max = next.value;
}
else return max;
}
return next.findMax();
}
This method properly returned the largest value of each linked list I tested it for. However, since I found this solution by trying random arrangements of code, I don't really feel like I understand what's going on here. Can anyone explain to me how/why this works? Also, if there is a more efficient solution, how would it be implemented?
You can imagine a linked list looking something like this:
val1 -> val2 -> val3 -> null
Recursion works on the principle that eventually, the input you pass into the function can be handled without recursing further. In your case, node.findMax() can be handled if the next pointer is null. That is, the max of a linked list of size 1 is simply the value (base case of the recursion), the max of any other linked list is the max of the value of that node or the max of the remaining elements.
ie) for the Node n3 with value val3, n3.findMax() simply returns the value
For any other node n, n.findMax() returns the maximum of the node's value or n.next.findMax()
The way this looks in the example at the start is:
n1.findMax()
= Max(n1.value, n2.findMax())
= Max(val1, Max(n2.value, n3.findMax())
= Max(val1, Max(val2, n3.value)) // Since n3.next == null
= Max(val1, Max(val2, val3))
which is simply the maximum over the whole list
Edit: Based on the discussion above, although what you said might work, there is a simpler way of writing the program:
int findMax() {
if (this.next == null) {
return this.value;
} else {
return Math.max(this.value, this.next.findMax());
}
}
Edit 2: A break down of why your code works (and why it's bad):
public int findMax(){
// This variable doesn't serve much purpose
int max = value;
if(next == null){
return max;
}
else{
// This if condition simply prevents us from following
// the else block below but the stuff inside does nothing.
if(max <= next.findMax()){
// max is never used again if you are here.
max = next.value;
}
else return max;
}
// We now compute findMax() again, leading to serious inefficiency
return next.findMax();
}
Why is this inefficient? Because each call to findMax() on a node makes two subsequent calls to findMax() on the next node. Each of those calls will generate two more calls, etc.
The way to fix this up is by storing the result of next.findMax() like so:
public int findMax() {
if (next == null) {
return value;
}
else {
int maxOfRest = next.findMax();
if(value <= maxOfRest) {
return maxOfRest;
}
else return value;
}
}

Recursively delete the last occurrence in a linked list, Java

class Link{
private int value;
private Link next;
}
I am asked to write a recursive method to delete last occurrence of a certain value, say 4.
before 2->3->4->5->4->2
after 2->3->4->5->2
The last occurrence only. I know how to delete all occurrence but I can't tell if its the last occurrence. No helper method is allowed.
The one to delete all occurrence
public Link deleteAll(){
if (next == null){
return value==4? null:this;
}else{
if (value == 4){
return next.deleteAll();
}
next = next.deleteAll();
return this;
}
}
You can declare a pointer to the last occurred node and delete that node when reached the last element in list. Following steps explains that -
Declare two pointers one is next as in your above code another can be temp.
Iterate through list using next like you doing in deleteAll method above.
If you find the node you looking for assign that node to temp.In your case 4.
When next is null you reached the end of list now delete, whatever node is in temp delete that node. If temp is still null than no node found in given key.
EDIT:
Possible pseudo Code in case of recursion:
public void deleteLast(Node node,Node temp,Node prev, int data)
{
if(node==null)
{
if(temp!=null && temp.next.next!=null){
temp.next = temp.next.next;}
if(temp.next.next==null)
temp.next = null;
return;
}
if(node.data==data)
{
temp = prev;
}
prev = node;
deleteLast(node.next, temp, prev, int data);
}
Above code should be able to solve your problem. I made some edit in my approach which should be obvious from the code but let me describe it below
I added a prev pointer. Because if we want to delete a particular node we need to assign its next to prev node's next.So, we need the prev node not the node that we want to delete.
I think this change will follow in iterative approach too.
Not really answering your exact question, but as an alternative option, you might consider the following.
Write a recursive method to delete the first occurrence of a specified value, something like this:
public Link deleteFirst(int target) {
if (value == target) {
return next;
}
next = (next == null) ? null : next.deleteFirst(target);
return this;
}
Then you could write a reverse() method as either an iterative or recursive method as you see fit. I haven't included this, but googling should show some useful ideas.
Finally the method to remove the last occurrence of a value from the linked list could then be written like this:
public Link deleteLast(int target) {
return reverse().deleteFirst(target).reverse();
}
Note that as long as your reverse() method is linear complexity, this operation will be linear complexity as well, although constants will be higher than necessary.
The trick is to do the work on the way back -- there is no need for additional parameters, helpers or assumptions at all:
Link deleteLast(int target) {
if (next == null) {
return null;
}
Link deleted = next.deleteLast(target);
if (deleted == null) {
return value == target ? this : null;
}
if (deleted == next) {
next = deleted.next;
}
return deleted;
}

Return the number of elements in a linked list recursively

I have the following recursive method in a class called ImageNode which is passed the head(this - the start of the linked list) from a class called Image.
I thought my code would recursively go through each node, increase the count then when its at the end return the count, unfortunatly not. Where am I going wrong?
private int countRec() {
int count = 1;
ImageNode node = this;
if (node.next != null ){
node = node.next;
count++;
countRec();
}
return count;
}
You're ignoring the result of countRec() - and you're iterating within the recursive call, defeating the purpose. (You're also making a recursive call on the same object, with no parameters and no change in state... so that can't do any good.) My recursive approach would be based on a design of:
If the next node is null, then the size of the list is 1
Otherwise, the size is 1 + the size from the next node onwards.
So:
private int countRec() {
return next == null ? 1 : 1 + next.countRec();
}
Now that doesn't allow for a list of length 0 of course... you probably want to separate the idea of the list from the node, in which case the list class would have something like:
public int count() {
return head == null ? 0 : head.countRec();
}
where the value of head is a reference to the head node if there is one, or null otherwise.
Of course, this will be O(n) in time and space. You can get O(1) space using iteration instead of recursion, and O(1) time by just keeping the size of the list as an instance variable in the list, updating it when you need to. I'm hoping that this question was based on an educational requirement rather than real code though - in production code, you'd just use the collections provided already.
The definition of a recursive function is it is defined in terms of itself: i.e. the count of elements in a list is equal to 0 if an empty list; otherwise it is equal to 1 + the count of the rest of the elements of the list.
The italicized portion of the above definition is where the function call gets made.
private int countRec(ImageNode node) {
if (node == null) {
return 0;
} else {
return 1 + countRec(node);
}
}
A recursive function is useful when it uses the result of the further calls to solve his problem (like an inductive step on mathematics). Your function are not using the return for the countRec() call for anything, and you're still trying to solve the issue without the recursion help. You can solve it by using it, as:
if(node.next != null)
{
node = node.next;
count = countRec()+1;
}
return count;
Of course, since we're telling about getting your code better, you wouldn't even need to use this node var, just doing:
private int countRec() {
if (this.next != null )
return (this.next.countRec())+1;
return 1;
}
Hope that helps.

How to convert a list to BSTree recursively?

I tried to convert a List from 3{1{,2{,}},5{4{,},6{,}}}
to a Binary Tree like this
3
1 5
2 4 6
I thought it would be easier to use recursion but I get stuck.
public void ListToTree (ArrayList al) {
Iterator it = al.iterator();
// n is the Tree's root
BSTnode n = new BSTnode(it.next());
recurse(al,it,n);
}
void recurse (ArrayList al, Iterator it, BSTnode n) {
if(!it.hasNext()) return;
Object element = it.next();
if(element=="{"){
recurse(al,it,n.left());
return;
} else if (element==",") {
recurse(al,it,n.right());
return;
} else if (element =="}") {
}
}
I don't know how to proceed and was wondering if it's the right track. Please give me some hints how to solve it. Moreover, I realize I often get stuck on recursive questions. Is it because I always want to break it down? Should I just think top-down and double-check if it's correct? Thanks in advance !
Firstly: are you bound to that terrible list representation? You can easily build a BST based on the BST rules with this code:
void insert(Node n, int value) {
if(n == null) {
n = new Node(value);
} else if(value < n.value) {
if(n.left == null) {
n.left = new Node(value);
return;
}
insert(n.left, value);
} else if(value > n.value) {
if(n.right == null) {
n.right = new Node(value);
return;
}
insert(n.right, value);
}
}
You really don't have to pass the iterator. Just use the values from the list. Also it is usually unadvised to use implementation types in method signatures. (i.e. ArrayList -> List).
Another big mistake here is that you don't use == for value comparison, that is for reference comparison. Use equals instead, but you should downcast the Object after an instanceof test e.g.:
if( element instanceof String) {
String seperator = (String)element;
if("{".equals(separator))
//do sth...
Btw the thing you are missing from the code is the actual insertion and the backwards navigation.
After you found the right subtree by navigating with the {-s and ,-s, check whether the element is an Integer then set it as a value for the current node. Backwards navigation should be in the } branch by either returning one level from the recusion and some tricks or calling the method on the parent of the actual node.
But I don't suggest you to follow this direction, it is much easier to just use the values from the list and the simple insertion method.

Categories

Resources