I have to write an algorithm for my project. Following is the problem
A Tree like Structure for which only one functionality is exposed i.e to **getAllChildNodes** which returns all the children of a particular node.
Now I am given an array of Nodes , I have to only retain the topmost parent node among them.
Example : Lets say there are 3 trees
Tree 1 : P1 has two children C11 & C12
Tree 2 : P2 has 1 children C21, and C21 has 2 child C22, C23
Tree 3 : P3 has 2 Children C31 and C32
Now if given an array say { C11, C21, C22 , P1, P3, C32}
The expected result is { C21, P1 , P3 }
Let me know if more information is required from my side.
More info :
I have done it by first getting all the child of first element of array and then compare with rest of the elements of array ,and similarly with each element. but this has more complexity.. i.e n*n*getAllChildNodes. I am here for a better suggestion
Pick ith element of array and add all its children to a hashmap(using the given function). Do this for i 1 to n(complete pass)
Loop i for 1 to n and for each iteration, check if the element is present in hashmap.
If it is present, delete it from the array,
else continue
Note the order of checking if element belong to hashmap is O(1) and also order of addition is O(1), avearage. So the algorithm is O(n*getAllChlidNodes) average
You can do this easily.
first create a method isPresent(node) to check if the node you are entering is present in the array. Then enter each node given to find its parent.
if(isPresent(x->parent)) push(x->parent);
Continue this for the entire list.
Now recursively check to see if the current list has any parents present. Once you start doing you'll get it. If there are any parents just pop() those elements.
Hope this helps :)
If you could get a function first like getParentNode(childNode) or create map/multimap of child as key and parent as value as pre processing step then Problem would become very easy.
If you have getParentNode(childNode) then just walk through the array and push the parents into set.
If you have map/multimap of child as key and parent as value as pre processing step then apply the algo as mentioned by adi
Related
I am currently considering different ways to accomplish the task of converting a family-type general tree (where each parent can have as many children as necessary) to a binary tree such that the left child of the parent node is inserted to the left of the parent and the right child of the parent node is inserted to the right of the (oldest) child node and so on.
This is the structure of how the binary tree must look like when converted from the general tree: https://www.geeksforgeeks.org/convert-a-generic-treen-array-tree-to-binary-tree/
I fed in my data by creating class object GTNode for the General Tree to add the nodes with the following values being passed:
//name = value1; numChildren = value2
GTNode gtn = new GTNode (String name, int numChildren);
No issues with constructor, this is purely to illustrated the main focus of the node is indeed the name of the family member. Thus this really can't be converted and sorted by a Binary Search Tree and is not the point of the resulting program I'm trying to create.
I was able to create methods to traverse the tree just fine, but it really doesn't help in the conversion process to the CONVERTED binary tree.
Therefore I created an additional section of code to create a linked list of the data. The reason why I did this was to establish pointers along the list which would point to the correct parent to add children to. Siblings would then be added to the right of the oldest sibling based on pointers based on where we were along real-time adding of nodes in the tree. By this time you can imagine I have two pointers going in my linked list traversal and three pointers along the tree nodes.
I can't seem to make good progress on an algorithm to create this binary tree from the data. here's a little sample code mostly pseudo code to show you basically how I'm adding nodes to the converted-style binary tree based on general tree data.
p=q=first; //initialize to first node f the linked list of family data
//ex. [Tom, 2] [Marc,1] [Ron,0] [Billy, 0] where Marc and Ron are Tom's children, and Billy is Marc's child)
z=root;
//I already established x, y = root earlier and moved pointer .next in order to add children nodes to the siblings
//here we establish x and y pointers for the tree and add our root node and first child node, which will always be to the left.
//I left it out of the while loop, because I was running into problems with null pointers.
{
while (p.next!=null && q.next!=null)
{
for (i = n; i>0; i--) //int n = node.numChildren; was declared earlier and then decreased
// n-=1 to accommodate the first child being added to left of parent node;
{
//add nodes left or right to parent node: still trying to figure out the appropriate condition
//statements to determine addLeft or addRight from node
}
//here we change the pointer of the GENERAL tree parent node based on the linked list
// add new to binary tree to the right of the last child i.e.
y = new BTNode(p.value,p.numChildren);
y = x.right;
x = y.parent;
x = y; //move pointer along
q = q.next; //q moves from Tom to Marc.
n = q.numChildren;
//go to beginning of while loop and as you can see, if n>0 it iterates based on the number of children
// if n=0 exits loop and creates a new node to the right
}
}
I'm wondering if this is an acceptable track to go down in terms of operability. Optimization I'm not as focused on because this is a difficult task... but could be taken into account.
Looking for pseudocode or java code shippers that would help in establishing an algorithm along these lines, or error in my logic. Again, not looking for an argument against doing a conversion like this because I want to see what it would look like as is.
Thanks!
I want to ask a question about sorting in Java, to be precise i need to sort a list of tuples (that are defined as a custom class) but that are linked like a tree to each other.
Basically this is a list of document ids that express the relation parent-child, and are organized as sets (possibly unordered). The tuples are already filtered to have unique left / right elements, so that the tree has unique links between documents (they are not allowed to have multiple leafs).
Using example data, i have this kind of list: [(1,2), (3,4), (0,1), (2,3)], this represents the following tree:
0
|_ 1
|_ 2
|_ 3
|_ 4
Hence i need the list to be ordered as follow: [(0,1), (1,2), (2,3), (3,4)].
I also add that it's possible that the parent document id is greater than the child one, so a simple sorting based on which id is greater is not possible.
I tried using the .sorted() method of the Stream class, after making the custom class comparable and adding the following code:
#Override
public int compareTo(DocumentIdVersionsStack o) {
if (parentDocumentId == o.getChildDocumentId()) return 1;
if (childDocumentId == o.getParentDocumentId()) return -1;
return 0;
}
Basically telling it to invert the order if the current one is child of the other tuple and vice versa, but the list is still not what i expect it to be.
Any idea on how to do this using streams? I didn't want to use complex sortings methods that require recursion, just to keep the code cleaner, but if it can't be done otherwise i'll check that.
Thank you!
EDIT:
I'll add a couple of informations:
The tuples are already contiguous, there won't be 'holes' of missing ids
The recursion (last id = first id) is again taken care before passing the tuples to the sorting method
There will be a tuple with the left value not found in any of the right values -> this will be the first element after the sort
There will be a tuple with the right value not found in any of the left values -> this will be the last element after sort
All left and right values are unique, they are just linked as explained before (left1 = right2 and so on)
You have mentioned that the tuples are unique. So the compareTo method will not work as it deals with "equal" elements as well, which is not applicable to a unique list. In the current compareTo code, the tuples (1,2) and (3,4) would be treated as equals which is why it is not returning expected results. Also since parent id could be greater than child id, you cannot clearly say if (1,2) is greater or less than (3,4).
The order could be (1,2), (2,3), (3,4) or (3,4), (4,1), (1,2). Hence without knowing the details of other nodes, it might not be possible to do it using compareTo.
I would suggest an approach to keep a map of these tuples with the parent id as the key, then find the root node and start traversing from root:
Map<Integer, DocumentIdVersionsStack> map = list.stream()//
.collect(Collectors.toMap(DocumentIdVersionsStack::getParentId,
Function.identity()));
Set<Integer> child = list.stream()
.map(DocumentIdVersionsStack::getChildId)
.collect(Collectors.toSet());
// Get the root node
DocumentIdVersionsStack node = list.stream()
.filter(u -> !child.contains(u.getParentId()))
.findFirst()
.orElse(null);
List<DocumentIdVersionsStack> list2 = new ArrayList<>();
list2.add(node);
// Traverse using the map
while (map.containsKey(node.getChildId())) {
node = map.get(node.getChildId());
list2.add(node);
}
System.out.println(list2);
I currently use the Graphstream API for Java for my project.
I wan't to delete or add Nodes on command.
With JFrame & co. I initialized a console so I can just insert
"addNode()" or "removeNode(id)" in order to get the result.
A Interface shows the nodes with a number next to them(the ID).
When I delete one node, I want all nodes with higher ID to change their ID,
but I did not figure out a way jet to change the ID of one node.
F.e. I have:
graph.addNode(0);
graph.addNode(1);
graph.addNode(2);
When deleting a Node:
graph.removeNode(0);
I want 1,2 to be changed to 0,1 without reinitializing the complete graph.
Is there a way to achieve this behaviour? I thought about something like:
graph.getNode(1).setID(0);
Unfortunately I have only access to .getID() and can't manipulate it this way.
Thanks
Nodes ids are strings and they are immutable (no renaming, no setId()).
Now what you are doing in your example is different. You are using the index-based access to the nodes. Indices are integers and correspond to arbitrary nodes in the graph, they are not associated to the ids.
When you do graph.addNode(0), the integer is converted to the string "0". Then when you do graph.removeNode(0), you are removing a node that was indexed as the first of the list of nodes. But it does have to be the node this id "0".
You can remove nodes with index (integer) 0 as long as there are nodes in the graph (graph.removeNode(0)) but you can only remove the one node with id "0" once (graph.removeNode("0")).
How do you remove from an ArrayList at a particular index then add back to that same index without the removal causing the ArrayList to compensate for the loss of them item and moving the empty space to the end of the array list?
I've tried:
public void dischargePatient(int bedNumber) {
if (bedNumber < beds.size()) {
beds.remove(bedNumber);
}
}
But this moves the bed at bedNumber to the end of the ArrayList after removing the patient from the bed. How do I keep it at bedNumber?
You want to use a Map object instead. I'm a little rusty at java, but you can define a map of beds like this:
HashMap<Integer,Boolean> occupiedBeds;
and then you can check if an entry is true to see if a bed is occupied, and then set it to false when you discharge a patient. You can initialize the occupiedBeds to a range of false values, or you can just assume an "unset" state means that nobody is in the bed.
You just aspecify the index you want - beds.add(bedNumber, patient);
This pushes the patients that were prior to the addition in locations bedNumber and later to bedNumber+1 ...., thus bringing your list back to the original order.
public void add(int index,
E element)
Inserts the specified element at the specified position in this list. Shifts the element currently at that position (if any) and any subsequent elements to the right (adds one to their indices).
You can use beds.get(bedNumber) and beds.set(bedNumber, patient).
If you want to keep on using an ArrayList, then you can use the method "set(index, null)" instead of invoking the method "remove(index)". This will ensure that the your order does not change.
Example:
0 1 2 3
ArrayList items: [ A, B, C, D ]
items.set(2, null);
0 1 2 3
items: [ A, B, null, D ]
I know this doesn't answer the question asked, but using a list in such a way, expecting the index to reflect the bed number while also expecting the list to define if a bed is taken is a bit broken, or at least highly troublesome. The examples below show how it is easier to manipulate sets and maps and they provide extra information such as total occupied beds without having to code that up yourself.
I suggest you use a Map of Patients rather than a list.
Map<Integer,Patient> patientBeds = new HashMap<Integer,Patient>();
patientBeds.add(bedNumber, patient);
patientBeds.remove(bedNumber);
patientBeds.contains(bedNumber); // is this bed taken?
patientBeds.size(); // total occupied beds, regardless of their numbers
If you don't need the Patient objects, but simply to know which beds are occupied, use a simple Set of Integers
Set<Integer> set = new HashSet<Integer>();
set.add(bedNumber); // help me nurse
set.remove(bedNumber); // I'm going home!
set.contains(bedNumber); // is this bed taken?
set.size(); // total occupied beds, regardless of their numbers
With either of these solutions, your class which holds the Map or Set might have a member which specifies the total number of available beds in the ward. I wouldn't try to build this concept into the Map such as populating the Map with "null" patients.
int totalBeds = 10;
if (bedNumber > totalBeds) {
// send them to the next ward
}
I'm learning about linked lists right now. I found an example for java that places a new node into the 3rd position on a linked list, but I've only ever seen insertion into a certain spot in the middle of a list like this done using 2 additional nodes, current and previous. I've also never seen anything like .getNext after another one like this. So can someone explain what each part of this snippet of code does and maybe rephrase it using nodes current and previous so I can understand how it relates and compares? Elem is the name given to the node being inserted and you don't have to instantiate current and previous if you do add an explanation involving those. I'll just assume it's already done.
elem.setNext(first.getNext().getNext());
first.getNext().setNext(elem);
numberOfElems++;
Please let me know if you need more info to answer!
elem.setNext(first.getNext().getNext());
As you said, elem is the element being inserted. The line of code above sets elem's next reference to the third element of the list (first.getNext().getNext() references the third element).
first.getNext().setNext(elem);
The second line of code sets the second element's next reference to the new element being inserted. The new element is now inserted in between the old second and third elements, making it the third element in the list.
The last line of code just increments the count of elements.