How to collect the result of a recursive method - java

I iterate through a tree structure to collect the paths of the leaf nodes. Which way do you prefer to collect the result of the operation:
a) merge the results of the children and return this
private Collection<String> extractPaths(final Element element, final IPath parentPath) {
final IPath path = parentPath.append(element.getLabel());
final Collection<Element> children = getElementChildren(element);
if (children.isEmpty())
return Collections.singletonList(path.toString());
final Set<String> result = new TreeSet<String>();
for (final Element child : children)
result.addAll(extractPaths(child, path));
return result;
}
b) provide the result collection as a parameter and add new elements in each recursion step
private void extractPaths(final Element element, final IPath parentPath, final Set<String> result) {
final IPath path = parentPath.append(element.getLabel());
final Collection<Element> children = getElementChildren(element);
if (children.isEmpty())
result.add(path.toString());
for (final Element child : children)
extractPaths(child, path, result);
}

Both can be used without any problems. Though, former solution is more clean since it doesn't change input parameters. No side effects is in the nature of functional programming.

I assume the latter is meant to call extractPaths(child, path, result)?
The latter form will be more efficient, as it doesn't need to copy items at every level of recursion. As Boris says, it's less functionally clean - but Java doesn't really provide immutable collections with appropriate methods to create new collections based on them efficiently.
In terms of making it pleasant to call, you could provide a wrapper in the style of the first option which just creates a new set and calls the second option. That's probably what I'd do:
private Collection<String> extractPaths(Element element, IPath parentPath) {
Set<String> ret = new HashSet<String>();
extractPaths(element, parentPath, ret);
return ret;
}
Another alternative is to change the third parameter from a Set<String> to some sort of "collector" interface: you tell it that you've found a result, without specifying what to do with it. Indeed, the collector could return a new collector to use from then on - leaving it up to the implementation to decide whether to make a functionally-clean "create a new set" version, or hide side-effects in the collector which would just return itself again for reuse.

