public List<Person> getDiseaseRouteTo(Person c){
if(this.contains(c)){
if(root == c){
route.add(c);
}
else if(root != c){
route.add(root);
for(DiseaseTree dt: children){
if(dt.contains(c)){
route.add(dt.root);
dt.getDiseaseRouteTo(c);
}
}
}
return route;
}
return null;
}
The constructor is a tree constructor named DiseaseTree which contain a root node and a Children set. The children set is a DiseaseTree set. I am supposed to find the route of seeking one node. For example, I have an existed tree named ddtt and I want to find the route to find node c in this tree. ddtt.getDiseaseroute(c) will get a list to find node c. like[A, B, C] if tree is like
A
--B
----C
I used recursion to realize that. But it can't have complete route. I don't know what is going on and totally confused.
you are adding the root twice to the route list, once on the line "route.add(root);" and the second time when you go over his children "route.add(dt.root);". you don't need to add it twice.
Also next time try to debug it with a simple input and see what is going on.
Related
I was solving the problem to delete the middle node of a LinkedList. Say given a linked list a->b->c->d->e you would want to delete b/c/d and the head of the LinkedList is not given.
public boolean deletemiddle(LinkedListNode node) {
if(node==null)
return false;
LinkedListNode n=node;
node.data=n.next.data;
node.next=n.next.next;
return true;
}
This works. But what if I want to delete the last node e? I know we can do this in c/c++ by manually freeing the space allocated but is it possible to do it in Java?
I did try allocating a null to the value but that does not seem to work
if(node.next==null) {
LinkedListNode dummynode=null;
node=dummynode;
return true;
}
No, this is not possible. You really need a reference to the preceding node so you can update its next reference. A doubly linked list provides such a back reference, but when you are speaking of a singly linked list, the function must get a reference to the preceding node in some other way.
I know we can do this in c/c++ by manually freeing the space allocated
That would not be enough. In C/C++ you also need to set the previous node's next pointer to NULL/nullptr, or else you'll get undefined behaviour. The only thing you can do more in C++ is to pass the previous node's next pointer by reference.
But no matter how you do it, the function must be able to access the next pointer/reference of the preceding node, or it will not be possible.
If I understand your question correct, you can delete the last node by setting the .next attribute of the previous node to null.
If your nodes contain the attribute .previous, you can use that.
So
if(node.next==null) {
node.previous.next = null;
return true;
}
If you don't have a previous attribute, you need to check for each node if the next node will be the end node. So
if(node.next != null && node.next.next == null){
node.next = null;
return true;
}
I hope that answers your question.
I need to write a piece of code using the Kruskal algorithm, which in turn needs the Union-Find algorithm.
This includes the methods Make-Set(x), Find-Set(x) and Union(x, y).
I need to implement them using linked lists, but I am not sure of how to start with the Make-Set method.
The Make-Set Method should create a set and make the first element into a key (to compare sets). How exactly would I declare a key using linked lists?
Shortly put: How do I implement this pseudo code for linked lists in Java?
Make-Set(x)
x.p = x
x.rank = 0
Thanks for your help in advance!
I've heard this referred to in the past not as "Union-Find" but as a disjoint set. It isn't exactly a linked list, since the nodes do have a link, but they aren't necessarily linked up in a linear fashion. It's more like a tree where each node has a pointer to its parent and you can walk up the tree to the root.
I don't have much time right now, but here's a quick sketch of how I would implement it in Java:
class Disjoint {
Disjoint next;
Disjoint findSet() {
Disjoint head = this;
if (next != null) {
head = next.findSet();
next = head;
}
return head;
}
void union(Disjoint other) {
Disjoint us = this.findSet();
Disjoint them = other.findSet();
us.next = them;
}
}
Creating an instance is your Make-Set. What you call Find-Set I would call find head or find leader, maybe find identity. I've called it findSet here, though. It walks the chain to find the root of the tree. It also performs an optional operation; it snaps all the links on the way back out of the recursive call so that they all point directly at the root. This is an optimization to keep the chains short.
Finally, Union is implemented just by assigning one root's next pointer to point at the other set. I'm not sure what you intended with rank; if it's the size of the set, you can add a field for that and simply sum them when you union two sets. But you initialize it to 0 for a new set when I would expect it to be initialized to 1.
Two nodes a and b belong to the same set if a.findSet() == b.findSet(). If you need the nodes to carry some data, make the class generic and provide the data to the constructor, and add a getter:
class Disjoint<T> {
Disjoint<T> next;
T data;
public Disjoint(final T data) {
this.data = data;
}
public T getData() {
return data;
}
// rest of class identical except Disjoint replaced with Disjoint<T> everywhere
}
I have a tree of nodes. While iterating this tree depth first, I need to return the list of all duplicate nodes from the root node to my current node.
Due to some business requirements the "already traversed" part of the tree is never the same. I do a lot of swap/replaces of branches in the already traversed part of the tree. So maintaining a list of traversed nodes might not work as it needs updates every time I finish traversing a node.
So whenever I need to answer getDuplicateNodesOfMyCurrentNode() I need to start from the top of the tree (rootNode) and search depth-first till my currentNode and return back a list<Nodes> that are duplicates of my currentNode.
private void getDuplicateNodesOfMyCurrentNode(Node parentNode, Node currentNode,List<Node> dupNodes){
for(Node child: parentNode.getChildren()){
if(child == currentNode){
return;
}
if(child.getApp().equals(currentNode.getApp()){
dupNodes.add(child);
}
getDuplicateNodesOfMyCurrentNode( child, currentNode, aDupNodes);
}
As you guys already know the issue with this code, return doesn't return back the control to the caller of this API since it recursively calls itself.
I want some way to exit out of this recursive loop once I get to my currentNode.
I probably can achieve this by maintaining some boolean state, but want to know the better way of solving this.
Pass whether or not to abort your recursion back through the call stack via a boolean and abandon the current for loop if necessary at the point of the recursive call (also acknowledging Norbet van Nobelen's comment above that alludes to something similar):
private boolean getDuplicateNodesOfMyCurrentNode(Node parentNode, Node currentNode,List<Node> dupNodes){
for(Node child: parentNode.getChildren()){
if(child == currentNode){
return false;
}
if(child.getApp().equals(currentNode.getApp()){
dupNodes.add(child);
}
if (getDuplicateNodesOfMyCurrentNode( builtOn, currentNode, aDupNodes) == false){
return false;
}
}
return true;
}
I'm trying to write a function to traverse a tree with depth first search.
My current algorithm goes something like:
If children
go to first child
If no children
go to next sibling
If no siblings
go to parent
The problem I'm running into is that I can't mark nodes on the tree as having been visited, so when I go to the parent the cycle just resets and it goes to the child again, getting stuck in a loop. Does anyone have any idea as to how I could solve this?
(It's in java using the ANTLR plugin)
EDIT:
Following one of the suggestions I wrote this:
public void traverseTree(Tree tree){
if (tree.getChildCount() > 0){
tree = tree.getChild(0);
traverseTree(tree);
System.out.println(tree.toString());
}
if (tree.getParent().getChild(tree.getChildIndex() + 1) != null){
tree = tree.getParent().getChild(tree.getChildIndex() + 1);
traverseTree(tree);
System.out.println(tree.toString());
}
if (!tree.getParent().toString().contains("ROOT_NODE")){
tree = tree.getParent();
traverseTree(tree);
System.out.println(tree.toString());
}
}
Root node is the name of the root node, but I'm getting a stack overflow error. Anyone have any idea why?
Thanks.
I would use recursion in this case.
class Node {
public List<Node> getChildren() { .... }
public void traverse(Visitor<Node> visitor) {
// If children
// go to first child - by traversing the children first.
for(Node kid: getChildren())
kid.traverse(visitor);
// If no children
// go to next sibling, - by continuing the loop.
visitor.visit(this);
// If no siblings
// go to parent - by returning and letting the parent be processed
}
}
interface Vistor<N> {
public void visit(N n);
}
Using a hash_table map each vertex to boolean indicate whether visited or not
Write a depth first Iterator that keeps track of visited nodes internally. That way the tree doesn't have to change to know that it's being watched.
If "no memory" can be interpreted as O(1) memory, then the change may help:
Remember not only the current node, but also node where you came from
Traverse children only if you didn't came from one of them
I have a structure like this of what we'll call Box objects.
Box--+---Box----Box
|
+---Box-+--Box
|
+--Box
|
+--Box
I'm trying to ask the top box object for a list of the leaf node Boxes, which is the 3 box objects in this case.
The box object has a list of its children in an instance variable of type Vector called children.
The number of children can be unlimited.
I've been trying to write a single recursive method to do this, but without success.
One way to do this would be a recursive traversal of the structure. The idea is as follows:
There are no leaf nodes in the empty tree.
In a tree with root r with no children, then r is the only leaf.
In a tree with root r, if r has children, then the leaves of the tree are the leaves of those children.
You could write a recursive traversal with this sort of pseudocode:
void findChildren (Box current, List<Box> found) {
/* Case 1. */
if (current == null) return;
/* Case 2. */
if (current.children.isEmpty()) {
found.add(current);
return;
}
/* Case 3. */
for (Box child: current.children)
findChildren(child, found);
}
Hope this helps!
it has been awhile since I've done Java, so I'm sure this code has plenty of syntax errors, and I hope no one marks me down for it; just trying to give you some algorithm ideas. Hopefully it helps:
vector<Box> getLeaves(Box root)
{
vector<Box> tempList; //vector to hold nodes to check
vector<Box> tempList2; //vector to hold nodes' children
vector<Box> leafList;
bool goflag = true;
tempList.add(root);
while(goflag){
for(int i = 0; i < tempList.size; i++){
if(tempList[i].children.isEmpty()){
leafList.add(tempList[i]);
}
else{
//add all children to tempList2
for(int c = 0; c < tempList[i].children.size; c++){
tempList2.add(tempList[i].children[c])
}
}
if(tempList2.isEmpty()) //no more childs
goflag = false;
else
tempList = tempList2;
tempList2.clear();
}
return leafList;
}
It goes through all the nodes, adding children to the next list to check, and adding leaves to a list to be returned.
There are several ways to write such a function. Here's one approach to work through.
Define a helper function that takes a node and a mutable queue holding nodes.
In that helper function, check if the supplied node's children are empty. If so, add that node to the queue, and return.
If instead the supplied node has any children, call the helper function once for each of the children, passing the child and the same queue reference through.
At the top level, create an empty queue, and call the helper function, passing in the root node and the queue.
When the helper function returns, the queue contains all the leaves in the order they were discovered.
A different approach uses the same depth-first traversal, but the function would return the list of leaves it discovered. These lists would need to be combined for each set of siblings explored, working back up the tree as each function call returns.