How to split a TreeList's children - java

I have been trying how to write a TreeList but failed so I googled one up and learn't from there. That works but what I am now trying to do and what I cannot find is how to split a TreeList. I have created 2 examples and both have failed me. The program just crashes. I am using Java and the TreeList class I am basing of is http://yet-another-tree-structure.googlecode.com/svn/trunk/java/src/com/tree/.
Original one
public TreeNode<T> removeAndCreate() {
TreeNode<T> tn = new TreeNode<T>(data);
tn.children = children;
tn.elementsIndex = elementsIndex;
elementsIndex.remove(this);
children.remove(this);
return tn;
}
The newer one I am using
public TreeNode<T> split() {
TreeNode<T> tP = parent;
while (tP.isRoot() == false) {
tP = tP.parent;
}
TreeNode<T> tn = new TreeNode<T>(data);
tn.children = children;
tn.elementsIndex = elementsIndex;
tP.elementsIndex.remove(this);
tP.children.remove(this);
return tn;
}
I thank you for the help I receive in advance.

After reviewing the classes you based things on and your second split I am going to assume that split means to take the node in question out of the current tree and return a new tree with node in question as its root. If that is what you are after then a few things need fixing. First of all your split function does:
TreeNode<T> tP = parent;
while (tP.isRoot() == false) {
tP = tP.parent;
}
Problem is that if your current node (this) doesn't have a parent you will get a Null exception thrown (so try splitting the root node and you should get an error). I think you meant:
TreeNode<T> tP = this;
This change will avoid the loop accessing a parent that may be null. Next, you need to delete all the elementsIndex at each level from the parent and above. You then have to remove the children from your direct parent (if you have a parent).
I think the code you might be looking for is below (assuming I haven't missed something):
public TreeNode<T> split() {
// Create a new root node for the tree we split off
TreeNode<T> tn = new TreeNode<T>(data);
tn.children = children;
tn.elementsIndex = elementsIndex;
// For each level of the tree above us make sure we remove
// ourselves from the elementsIndex at EACH LEVEL until we
// finish at the root.
TreeNode<T> tP = this;
while (tP.isRoot() == false) {
tP = tP.parent;
tP.elementsIndex.remove(this);
}
// If this node has a parent remove this node as one of
// our parent's children. We aren't the child of any of the
// levels above our parent
if (parent != null)
this.parent.children.remove(this);
// Return the root of the newly split tree
return tn;
}

Related

Problem while implementing Find() method for a disjoint set

Been trying to solve this for a while now. I've been given a Node in a Disjoint Set.The Node's implementation is as a class where either it has a different parent node or is it's own
class Node {
Node parent;
int rank;
//...constructor and method declarations}
Now, I have to implement the Find method for this class with path compression, called the getParent() method. I wrote the following code:
Node getParent(){
while(parent != this)
{
parent = parent.getParent();
}
return parent;
I get infinite recursion with this code. I know it's problematic, but I do not know how to fix it. I tried using the this keyword, but it led to the same errors.
Please help. Also, an insight on how to write this code in an iterative manner would be a great plus.
Also, I would like to restructure the tree such that all intermediate nodes between the node on which the getParent() is called and the root have a common parent i.e. the root node.
The first part of your question is already answered by Stephen, and I think this is complete enough.
About the second part of your question, I assume you have all the nodes in a list. So you have List<Node> allNodes. The needed method to restructure the tree would be:
public void reStructureTree(List<Node> allNodes){
for(Node item: allNodes){
Node p = item.parent;
List<Node> branch = new ArrayList<>();
while (p.parent != p){
branch.add(p);
p = p.parent;
}
for(Node branchItem : branch){
branchItem.parent = p;
}
}
}
The order of this method in the worst case would be O(n^2) and I did not look for a better way, cause you didn't mention the importance of it.
Node getParent() {
while (parent != this) {
parent = parent.getParent();
}
return parent;
}
The problems:
You are mutating the parent field.
You should be testing if the parent's parent is itself ... not this.
Your code should probably be:
Node getParent() {
Node p = parent;
while(p.parent != p) {
p = p.parent;
}
return p;
}
Or recursively:
Node getParent() {
return (parent == this) ? this : parent.getParent();
}
(In this case, the iterative version is safer. You should not get "infinite" recursion, but there is still a risk that you may recurse too deep, with a pathologically deep data structure.)
UPDATE - apparently, it is your intention that getParent should (incrementally) collapse the parent chain of each Node it visit. In that case, the recursive solution would be:
Node getParentAndCollapse() {
if (parent == this) {
return this;
} else {
parent = parent.getParentAndCollapse();
return parent;
}
}
An iterative solution that collapses the entire chain requires two traversals of the chain:
Traverse the chain find the ultimate parent.
Traverse the chain again, updating all the parent fields to refer to the ultimate parent.
Return the ultimate parent.
Something like this
Node getParentAndCollapse() {
Node p = getParent(); // iterative version
Node n = this;
while (n.parent != p) {
Node np = n.parent;
n.parent = p;
n = np;
}
return p;
}

How can I create a link-list in order to test a method that uses a Node class?

I know that a linked-list contains nodes where each node stores a value and a reference to the next node. I've seen classes that use these Nodes (like Linked-list Stack and Queue) and I had no trouble understanding them. But I don't understand how these nodes are actually created. I've looked at tutorials and each tutorial looks like it's doing completely different things and so I find it hard to grasp the overall concept.
I have a Java method that uses a Node:
public Node fun(Node x) {
Node first = x;
Node magic = null;
while (first != null) {
Node second = first.next;
first.next = magic;
magic = first;
first = second;
}
return magic;
}
I want to test this method. But in order to actually test this method, I need a linked-list (otherwise I'll get an error because Node is not recognized). This is where I'm lost. How do I create the Node class? Is the Node class and Linked-list class two entirely separate things? Is so, what would the linked-list class look like?
Suppose your Node class is this :
class Node {
int value;
Node next;
public Node(int value) {
this.value = value;
}
// setters and getters
}
You can create a linked list in this way :
Node first = new Node(0);
first.next = new Node(1);
first.next.next = new Node(2);
first.next.next.next = new Node(3);
You can iterate through list:
while(first != null) {
System.out.println(first.value);
first = first.next;
}

Deleteing a Node in a Binary tree

Iunderstand the basis of a deletion algorithm in a Binary Search tree and have created the following code to delete the largest value from the tree.
public void DelLargest()
{
Node<T> del = this;
boolean child = this.left.empty();
boolean child2 = this.right.empty();
right.DelLargest();
if(child && child2)
this.head = null;
else if(child == true && child2 == false)
this.head = left;
}
Basically what I have is that the recursion runs until 'this' is the rightmost node and then checks two cases, whether 'this' is a leaf, or whether 'this' has a left child. (The other case normally associated with this kind of algorithm is redundant because in finding the node with the largest value, I have gone as right as I can go.) The trouble I am having is getting the current node to then either point to null or to the value at Node left.
Note : This is what my instructor referred to as a "modern" Binary search Tree wherein a vertex or "filled" node and a nil or "empty" node are two subclasses of Interface Node which define the characteristics of each type.
I've managed to narrow the problem down to the fact that I do not have a method that returns a value of a given Node. Working on that now, input would be appreciated.
As suggested in the other answer you should use iterative approach.
In a BST the largest value is the rightmost node.
So do a scan and keep going right until you hit a null.
In the scan keep track of three nodes. (gpnode, pnode, node).
Once the scan is done you will have (gpnode,pnode,null)
Now there are 2 cases.
case 1:
pnode is a leaf. So change the edge (gpnode,pnode) to (gpnode,null)
case 2: (EDITED)
pnode.lChild is not null. Note that pnode.rChild will be null as the search would have terminated at that point.
Now change the edge (gpnode,pnode) to (gpnode,pnode.lChild)
Here is the pseudo code:
public class Node
{
long key;
Node lChild;
Node rChild;
}
public void DelLargest()
{
Node gpnode = null;
Node pnode = null;
Node node = root;
while(node != null) // keep going right until a null is reached
{
gpnode = pnode;
pnode = node;
node = node.rChild;
}
if(pnode.lChild == null) // its a leaf node So change the edge (gpnode,pnode) to (gpnode,null)
{
if(gpnode.lChild == pnode)
{
gpnode.lChild = null;
}
else
{
gpnode.rChild = null;
}
}
else // copy lChild's key to this node and delete lChild
{
if(gpnode.lChild == pnode)
{
gpnode.lChild = pnode.lChild;
}
else
{
gpnode.rChild = pnode.lChild;
}
}
}
You've got the right idea. What you want to do is keep a reference to the right most nodes parent, and the right most nodes left child so then when you delete it you can attach the two.
Here's an iterative solution. This will generally be more efficient than recursion, but if you want recursion you should be able to adapt it:
public void delLargest() {
// get rightmost node's parent
Node<T> current = root;
while(current.right != null && current.right.right != null) {
current = current.right;
}
// get the rightmost nodes left node
Node<T> left = current.right.left;
// attach the parent and left
current.right = left;
// nothing points to the right most node anymore, so it will be garbage collected
}

java alogrithm: find pre/next leaf node that meet special condition from any node in a tree

I need to write a function to find previous/next leaf node that meet special condition from any node in a singly rooted tree. (in the parent first order)
The API would be something like this:
Node findNextLeafNode(Node currentNode, Condition condition);
Node findPretLeafNode(Node currentNode, Condition condition);
where currentNode is any node in a tree, and Node is defined as:
interface Node{
/** #return the Node's parent or null if Node is root */
Node getParent();
/** #return true if node is root */
boolean isRoot();
/** #return non-null array of child nodes (zero length for leaf nodes) */
Node[] getChildren();
/** #return the number of child nodes. If node is leaf, value is 0 */
int getChildCount();
}
And the Condition interface defines the semantics of checking a constraint against a given Node.
interface Condition{
/** #return true if provided node meets the condition */
boolean check(Node node);
}
My question:
Is there an existing library or algorithm for such a common scenario? I am open to either stack based or recursive algorithms. Pseudocode, links to open source libraries, or if you care to share you own code, would be appreciated.
(If not, I need to spend time to invent the same wheel again and paste it here later for sharing.)
Thanks.
-----------------------------write a method to getNext()........
// currentNode must be descendant of root
public static Node getNextNode(Node currentNode, Node root)
{
// 1. if is has child, next is its first child
if (currentNode.getChildSize() > 0) {
return currentNode.getChildren()[0];
}
// 2. if it has no child, check if its is the last child of his parent
else {
// if it is root and has no children, return null
if (currentNode == root) {
return null;
}
// else should have parent which is or under root;
Node parent = currentNode.getParent();
int index = getIndex(currentNode);
if (!isLastofParent(currentNode)) {
// ----a. if not last, next is his parent's next
return currentNode.getParent().getChildren()[index + 1];
}
else {
// ----b. if it is the last one, return its parent's next right if there is. while until root
Node tmp = parent;
while (tmp != root) {
int parentIndex = getIndex(tmp);
if (!isLastofParent(tmp)) {
return tmp.getParent().getChildren()[parentIndex + 1];
}
tmp = tmp.getParent();
}
}
}
return null;
}
private static boolean isLastofParent(Node node)
{
if (getIndex(node) == node.getParent().getChildSize() - 1) {
return true;
}
return false;
}
private static int getIndex(Node currentNode)
{
Node parent = currentNode.getParent();
for (int i = 0; i < parent.getChildSize(); i++) {
if (parent.getChildren()[i] == currentNode) {
return i;
}
}
//TODO: error condition handling, will not happen if tree not change
return -1;
}
------------------------a full search is much easier............
public static Node getNextFailNode(Node currentNode, Node root, Condition condition)
{
boolean foundCurrentNode = false;
Stack<Node> stack = new Stack<Node>();
stack.push(root);
while (!stack.isEmpty()) {
Node tmp = stack.pop();
System.out.println("-popup---------" +tmp+ " ");
if (foundCurrentNode && checkCondition(tmp, condition)) {
return tmp;
}
if (tmp == currentNode) {
foundCurrentNode = true;
}
if (tmp.getChildSize() > 0) {
for (int i = tmp.getChildSize() - 1; i >= 0; i--) {
stack.push(tmp.getChildren()[i]);
}
}
}
return null;
}
This maybe way overblown for what you need, but it can support what you want:
There is a graph traversal language: Gremlin. Typically bolted on top of something like Neo4j, but any graph data structure (e.g. a singly rooted directed tree) can be wrapped to support the API. Take a look at Blueprints projects to find out how it is done.
[edit: for something less heavy]
Perhaps JGraphT is what you want. Also take a look at this question on SO. It is not an exact duplicate, but you should find it helpful.
Write an iterator for your tree that can be initialized from any node and uses pre/in/post-order traversal (Of course it should be bi-directional).
This is basically writing one simple algorithm that at least to me seem basic.
Once you have an iterator all you need is to iterate your way to the next node which is a leaf and the condition holds for it.
If you have trouble with any specific part just ask and I'll improve my answer.
Based on the fact that you already have defined your interfaces, and you say the graph-traversal libraries are too heavyweight, you probably should just write it yourself. It would be an absolutely trivial amount of code. (This page contains some code if you need help.)
(One suggestion for your API: don't put a boolean isRoot(); method on Node, that's a waste of bits unless you have a very good reason to do so. The code that builds the tree should just refer to the root node.)

Why can I not remove a child element I've just found? NOT_FOUND_ERR

I'm building a script which has to patch XML files, including replacing one list of elements with another. The following function applies a patch (involving a possibly empty list of elements with the same name) onto a parent Element's list of elements by the same name (also possibly an empty list). (This is only a small part of the patching logic).
Why, when I run the code, do I get the following error?
org.w3c.dom.DOMException: NOT_FOUND_ERR: An attempt is made to reference a node in a context where it does not exist.
at com.sun.org.apache.xerces.internal.dom.ParentNode.internalRemoveChild(ParentNode.java:503)
at com.sun.org.apache.xerces.internal.dom.ParentNode.removeChild(ParentNode.java:484)
at CombineSweeps$PTReplaceNodeList.apply(CombineSweeps.java:514)
(Line 514 is labelled below.) As far as I understand it, I've just verified that the element exists (because NodeList is live, its first entry will always be the next match or null). Interestingly, this isn't always a problem.
private static class PTReplaceNodeList extends PTBase {
private final String name;
private final String nextElement;
private final List<Node> childList;
...
int apply(Document document, Node parent, Node node_unused) {
NodeList nodes;
// A marker for where to insert our nodes.
// We make a guess using nextElement (if null, means at end).
Node refNode = null;
if (parent instanceof Document) { // root element
Document parDoc = (Document) parent;
nodes = parDoc.getElementsByTagName(name);
if (nextElement != null) {
refNode = parDoc.getElementsByTagName(nextElement).item(0);
}
} else {
Element parElt = (Element) parent;
nodes = parElt.getElementsByTagName(name);
if (nextElement != null) {
refNode = parElt.getElementsByTagName(nextElement).item(0);
}
}
while (true) {
// iterate through the list of nodes
Node node = nodes.item(0);
if (node == null) {
break;
}
// Reliable guess: insert before node following last in list
refNode = node.getNextSibling();
parent.removeChild(node); // line 514
}
for (Node child : childList) {
Node imported = document.importNode(child, true);
parent.insertBefore(imported, refNode);
}
return childList.size();
}
}
Edit: I used the following function as a replacement for getElementsByTagName() (see accepted answer).
/** Returns all direct children of node with name name.
*
* Note: not the same as getElementsByTagName(), which finds all descendants. */
static List<Node> getChildNodes( Node node, String name ){
ArrayList<Node> r = new ArrayList<Node>();
NodeList children = node.getChildNodes();
int l = children.getLength();
for( int i = 0; i < l; ++i ){
if( name.equals( children.item(i).getNodeName() ) )
r.add( children.item(i) );
}
return r;
}
how about
nodeToBeRemoved.getParentNode().removeChild(nodeToBeRemoved);
This is because when you are doing parent.removeChild(node), parent is not necessarily the parent of the node because getElementsByTagName() is doing a recursive search.
parent.removeChild(node) is throwing a NOT_FOUND_ERR because node is not a child of parent. I see that node comes from getElementsByTagName which might not be an immediate child of parent. It could be anywhere under parent.
Building on the diagnosis by #Maurice and #fahd...
Can't you just put a condition before
parent.removeChild(node);
such as
if (parent.isSameNode(node.getParentNode()))
Then it would only remove a direct child of the given parent.

Categories