To provide the most convenient and flexible interface to your clients, write it as a class that implements Iterator<E>.
This means that the client can loop through the items found during the recursion, but they don't have to implement their "for each" code as a callback (Java doesn't have a pretty way to do that), and they can even "pause" the operation and continue it later, outside of the scope in which they began it (or abandon it at any point).
It's the trickiest to implement though. If the data structure you're traversing is a tree-like structure with parent pointers in each node then you need no other data than the current node. To get to the next node, look for a first child. If there is one, that's the next node. Otherwise try the next sibling. If there isn't one, get the parent and try to get its next sibling, and so on until you hit a null in which case there are no more items.
As a quick and dirty example, here's a treenode-like class, breaking all the rules about encapsulation to save some space here:
class SimpleNode
{
String name;
public SimpleNode parent, firstChild, nextSibling;
public SimpleNode(String n) { name = n; }
public void add(SimpleNode c)
{
c.parent = this;
c.nextSibling = firstChild;
firstChild = c;
}
public String getIndent()
{
StringBuffer i = new StringBuffer();
for (SimpleNode n = this; n != null; n = n.parent)
i.append(" ");
return i.toString();
}
}
Now let's create a tree from it:
SimpleNode root = new SimpleNode("root");
SimpleNode fruit = new SimpleNode("fruit");
root.add(fruit);
fruit.add(new SimpleNode("pear"));
fruit.add(new SimpleNode("banana"));
fruit.add(new SimpleNode("apple"));
SimpleNode companies = new SimpleNode("companies");
root.add(companies);
companies.add(new SimpleNode("apple"));
companies.add(new SimpleNode("sun"));
companies.add(new SimpleNode("microsoft"));
SimpleNode colours = new SimpleNode("colours");
root.add(colours);
colours.add(new SimpleNode("orange"));
colours.add(new SimpleNode("red"));
colours.add(new SimpleNode("blue"));
Now, to spell this out for anyone new to this idea, what we want to be able to do is this:
for (final SimpleNode n : new SimpleNodeIterator(root))
System.out.println(n.getIndent() + "- " + n.name);
And get this (I've made the above code generate something that looks like a hierarchical bullet list in SO):
root
colours
blue
red
orange
companies
microsoft
sun
apple
fruit
apple
banana
pear
To do this, we have to map some standard operations onto our SimpleNode class:
class SimpleNodeIterator extends TreeIterator<SimpleNode>
{
public SimpleNodeIterator(SimpleNode root)
{ super(root); }
protected SimpleNode getFirstChild(SimpleNode of)
{ return of.firstChild; }
protected SimpleNode getNextSibling(SimpleNode of)
{ return of.nextSibling; }
protected SimpleNode getParent(SimpleNode of)
{ return of.parent; }
}
And finally, at the bottom of our design, TreeIterator<TNode> is a very reusable abstract base class that does the rest, now we've told it how to navigate our node class:
abstract class TreeIterator<TNode> implements Iterator<TNode>,
Iterable<TNode>
{
private TNode _next;
protected TreeIterator(TNode root)
{ _next = root; }
public Iterator<TNode> iterator()
{ return this; }
public void remove()
{ throw new UnsupportedOperationException(); }
public boolean hasNext()
{ return (_next != null); }
public TNode next()
{
if (_next == null)
throw new NoSuchElementException();
TNode current = _next;
_next = getFirstChild(current);
for (TNode ancestor = current;
(ancestor != null) && (_next == null);
ancestor = getParent(ancestor))
{
_next = getNextSibling(ancestor);
}
return current;
}
protected abstract TNode getFirstChild(TNode of);
protected abstract TNode getNextSibling(TNode of);
protected abstract TNode getParent(TNode of);
}
(It's mildly naughty in that it implements Iterator<E> and Iterable<E> on the same object. This just means that you have to new up a fresh object in order to iterate a second time; don't try to reuse the same object).
This means that if your hierarchical structure consists of nodes for which you can define those three simple navigational operations, then all you have to do is derive your own equivalent of SimpleNodeIterator. This makes it very easy to enable this capability on any tree implementation.
If what you're iterating doesn't have a way to get the parent, you need to keep a stack during the iteration. Each time you descend a level, you push the state for the current level onto the stack. When you finish iterating at the current level, you pop the last state off the stack and continue with it. When the stack is empty, you're done. This means you have some intermediate storage, but its maximum size is proportional to the depth of the recursion rather than the number of items, so assuming the data is roughly balanced then it should be a lot more storage-efficient than copying all the items to a list before you return it.

The final solution I found after some refactoring is to implement variant b) but to pass a Visitor instead of the result collection:
private void traverse(final Element element, final Visitor... visitors) {
for (final Visitor visitor : visitors)
// push e.g. the parent path to the stack
visitor.push(visitor.visit(element));
for (final Element child: getElementChildren(element))
traverse(child, visitors);
for (final Visitor visitor : visitors)
visitor.pop();
}
The Visitor provides also a stack to carry the information about the parent path. This solution allows me to separate the traversal logic from the collection logic, without the need of the more complex TreeIterator implementation.
private class CollectPathsVisitor extends ElementVisitor {
public final Set<String> paths = new TreeSet<String>();
public Object visit(Element element) {
final IPath parentPath = (IPath) peek();
final IPath path = parentPath.append(element.getLabel());
if (!hasChildren(element))
paths.add(path);
return path;
}
}

I usually prefer to return the result, since i think
$result = extractPaths($arg,$arg2);
is more clear than
extractPaths($arg,$arg2,$result);
but it's entirely based on taste.

I would choose option b, since it would create fewer objects and thereby be more efficient. Solution a feels more like the way you would do it in a functional language, but that relies on assumptions that don't hold in Java.

If you pass in the object to be built, if you had an exception that you caught in a place where you had a reference to that object, then you would at least have the data you built up until the exception was thrown.
I personally pass in Builders as arguments when multiple methods will be "building" on it, including recursion. This way you only have a single object being built, and miss out lots of Set, Map or List copying.

in this specific case I prefer the latter solution since:
it avoids creating throw-away collections
your algorithm implemented in this way cannot get any gain from being "functional"
imho there is no real benefit of being functional without a really good reason f (e.g. using threads).

pass a collection as parameter for this method

Later will create less objects in memory (as already said) but also manages each tree path only once: when extracted and stored in the Set result it is not 'addedAll' to any other set again and again and again.

Related

How to find the largest Count of Objects assosiated with the same Object

