java recursive linked list - java

private Node<T> recremoveFirst (Node<T> list, T element)
{
if (list == null)
return null;
else if(list.next == element)
return list.next;
else{
list.next = recremoveFirst(list.next, element);
return list;
}
}//calling recursive method
public void removeFirst(T element) {
recremoveFirst(head, element);
}
int choice;
Element elem;//constructor public Element (String name, int no)
LinkedList<Element> list = new LinkedList<Element>();
String name;
int number;
case 1 : // addFirst
System.out.print("Type name and number: ");
name = Cin.readString();
number = Cin.readInt();
list.addFirst(new Element(name,number));
break;
case 2 : // addLast
System.out.println("Enter name and number to add last element: ");
name = Cin.readString();
number = Cin.readInt();
list.addLast(new Element(name, number));
break;
case 3 : // removeFirst
list.removeFirst(elem);
When I'm trying to test this recursive method it shows me an error near list.removeFirst(elem);
and gives only suggestion initialize it even though it is initialized(if press initialize sets it to null). So I wonder what's is that I'm doing wrong.
Error mssage: Multiple markers at this line
- The local variable elem may not have been
initialized
- The constructor Element(Element) is
undefined

Because
Element elem;
could be null when
list.removeFirst(elem);
is executed.
So it will be
Element elem = null;
(You need to initialize it to use it.)
Anyway, i'm pretty sure you want something like this:
list.addFirst(elem = new Element(name,number));
So it
list.removeFirst(elem);
will remove the item added recently.
Anyway, are you sure you don't want to use removeFirstOccurrence ? Because removeFirst does a total different thing.
removeFirstOccurrence:
Removes the first occurrence of the specified element in this list (when traversing the list from head to tail). If the list does not contain the element, it is unchanged.
Anyway the reason you get this error, is not related to the recursion
Edit:
Well, you don't need any edit to addFirst since removeFirst will remove the first item in the list.
You just need to change
removeFirst(elem);
to
removeFirst();
In this case, if you don't use it in other places, you don't need anymore elem.

Related

Computing the size of a linked list using recursion/helper function - Java