I have a Mentor class in which I have an ID for each mentor and an ArrayList of mentee IDs, like this:
public class Mentor {
int mentorId;
ArrayList<Integer> mentees = new ArrayList<>();
public Mentor(int mentorId, ArrayList<Integer> mentees) {
this.mentorId = mentorId;
this.mentees = mentees ;
}
}
The problem is that some mentees can be mentors too.
I would like to somehow get a count of all of the mentees associated to the top mentor as well as how many mentors are under the top mentor.
So, basically, if a mentor has a mentee, who is also a mentor, then this mentor's mentees are also associated to the top mentor.
So, my thinking was to loop through the mentee-list and see if any of the id's match an ID of Mentor. If true, Add this mentor's list of mentees to a list and loop again, but this will not work dynamically.
My main class looks something like this:
ArrayList<Mentor> mentors = new ArrayList<>();
ArrayList<Integer> mentees = new ArrayList<>();
ArrayList<Integer> mentees2 = new ArrayList<>();
mentees.add(2);
mentees.add(3);
mentees2.add(4);
mentees2.add(5);
//[1,{2,3}]
mentors.add(new Mentor(1, mentees));
//[2,{4,5}]
mentors.add(new Mentor(2, mentees2));
int mentorCount = 0;
int menteeCount = 0;
for (Mentor mentor : mentors) {
for (Integer mentee : mentees) {
mentorCount++;
if (mentee == mentor.mentorId){
mentorCount++;
//add each mentee to arraylist and start the process again, but is there an easier way to do this.
}
}
}
I was wondering if there is a way of solving this, maybe using streams?
I would recommend using good object oriented design, you shouldn't just use integer id's like that, because in this situation you could simply make an ArrayList of Person objects Where Mentees, and Mentors Inherit from Person. Then you can check if a Person is an instance of Mentee versus Mentor:
for (Person p : people) {
if (p instanceof Mentor)
{
// Mentor logic
}
if (p instanceof Mentee)
{
// Mentee Logic
}
}
Firstly, let's briefly recap the task.
You have a set of mentors, each mentor has a collection of mentees. Some of them might happen also to be mentors and so on.
Class design
From the perspective of class design, the solution is pretty simple: you need only one class to describe this relationship - Mentor. And each Mentor should hold a reference to a collection of Mentors (not integer ids).
In your domain model, as you described it, there's no substantial difference between a mentor and a mentee. Mentor points to other mentors - is a simplest way to model that. Mentee is just an edge case, a mentor which has an empty collection of mentors.
You don't need to include classes and features in your application that doesn't bring benefit.
Data structure
From the perspective of data structures, this problem can be described very well with an acyclic disjointed Graph.
Acyclic because if we consider the relationship between mentors when a mentor could indirectly point at themself (i.e. a mentor N has a mentee, with in tern points to another mentee that happens to be also a mentor of mentor N) the task becomes ambiguous. Therefore, I'm making an assumption that no one can be a mentor to himself.
I also depicted this data structure as disjointed because mentors in this model (as well as in real life) can form isolated groups, which in graph theory called connected components. That means that there could be several mentors with the same count of mentee, which happens to be the largest.
Depth first search
In order to find all the vertices (mentors) connected with a particular mentor, we have a classic traversal algorithm, which is called Depth first search (DFS). The core idea of DFS is to peek a single neighbor of the given vertex, then in turn peek one of its neighbors and so on until the hit the vertex that doesn't point to the other vertex (i.e. maximum depth is reached). And then it should be done with every other neighbors of the previously visited vertices.
There are two ways to implement DFS.
Iterative approach
For that, we need a stack. It will store all unvisited neighbors of the previously encountered vertexes. The last vertex from each list of neighbors in every branch will be explored first because it will be placed on the top of the stack. Then it will get removed from the stack and it's neighbors will be placed on the stack. This process repeats in a loop until the stack contains at least one element.
The most performant choice of collection for the stack is ArrayDeque.
Because this approach require continuous modification of the stack by adding and removing vertices, it isn't suitable to be implemented with Stream IPA.
Recursive approach
The overall principle is the same as described above, but we don't need to provide a stack explosively. The call stack of the JVM will be utilized for that purpose.
With this approach, there's also some room to apply streams. For that reason, I've chosen the recursive implementation. Also, its code is probably a bit easier to understand. But keep in mind that recursion has certain limitations, especially in Java, and not suitable for processing a large set of data.
Recursion
A quick recap on recursion.
Every recursive implementation consists of two parts:
Base case - that represents a simple edge-case for which the outcome is known in advance. For this task, the base case is the given vertex has no neighbors. That means menteesCount of this vertex needs to be set to 0 because it has no mentee. And the return value for the base case is 1 because this vertex, in turn, is a valid mentee of another vertex that holds a reference to it.
Recursive case - a part of a solution where recursive calls a made and where the main logic resides.
The recursive case could be implemented using streams and entails recursive invocation of the for every neighbor of the given vertex. Each of these values will contribute to the menteesCount of the given vertex.
The value returned by the method will be menteesCount + 1 because for the vertex which triggered this method call, the given vertex will be a mentee as well as its mentees.
Implementation
Class mentor basically serves as a vertex of the graph. Each vertex has a unique id and collection of adjacent vertexes.
Also, in order to reuse values obtained by performing DFS I've added a field menteesCount which is initially initialized to -1 in order to distinguish between vertices that has no adjacent vertices (i.e. menteesCount has to be 0) and vertices which value wasn't calculated. Every value will be established only ones and then reused (another approach will be to utilize a map for that purpose).
Method getTopMentors() iterates over the collection of vertices and invokes DFS for every vertex which value wasn't calculated yet. This method returns a list of mentors with the highest number of associated mentees
Method addMentor() that takes a vertex id, and id of its neighbors (if any) was added in order to interact with the graph in a convenient way.
Map mentorById contains every vertex that was added in the graph and, as its name suggests, allows retrieving it based on the vertex id.
public class MentorGraph {
private Map<Integer, Mentor> mentorById = new HashMap<>();
public void addMentor(int mentorId, int... menteeIds) {
Mentor mentor = mentorById.computeIfAbsent(mentorId, Mentor::new);
for (int menteeId: menteeIds) {
mentor.addMentee(mentorById.computeIfAbsent(menteeId, Mentor::new));
}
}
public List<Mentor> getTopMentors() {
List<Mentor> topMentors = new ArrayList<>();
for (Mentor mentor: mentorById.values()) {
if (mentor.getCount() != -1) continue;
performDFS(mentor);
if (topMentors.isEmpty() || mentor.getCount() == topMentors.get(0).getCount()) {
topMentors.add(mentor);
} else if (mentor.getCount() > topMentors.get(0).getCount()) {
topMentors.clear();
topMentors.add(mentor);
}
}
return topMentors;
}
private int performDFS(Mentor mentor) {
if (mentor.getCount() == -1 && mentor.getMentees().isEmpty()) { // base case
mentor.setCount(0);
return 1;
}
int menteeCount = // recursive case
mentor.getMentees().stream()
.mapToInt(m -> m.getCount() == -1 ? performDFS(m) : m.getCount() + 1)
.sum();
mentor.setCount(menteeCount);
return menteeCount + 1;
}
public static class Mentor {
private int id;
private Set<Mentor> mentees = new HashSet<>();
private int menteesCount = -1;
public Mentor(int id) {
this.id = id;
}
public boolean addMentee(Mentor mentee) {
return mentees.add(mentee);
}
// getters, setter for menteesCount, equeals/hashCode
}
}
An example of the graph used as a demo.
main() - the code models the graph shown above
public static void main(String[] args) {
MentorGraph graph = new MentorGraph();
graph.addMentor(1, 3, 4);
graph.addMentor(2, 5, 6, 7);
graph.addMentor(3, 8, 9);
graph.addMentor(4, 10);
graph.addMentor(5, 11, 12);
graph.addMentor(6);
graph.addMentor(7, 13, 14);
graph.addMentor(8);
graph.addMentor(9, 16, 17, 18);
graph.addMentor(10);
graph.addMentor(11, 18);
graph.addMentor(12);
graph.addMentor(13);
graph.addMentor(14, 19, 20);
graph.addMentor(15);
graph.addMentor(16, 21, 22);
graph.addMentor(17);
graph.addMentor(18);
graph.addMentor(19);
graph.addMentor(20);
graph.addMentor(21);
graph.addMentor(22);
graph.getTopMentors()
.forEach(m -> System.out.printf("mentorId: %d\tmentees: %d\n", m.getId(), m.getCount()));
}
Output
mentorId: 1 mentees: 10
mentorId: 2 mentees: 10
Use Person and Mentor and Mentee subclasses as suggested by acornTime, define mentees as a list of Person and the information you want becomes simple to get:
import java.util.*;
import java.util.stream.Stream;
public class Main{
public static void main(String[] args) {
ArrayList<Person> mentees = new ArrayList<>();
mentees.add(new Mentee(11));
mentees.add(new Mentee(12));
mentees.add(new Mentor(2, new ArrayList<>()));
mentees.add(new Mentee(13));
mentees.add(new Mentee(14));
mentees.add(new Mentor(3, new ArrayList<>()));
mentees.add(new Mentor(4, new ArrayList<>()));
mentees.add(new Mentor(5, new ArrayList<>()));
Mentor mentor = new Mentor(1, mentees);
System.out.println(mentor.menteesCount());
System.out.println(mentor.mentorsInMentees().count());
}
}
interface Person {
int getId();
}
class Mentor implements Person{
private final int mentorId;
private List<Person> mentees = new ArrayList<>();
public Mentor(int id, ArrayList<Person> mentees) {
mentorId = id;
this.mentees = mentees ;
}
#Override
public int getId() {
return mentorId;
}
public List<Person> getMentees() {
return mentees;
}
public int menteesCount() {
return mentees.size();
}
public Stream<Person> mentorsInMentees(){
return mentees.stream().filter(m -> (m instanceof Mentor));
}
}
class Mentee implements Person{
private final int menteeId;
public Mentee(int id) {
menteeId = id;
}
#Override
public int getId() {
return menteeId;
}
}
Test it online here
You should do something like a depth-first or breadth-first search (*):
Maintain a Set<Integer> containing all the people you have already seen.
Maintain a queue of some kind (e.g. an ArrayDeque), of people you are going to check.
Put the first person (or any number of people, actually) into this queue.
Then, while the queue is not empty:
Take the next person in the queue
If you've already seen them, go to the next item in the queue
If you've not already seen them, put the person into the seen set; add all of their mentees into the queue
That's it. The number of people at the end is the size of the seen set.
(*) Whether you do depth-first or breadth-first search depends on which end of the queue you add mentees to: adding them to the same end that you remove them from results in depth-first search; adding them to the other end results in breadth-first search. If you don't care which, choose either.

Store three search algorithms in a list (as method calls) and iterate over them in main?

Briefing:
I have implemented three search algorithms to break a lock. A lock can be broken by the actions shaking, pulling, pulling, or poking. These are 4 methods can be applied to the given lock. This lock has a length anywhere from 1 to 16, meaning that if the length was 16, 16 back to back actions in the correct order will need to be done. For example, a length two lock that can be unlocked by pulling and then poking will need to be pulled and then poked. The data structure devised to solve this is a tree where each parent has 4 children that correspond to actions. These search algorithms climb the tree in many ways to find the correct solution to break a given lock.
Set-up of Solution & Problem:
I have one class called Tree that has 3 Search algorithms: Breadth-First, Depth-Limited, and Iterative-Deepening Search. In this same class, I have 2 helper methods to help each algorithm break a lock combination (check, which checks if the sequence of actions up to the child being viewed is a solution, and depth, which determines the depth of a given child). I also have a Node class that is used by Tree to create the root and subsequent children. Now, I want to store each algorithm in an array, so that I can iterate over each algorithm, and collect data for each algorithm from a main function. I have looked a little into the Command Pattern regarding Polymorphism. It seems that it might work, but I am confused on how I would have to organize my current solution to adapt. Would I need to turn each algorithm methodintoPerhaps there is a better solution than the Command Pattern. I can create a main in the Tree and simply call each algorithm there, but that seems a bit "sloppy" to me. Any suggestions?
The code below is just to get a gist of my current format. I have would rather simplify the code to show organization to best get at how I can adapt to utilize something like the Command Pattern to store each algorithm in an array to iterate over each and collect certain data.
public class Tree {
Node root = new Node(0, null);
TheLock lock = new TheLock("Michael");
Tree()
{this.root = root;}
public int runBST(TheLock lock){
}
public int it2runIDS(TheLock lock){
}
public int runDLS(int depthlim, TheLock lock){
}
public boolean check(Node child,TheLock lock) {
}
public int depth(Node child, int currd) {
}
}
public class Node {
int action;
Node parent;
public Node(int action, Node parent) {
this.action = action;
this.parent = parent;
}
}
I would suggest the Visitor pattern, if you had to pick a specific one. Each algorithm will visit one lock and try to break it.
The following approach is not exactly an implementation of said pattern, but it shows one way you can store a list of objects with a similar method
Start with an Interface, and some model object to hold state of a Lock
public interface LockAlgorithm {
// returns true if lock is broken
boolean break(Lock lock);
}
Some implementation, repeat for other types
public class BFSLockAlgorithm implements LockAlgorithm {
#Override
public boolean break(Lock lock) {
return false; // TODO: implement
}
}
Then, you store a list of interface implementations to loop over and apply on some Lock object
// in main
List<LockAlgorithm> algos = Arrays.asList(new BFSLockAlgorithm());
Lock l = new Lock("data");
for (LockAlgorithm a : algos) {
if (l.isLocked()) {
if (a.break(l)) System.out.print("success");
}
}
if (l.isLocked()) {
System.out.print("failed");
}
The inverted way to implement the link above would be to allow for boolean Lock.unlockWith(LockAlgorithm a)
Don't forget to do adequate unit testing for each LockAlgorithm first