Beginner here using Java (first year student), and am unable to get the below function to work. The goal is to use recursion and a helper function to compute the size of a singly linked list. When running the code against test lists, it keeps returning List changed to [].
I'm struggling in general with Java, so any help is appreciated. Thank you
public class MyLinked {
static class Node {
public Node(double item, Node next) {
this.item = item;
this.next = next;
}
public double item;
public Node next;
}
int N;
Node first;
public int sizeForward() {
return sizeForwardHelper(first);
}
public int sizeForwardHelper(Node n) {
Node current = first;
if (current == null) {
return 0;
} else {
first = first.next;
return sizeForward() + 1;
}
}
I believe I have the first portion set up to return 0 if there are no elements in the List. I believe it's the second part that isn't setting up correctly?
Thanks
Because it’s important for your learning to not spoonfeed you, I’ll describe an approach rather than provide code.
Use this fact:
The length of the list from any given node to the end is 1 plus the length measured from the next node (if there is one).
Usually (as would work here), recursive functions take this form:
If the terminating condition is true, return some value
Otherwise, return some value plus the recursively calculated value
When writing a recursive function, first decide on the terminating condition. In this case, n == null is the obvious choice, and you’d return 0, because you’ve run off the end of the list and the length of nothing (ie no node) is nothing. This also handles the empty list (when first is null) without any special code.
Otherwise, return 1 (the length of one node) plus the length of next.
Put that all together and you’ll have your answer.
——
Hint: The body of the recursive helper method can be coded using one short line if you use a ternary expression.
Instead of calling your wrapper function call your helper function recursively. Try the following:
public int sizeForward () {
return sizeForwardHelper (first);
}
public int sizeForwardHelper(Node n) {
if (n == null) // base case
return 0;
return sizeForwardHelper(n.next) + 1; // count this node + rest of list
}
Your method that computes the size of the list actually modifies the list in the process (with first = first.next; you set the first element to the next, and since there is a recursion, the first element always end up being null which is equivalent to an empty list with your design). Your method will work once, but your list will be empty afterwards.
To illustrate this, I added a print next to the instruction first = first.next; and wrote the following main:
public static void main(String[] args) {
Node n2 = new Node(2d, null);
Node n1 = new Node(1d, n2);
Node n = new Node(0, n1);
MyLinked l = new MyLinked(n);
System.out.println("The first element is: "+l.first.item);
System.out.println("The size is: "+l.sizeForward());
System.out.println("The first element is: "+l.first);
}
It yields:
The first element is: 0.0
first is set to 1.0
first is set to 2.0
first is set to null
The size is: 3
The first element is: null
Clearly, you should not modify the list while computing its size. The helper method should return 0 if the node is null (empty list), and 1 plus the size of the rest of the list otherwise. Here is the code.
public int sizeForwardHelper(Node n) {
if (n == null)
return 0;
else
return sizeForwardHelper(n.next) +1;
}
The goal of the arg free method sizeForward() is just to call the helper. The helper should not use it though.

Why does not a remove call to this Treeset effectively removes the element?

I was trying earlier to code a Dijkstra algorithm and faced out a problem with my implementation. I finally found a solultion but am still puzzled with the behaviour of the code.
What I am trying to do here is to iteratively mark the elements of a tree set. Everytime I mark an element, I remove it from the set and reinsert it, so the set places it at the end of the set (as the compareTo method tells it to do).
Doing so, I can take the first element of the set inside a while loop and stop when this first element is marked.
The following example is a minimal example:
public static void main(final String[] args) {
Set<Element> elements = new TreeSet<>();
elements.add(new Element(1));
elements.add(new Element(2));
elements.add(new Element(3));
elements.add(new Element(5));
elements.add(new Element(4));
System.err.println(elements.size());
while(!elements.iterator().next().mark){
Element element = elements.iterator().next();
element.mark();
elements.remove(element);
elements.add(element);
}
System.err.println(elements.size());
}
private static class Element implements Comparable<Element>{
private boolean mark = false;
private final int id;
public Element(int id){
this.id = id;
}
public void mark(){
this.mark = true;
}
#Override
public boolean equals(Object o){
Element other = (Element) o;
if(this.mark == other.mark){
return this.id == other.id;
} else {
return false;
}
}
#Override
public int compareTo(Element other){
if(this.mark == other.mark){
return this.id - other.id;
} else if(this.mark && !other.mark){
return 1;
} else {
return -1;
}
}
}
The problem here is that the line :
elements.remove(element);
Does not remove the element. However, running it in a debugger, I can see that the element has the exact same reference as the element in the set and is equal to it with respect to the equals method. So, when running the line :
elements.add(element);
The same element is added two times ; because I suppose that the insertion in a tree set uses a binary search and does not test the equality between the first element of the set and the newly inserted one.
I have understood that swapping the two lines :
element.mark();
elements.remove(element);
Actually solves the problem.
My question though is : why does a modified element of a tree set is not effectively removed when modified through an iterator ?
TreeSet uses compareTo in order to position the elements in a tree structure (and also to determine equality). If you put an element in the TreeSet and then modify a property that is used in your compareTo method (i.e. the mark in your case), remove can't locate that element, since it looks for it in a different location than the one in which the original element was inserted.
If you remove the element before changing it, you solve the problem, since the original element is found were it was inserted.

Recursively finding indexes of an INT in an ever-shrinking LispList

2nd-year Computer-Science student here, and as part of a set of exercises on recursion, we've been given some arbitrary problems to solve with LispLists. I'm stuck half-way through, so if anyone can point me in the right direction without explicitly giving me the answer, that would be great.
I need to find the positions of every instance of intToFind in the LispList listToCheck - the only conditions are that:
no additional arguments can be used
it has to be done recursively
For everyone who hasn't encountered LispLists - they don't have indexing, and the only methods you can call on them are:
.isEmpty() returns boolean
.head() returns the element at the 0th position
.tail() returns a LispList of all elements that aren't the head
.cons(value) adds value to the 'head' position - shifting everything else one down
There's also one method I wrote previously called:
recursiveCountLength(list) returns an int of the length of the passed LispList.
The list I've been testing on is: [2,3,4,2,5,12,2,5], so the result I'm looking for is [0,3,6] - with that out the way, here's what I've got so far (explanation of what I'm attempting after):
public static LispList<Integer>
recursivePositions(LispList<Integer> listToCheck, int intToFind)
{
if(listToCheck.isEmpty()) return listToCheck;
else {
// go through the array in its entirety once through,
// do everything else 'on the way back up'
LispList<Integer> positions = recursivePositions(listToCheck.tail(), intToFind);
//get the current length and current head
int currentInt = listToCheck.head();
int currentLength = recursiveCountLength(listToCheck);
//if a match is found, add the current length of the list to the list
if(currentInt == intToFind) return positions.cons(currentLength);
else return positions;
}
}
My current theory is that length of the array at each encounter of the int we're looking for (in this case 2) subtracted from the original length of the list (in this case 8) will give us the indexes.
2 first happens with a length of 8 (8-8 = index of 0, so indexes now [0]),
2 next happens with a length of 5 (8-5 = index of 3, so indexes now [0, 3]),
2 lastly happens at a length of 2 (8-2 = index of 6, so indexes now [0, 3, 6]).
The only problem is that I can't figure out how to get a static '8' - which leaves me to conclude that I'm approaching this in entirely the wrong way. Does anyone have any tips for me here? Any help would be hugely appreciated.
To clarify: a LispList is just a singly-linked-list (to differentiate from a Java LinkedList, which is double-linked).
Usually, you'd use a helper that carries information into the recursive calls, such as the current position and the positions already found (the current partial result).
LispList<Integer> positions (final int item, final LispList<Integer> list) {
return positionsAux( item, list, 0, new LispList<Integer>() );
}
private LispList<Integer> positionsAux (final int item,
final LispList<Integer> list,
final int position,
final LispList<Integer> result) {
if (list.isEmpty()) {
return result.reverse();
}
if (list.head().intValue() == item) {
result = result.cons(position);
}
return positionsAux( item, list.tail(), position + 1, result );
}
If that is not allowed, you need to carry the results backwards. If you assume that the recursive call has returned the correct result for your list.tail(), you need to add 1 to each found position to get the right result for your list. Then, you cons a 0 to the result if the current element matches. This version is less efficient than the first, because you traverse the current result list for every element of the input list (so it is O(n·m) instead of O(n), where n is the length of the input list and m the length of the result list).
LispList<Integer> positions (final int item, final LispList<Integer> list) {
if (list.isEmpty()) {
return new LispList<Integer>();
}
final LispList<Integer> tailResult = positions( item, list.tail() );
final LispList<Integer> result = tailResult.addToEach( 1 );
if (list.head().intValue() == item) {
return result.cons( 0 );
} else {
return result;
}
}
Implementing reverse() for the first version and addToEach(int) for the second is left as an exercise to the reader.
You need at least 3 arguments. Pretty sure adding more arguments is okay since he allows helper methods (because otherwise you could just make your method call the helper method which has more arguments).
Simplest way recursively:
public static LispList<Integer> positions(LispList<Integer> list, Integer key, Integer position){
if (list.isEmpty()) return LispList.empty();
if (list.head().equals(key)) return positions(list.tail(), key, position+1).cons(position);
return positions(list.tail(), key, position+1);
}

Deleting the last element from an array

I am trying to delete an element from an array depending on the method's argument. If the argument is the last element's position, I can't use the for loop and end up specifying an if statement just to satisfy that. Also trying to return the current name in that position after the deletion. I have tested and the following code works.
I am trying to see if there is a better way of producing the same result without the extra if statement. I tried looking up the Arrays Class and no static method there that seems to help either. Please advice if there is a better way of doing this method. Thanks.
public class ArrayTester {
public static String[] array1 = new String[100];
public static void main(String[] args) {
remove(50);
System.out.println(remove(50));
}
public static String remove(int name) {
if(name == 99){
array1[name] = null;
return array1[name];
}
else if (name >= 0 && name < 99){
for (int i=name; i < array1.length-1; i++){
array1[i] = array1[i+1];
}
return array1[name];
}
return null;
}
}
And with ArrayList??
import java.util.ArrayList;
public class RemoveArrayListElement {
public static void main(String[] args) {
ArrayList<String> arlist=new ArrayList<String>();
//<E> it is return type of ArrayList
arlist.add("First Element"); // adding element in ArrayList
arlist.add("Second Element");
arlist.add("Third Element");
arlist.add("forth Element");
arlist.add("fifth Element");
// remove array list element by index number
arlist.remove(3);
// remove ArrayList element by Object value
arlist.remove("fifth Element");
// get elements of ArrayList
for(int i=0;i<arlist.size();i++)
{
System.out.println("ArrayList Element "+i+" :"+arlist.get(i));
}
}
}
Output:
Remove ArrayList Element 0 :First Element
Remove ArrayList Element 1 :Second Element
Remove ArrayList Element 2 :Third Element
With ArrayList is easier, isn't it?
You can simplify your code a little by excluding the if. Unfortunately, the loop has to stay - arrays provide contiguous storage, so you need to move the data if you are to delete an item in the middle of the array.
public static String remove(int index) {
// Note the use of "index" instead of "name"
if (index < 0 || index >= array1.length) {
// A more common approach is to throw an exception,
// but your code returns null for out-of-range index
return null;
}
for (int i = index; i < array1.length-1 ; i++) {
array1[i] = array1[i+1];
}
// Unconditionally set null in the last element of the array
array1[array1.length-1] = null;
return array1[index];
}
Looking at your code, you seem to want something like this -
if (name == 99) {
try {
return array1[name];
} finally {
array1[name] = null;
}
}
array1 = Arrays.copyOf(array1, 99);
Sounds to me like you would be better off using an ArrayList. Arrays aren't really made for what you're doing. But you could also just null the value at the desired location and run the java.util.Arrays.sort method on the array. Something like this (I'm winging it, but this would be close):
public static String remove(int name) {
String returnValue = array1[name];
array1[name] = null;
java.util.Arrays.sort(array1);
return returnValue;
}
This is going to leave you with a sorted array, but you're already shifting them out of their original indices anyway so that may or may not matter to you.
Another option would be to simply add a if (array1[index] != null) conditional to all of your code handling that array. That way you wouldn't have to shift your values around in the array and your code would just skip over any null values it runs into.

Java Splitting integer Linked List

I need to write a method that starts with a single linked list of integers and a special value called the splitting value. The elements of the list are in no particular order. The method divides the nodes into two linked lists: one containing all the nodes that contain an element less than the splitting value and one that contains all the other nodes. If the original linked list had any repeated integers (i.e., any two or more nodes with the same element in them), then the new linked list that has this element should have the same number of nodes that repeat this element. The method returns two head references - one for each of the linked lists that were created.
I have been spent countless hours trying to get this right and think this is the closest but I have an error while compiling that my copyTail* IntNodes may not be initialized. I also may be completely wrong with my code....
Any help pointing in me in the right direction??
public static IntNode[ ] listSplitLessGreater(IntNode source, int splitter)
{
IntNode copyHeadLess;
IntNode copyTailLess;
IntNode copyHeadGreater;
IntNode copyTailGreater;
IntNode[ ] answer = new IntNode[2];
boolean less = true;
boolean greater = true;
// Handle the special case of the empty list.
if (source == null)
return answer; // The answer has two null references .
//Split list into two lists less and greater/equal than splitter.
while (source.link != null)
{
if (splitter < source.data)
{
if (less)
{
copyHeadLess = new IntNode(source.data, null);
copyTailLess = copyHeadLess;
less=false;
}
else
{
source = source.link;
copyTailLess.addNodeAfter(source.data);
copyTailLess = copyTailLess.link;
}
}
else
{
if (greater)
{
copyHeadGreater = new IntNode(source.data, null);
copyTailGreater = copyHeadGreater;
greater=false;
}
else
{
source = source.link;
copyTailGreater.addNodeAfter(source.data);
copyTailGreater = copyTailGreater.link;
}
}
}
//Return Head References
answer[0] = copyHeadLess;
answer[1] = copyHeadGreater;
return answer;
}
I think you're making it more complicated than it needs to be, by modelling a list just with a single class (IntNode). If you model it as "the list" and "a node in the list" then it's easy to have an empty list. You also don't need to keep track of both the head and the tail - the list can do that. At that point, it's very simple:
Create two empty lists, one for "lower" and one for "not lower"
Iterate over the original list:
Work out which list to add the element to
Add the element
Return both lists (e.g. using an array as you have done)
Note that even without that, you can make your code simpler by just using null to mean "I haven't got this list yet". At the moment your code won't compile, as copyHeadLess etc aren't definitely assigned when they're used. You know that you won't try to use them until they've been assigned, but the compiler doesn't. I'd still recommend the remodelling approach though :)
If source isn't null, but source.link is null (list is only composed of one element) then you never assign to your copyHeadLess, etc, variables. Try initializing them to null or whatever the default is:
IntNode copyHeadLess = null;
IntNode copyTailLess = null;
IntNode copyHeadGreater = null;
IntNode copyTailGreater = null;
IntNode[ ] answer = new IntNode[2];
boolean less = true;
boolean greater = true;
// Handle the special case of the empty list.
if (source == null)
return answer; // The answer has two null references .
//Split list into two lists less and greater/equal than splitter.
while (source.link != null)
{
// what about case where source isn't null but source.link is null?
}
//Return Head References
answer[0] = copyHeadLess; // this may have never been assigned in your original code
answer[1] = copyHeadGreater; // this may have never been assigned in your original code
return answer;
}

Categories