Why is boolean flag within the method body a bad idea?

Suppose I have something as follows where DataImporter is a utility to retrieve data from the file system and has child data importers within it for retrieving data from the sub folders based on the category string:
List<String> categories = getCategories();
boolean doesChildImporterExist = false;
for (String category : categories)
{
DataImporter childDataImporter=importer.getChild(category);
if (childDataImporter != null)
{
doesChildImporterExist = true;
populateImportedData(childDataImporter.importData());
}
}
if(!doesChildImporterExist)
populateImportedData(importer.importData());
I know the other option is to construct a List of child data importers and check for its size, if it is 0 or not and based on that import the data using the desired importer. However, I'm trying to understand what is wrong with using the boolean flag here?
Assume that the code above is within a method and using Java 1.7.
When you use a boolean flag in a method as a branch decider (not the best terminology),
you are actually taking the functionality of two different methods and smashing them into one method.
Often,
the better solution is to have a method for the shared functionality and a second method for the super set functionality.
For example:
public DataImporter doYourCategoryStuff()
{
List<String> categories = getCategories();
... blah including the for loop.
return theDataImporter;
}
public void doAllTheStuffs()
{
final DataImporter theDataImporter;
theDataImporter.doYourCategorStuff();
populateImportedData(theDataImporter.importData());
}
Edit
More to the point in your code.
In your code,
the boolean flag indicates "I did something to a child importer and need to update parent importer".
In this case you are smashing "identify things to update" and "do the update" together;
split them.
Consider something like this:
Set<DataImporter> updateSet = new HashSet<>();
for (category for loop)
{
final DataImporter child = importer.getChild(category);
if (child != null)
{
updateSet.add(child);
updateSet.add(importer);
}
}
for (final DataImporter current : updateSet)
{
current.importData();
}
Even though the add(importer) (the parent) may be called multiple times,
the set will only ever contain one instance of each DataImporter.
This should be reasonable even if you don't implement hashCode and equals on DataImporter, since the parent reference will always be the same.

Efficient concatenation of Java LinkedList?

The idea of LinkedList is, that each element has a reference to its successor (and predecessor in the case of doubled linked list), so concatenation of two LinkedLists happens that last element of the first list get reference to first element of second list Detailed explanation here, what is made in O(1) time.
Howewer they made it stupid in Java.
It has no method java.util.LinkedList.addFirst(LinkedList) or something.
if you look at the method java.util.LinkedList.addAll(Collection), it iterates over an array, what collection returns with c.toArray(), and then adds each element of this array. What is even twice stupid:
1) linked list is iterated in 0(n)
2) elements are added to linked list in 0(n) time.
Is there any possibility to extends the standart LinkedList so he would have good concatenation method? Because now, the simplest, but bad solution i see to make the copy- paste of LinkedList code and make some methods protected in order to extend that with implementation of right addALL
You can't use addAll for that, because O(1) linked list concatenation is a destructive operation. In other words, you start with two non-empty lists, and end up with one big list and one empty list.
You are looking for two operations
void transferBeforeFirst(LinkedList<T> other);
void transferAfterLast(LinkedList<T> other);
They take LinkedList<T> other in whatever state it may be, and leave it empty upon return. This is rather counterintuitive, because generally the caller expects to find his data unchanged after calling a library method.
Of course, technically this could certainly be done. However, this goes against the grain of Java API design, which prefers to leave method parameters unchanged.
I don't think there is a way to do that, and the reason is that java has a strong object orientation and doesn't operate with data in a direct way such has C does, so if you have two linked lists and you want to make one out of two, you are forced to copy one of them entirely instead of only liking it at the end of the other one.
This behaviour is because special casing the adding of two linked lists together would destroy the sconfd list.
Notice that the LinkedList.Node class has both a next and a prev so it is indeed doubly-linked. To just join the chains together would make list2.first.prev point to list1.last which would then break list2.
public void addLast(LinkedList<? extends E> l) {
// My list continues on into the new list.
last.next = l.first;
// Back-link too - THIS BREAKS l!!
l.first.prev = last;
// End of new list is now last.
last = l.last;
}
Secondly notice that LinkedList<? extends E>. Remember that you can extend LinkedList so you may be adding two lists of a completely different class together - that would also require careful handling.
If you really want to achieve O(1) you could write an IterableIterable that would walk an Itearble<Iterable<T>> delivering each element from each Iterable in turn - kind of like a flatMap for Iterables.
class IterableIterable<T> implements Iterable<T> {
private final Iterable<? extends Iterable<T>> i;
public IterableIterable(Iterable<? extends Iterable<T>> i) {
this.i = i;
}
#Override
public Iterator<T> iterator() {
return new IIT();
}
private class IIT implements Iterator<T> {
// Pull an iterator.
final Iterator<? extends Iterable<T>> iit = i.iterator();
// The current Iterator<T>
Iterator<T> it = null;
// The current T.
T next = null;
#Override
public boolean hasNext() {
boolean finished = false;
while (next == null && !finished) {
if (it == null || !it.hasNext()) {
if (iit.hasNext()) {
it = iit.next().iterator();
} else {
// All over when we've exhausted the list of lists.
finished = true;
}
}
if (it != null && it.hasNext()) {
// Get another from the current list.
next = it.next();
}
}
return next != null;
}
#Override
public T next() {
T n = next;
next = null;
return n;
}
}
}
That's why LinkedList has the addLast() method
https://docs.oracle.com/javase/7/docs/api/java/util/LinkedList.html#addLast%28E%29
and it does have a addFirst() too
https://docs.oracle.com/javase/7/docs/api/java/util/LinkedList.html#addFirst%28E%29
you can't do better than that, because Java has not the pointer concept.
you could try to implement your own native code for that, however.

Delete Binary Tree - Suggestions on Design

I have written a code for deleting all elements of tree.
Need suggestions for following:
In reverseTreeStack method, Can I design without using stack method parameter?
Can I design the entire code in 1 method with better design?
UPDATE : Changed return type of reverseTreeStack to void.Removed additional variable for stack.
public class DeleteTree {
public static void deleteTree(BinaryTreeNode root)
{
Stack stack = new Stack();
reverseTreeStack(stack, root);
while (!stack.isEmpty())
{
BinaryTreeNode node = (BinaryTreeNode)stack.pop();
System.out.println("---------Deleting----------->" + node.getData());
node = null;
}
}
public static void reverseTreeStack(Stack stack,BinaryTreeNode root)
{
if (root != null)
{
stack.push(root);
reverseTreeStack(stack,root.getLeft());
reverseTreeStack(stack, root.getRight());
}
}
}
Why do you need to do this? If I recall correctly, the JVM can free resources once there are no available references to the resource, so just setting your root node to be null should free the whole tree.
I think, James is right, but if you want to practice the tree traversal, or if you want to implement this in a language where you need to free memory manually, then use recursion:
void deleteTree(TreeNode node)
{
if(node==null)return;
deleteTree(node.getLeft());
deleteTree(node.getRight());
System.out.printline("Deleting: "+node.getData())
node = null;
}
Also take a look at Postorder Traversal (thats the only one, that works for deleting)
1) I think you can kill the return value and make it a void method as you are directly manipulating the stack. So just do
Stack stack = new Stack();
reverseTreeStack(stack, root);
// Now just use stack
2) Don't condense things into one method. Breaking things out into more methods will make your code easier to navigate and understand. The less each function is responsible for, the more sense it will make to someone reading it.
Well your reverseTreeStack method can potentially give you a StackOverflowError if your tree is too large, so using a loop instead of recursion there might be a better choice (unless you know for a fact that your trees will never be that large).
Also, why are you "deleting" every node? (node = null actually just removes the reference you have just in that method...) Generally just forgetting the root (root = null) will delete your whole tree if you're structuring it in the classic way of Node(parent, leftChild, rightChild) and not storing pointers to nodes anywhere else.

Categories

Resources