I have a binary tree, i want to print all non-boundary nodes.
Boundary Nodes:- All leaf nodes+all nodes on path from root to leftest node+all nodes from root to rightest node.
I ave done this using an extra boolean in tree structure to identify whether it's boundary node or not and then doing a traversal and printing if not boundary nodes. Can someone come up with a better approach, because it's using some extra space(though very less).
One observation you might find helpful is that a non-boundary node in a binary tree is one that (a) isn't a leaf and (b) is one where along the access path to the node, you've taken a step left and a step right. Therefore, one option would be to do a normal tree traversal, tracking whether you've gone left and gone right along the way. Here's some pseudocode:
function printNonBoundaryNodesRec(root, goneLeft, goneRight) {
if (root == null or root is a leaf) return;
if (goneLeft and goneRight) print root.value
printNonBoundaryNodesRec(root.left, true, goneRight);
printNonBoundaryNodesRec(root.right, goneLeft, true);
}
function printNonBoundaryNodes(root) {
printNonBoundaryNodesRec(root, false, false);
}
Hope this helps!
Related
What recursion algorithm should I use to calculate the number of black nodes in each path?
In a red-black tree, the number of black nodes on any path is constant. The process can be broken into two parts.
Part 1: get a path. Here, a path is defined as a sequence of nodes.
To get a path from the empty tree, return the path containing only the empty tree.
To get a path from a non-empty tree, get the path of its left child and append the non-empty tree to this path.
Part 2: count the number of black nodes in the path.
Hopefully, this one is self-explanatory.
What recursion algorithm should I use to calculate the number of black nodes in each path?
None. Use an iterative approach. So if you start from the root, increment a counter initialised to 0 every time you see a black node including the root and keep going leftwards until the left node pointer is null. Whatever the count is, that is the black depth down any given path. In pseudo code:
int bcount = 0;
Node *currnode = GetRoot();
while (currnode != NULL)
{
if (currnode->GetColour() == BLACK)
++bcount:
currnode = currnode->Left();
}
As part of my project, I have to use Decision tree that I am using "fitctree" function that is the Matlab function for classified my features that extracted with PCA.
I want to control number of Tree and tree depth in fitctree function.
anyone knows how can I do this? for example changed the number of trees to 200 and tree depth to 10. How am I going to do this?
Is it possible to change these value in decision tree?
Best,
fitctree offers only input parameters to control the depth of the resulting tree:
MaxNumSplits
MinLeafSize
MinParentSize
https://de.mathworks.com/help/stats/classification-trees-and-regression-trees.html#bsw6baj
You have to play with those parameters to control the depth of your tree. Thats because the decision tree only stops growing when purity is reached.
Another possibility would be to turn on pruning. Pruning will reduce the size of your tree by removing sections of the tree that provide little power to classify instances.
Let me assume that you are using ID3 algorithm. Its pseudocode can provide a way to control the depth of the tree.
ID3 (Examples, Target_Attribute, Attributes, **Depth**)
// Check the depth of the tree, if it is 0, we are going to break
if (Depth == 0) { break; }
// Else continue
Create a root node for the tree
If all examples are positive, Return the single-node tree Root, with label = +.
If all examples are negative, Return the single-node tree Root, with label = -.
If number of predicting attributes is empty, then Return the single node tree Root,
with label = most common value of the target attribute in the examples.
Otherwise Begin
A ← The Attribute that best classifies examples.
Decision Tree attribute for Root = A.
For each possible value, vi, of A,
Add a new tree branch below Root, corresponding to the test A = vi.
Let Examples(vi) be the subset of examples that have the value vi for A
If Examples(vi) is empty
Then below this new branch add a leaf node with label = most common target value in the examples
// We decrease the value of Depth by 1 so the tree stops growing when it reaches the designated depth
Else below this new branch add the subtree ID3 (Examples(vi), Target_Attribute, Attributes – {A}, Depth - 1)
End
Return Root
What algorithm does your fictree function try to implement?
I'm still getting used to data structures, and I'm comfortable with traversing binary trees in the various ways, but I'm presented now with a situation where I have a normal binary tree, constructed of nodes that only know have data, left and right attributes.
However I want to transfer it into a "smarter" binary tree. This tree is to know its parent node, its total subnodes, and the level in the total tree it is at.
I'm really struggling with how I'd go about transferring the one "dumber" tree into the smarter version. My first instinct is to traverse recursively, but I'm not sure how I'd then be able to distinguish the parent and the level.
Copy the old tree to a new tree, using the normal recursive methods to traverse the original.
Since you're adding new attributes to the nodes, I presume you'll need to construct new nodes with fields for the new attributes.
Define a recursive function to copy the (sub)tree rooted at a given node. It needs as input its depth and parent. (The parent, of course, needs to be what will be its parent in the new tree.) Let it return the root of the new (sub)tree.
function copy_node (old_node, new_parent, depth) -> returns new_node {
new_node = new node
new_node.data = old_root.data // whatever that data might be
new_node.depth = depth
new_node.parent = parent
new_node.left = copy_node (old_node.left, new_node, depth + 1)
new_node.right = copy_node (old_node.right, new_node, depth + 1)
return new_node }
Copy the whole tree with
new_tree = copy_node (old_tree, nil, 0)
If you're using a language where fields can be added to existing objects willy-nilly, you don't even have to do the extra copying:
function adorn_node (node, parent, depth) {
node.parent = parent
node.depth = depth
adorn_node (node.left, node, depth + 1)
adorn_node (node.right, node, depth + 1) }
and start the ball rolling with
adorn_node (root, nil, 0)
That having been said, you will probably discover that there is a very good reason why most binary tree implementations do not contain these extra fields. It's a lot of work to maintain them across the many different operations you want to perform on trees. depth, especially, is hard to keep correct when you need to re-balance a tree.
And the fields don't generally buy you anything. Most algorithms that operate on trees do so using recursive functions, and as you can see from the above examples it's really easy to re-calculate both parent and depth on the fly while you're walking the tree. They don't need to be stored in the nodes themselves.
Tree-balancing often needs to know the difference in heights of the left and right subtrees. ("depth" is the distance to the root; "height" is the distance to the most distant leaf node in the subtree.) height is not so easy to calculate on the way down from the root, but fortunately you're usually only interested in which of the subtrees has the greatest height, and for that it's usually sufficient to store only the values -1, 0, +1 in each node.
I'm trying to write a function to remove a node from a binary tree. I haven't coded the function yet, and I am trying to think about the different conditions I should consider for removing a node. I am guessing that the possible conditions are:
The node has no children
The node has one child
The node has 2 children
In each of these cases what would be the algorithm to perform a delete function?
This is something you would find in any standard textbook about algorithms, but let's suppose you are interested in the unbalanced case (balanced trees usually performs some rebalancing operations called "rotations" after a removal) and you use the "obvious" datastructure (a tree_node structure that holds the value and two pointers to other tree_node):
No children: release the memory hold by the node and set the parent's child link that pointed to it as NULL;
One child: release the memory hold by the node and set the parent's child link that pointed to it as the address of its unique child;
Two children: this is indeed the "complicated" case. Find the rightmost node of the left child (or the leftmost node of the right child), take its value, remove it (it is "case 1", so it is easy and can be done recursively) and set the current node's value as the one of that node. This is O(tree_height) = O(n), but it is not a problem (at least in theory) because this would be neverthless the complexity of finding a node.
Does your tree have any additional properties?
Is it an AVL?
If not, there are some pretty obvious and straightforward ways to do what you want (which will depend on your data representation, as Vitalij said).
And if it is an AVL for example, there ALSO are some well known method for doing that (wikipedia will tell you more on that topic)
First task is to find whether node exists which will be done during search and rest of your conditions are correct.
Leaf node: set the parent's child (right/left) to NULL.
Has one child: Just set the child of the node to be deleted to its parent's child.
Has two children: Basically have to re-order the whole subtree here by pruning the subtree to by finding new children for the node to be deleted.
Assuming you are dealing with general binary trees, do the following,
Node has no child- ie it is a leaf : Conveniently delete it..
Node has one child - Make the parent of the node to be deleted parent of its child , then delete the node. ie, if A->Parent = B; C->Parent = A; and A has to be deleted, then 1. Make C->Parent = B; 2. Delete A;
Tricky one.... Yes, replacing the node to be deleted by the left most child of the right subtree work, or by the rightmost tree of the left subtree, either will do... because it can be seen like this,
When a node is deleted, it has to be replaced by a node which satisfies some properties...
Lets say if our binary tree represents sorted numbers (in increasing order) in inorder traversal, then the deleted node should be replaced by some node from either of its subtrees. That should be larger in value than the whole remaining left subtree, and smaller than the whole remaining right subtree (remaining means the subtree remaining after adjusting for the deleted node successfully). Only two such nodes exist, leftmost leaf of the right subtree, or the rightmost node of left one.
Hence, replacing the deleted node from either one suffices...!!
Delete the given keys one at a time from the binary search tree. Possible equal keys were inserted into the left branch of the existing node. Please note that the insertion strategy also affects how the deletion is performed
BinarySearchTree-Delete
Node Delete(Node root, Key k)
1 if (root == null) // failed search
2 return null;
3 if (k == root.key) // successful search
4 return DeleteThis(root);
5 if (k < root.key) // k in the left branch
6 root.left = Delete(root.left, k);
7 else // k > root.key, i.e., k in the right branch
8 root.right = Delete(root.right, k);
9 return root;
Node DeleteThis(Node root)
1 if root has two children
2 p = Largest(root.left); // replace root with its immediate predecessor p
3 root.key = p.key;
4 root.left = Delete(root.left, p)
5 return root;
6 if root has only left child
7 return root.left
8 if root has only right child
9 return root.right
10 else root has no children
11 return null
Node Largest(Node root)
1 if root has no right child
2 return root
3 return Largest(root.right)
I am trying to solve a problem of finding a max repetitive sub-tree in an object tree.
By the object tree I mean a tree where each leaf and node has a name. Each leaf has a type and a value of that type associated with that leaf. Each node has a set of leaves / nodes in certain order.
Given an object tree that - we know - has a repetitive sub-tree in it.
By repetitive I mean 2 or more sub-trees that are similar in everything (names/types/order of sub-elements) but the values of leaves. No nodes/leaves can be shared between sub-trees.
Problem is to identify these sub-trees of the max height.
I know that the exhaustive search can do the trick. I am rather looking for more efficient approach.
you could implement a dfs traversal generating a hash value for each node. Store these values with the node height in a simple array. Sub-tree candidates are duplicate values, just check that the candidates are ok since two different sub-trees could yield same hash value.
Assuming the leafs and internal nodes are all of type Node and that standard access and traversal functions are available :
procedure dfs_update( node : Node, hashmap : Hashmap )
begin
if is_leaf(node) then
hashstring = concat("LEAF",'|',get_name_str(node),'|',get_type_str(node))
else // node is an internal node
hashstring = concat("NODE",'|',get_name_str(node))
for each child in get_children_sorted(node)
dfs_update(child,hashmap)
hashstring = concat(hashstring,'|',get_hash_string(hashmap,child))
end for
end if
// only a ref to node is added to the hashmap, we could also add
// the node's height, hashstring, whatever could be useful and inapropriate
// to keep in the Node ds
add(hashmap, hash(hashstring),node)
end
The tricky part is after a dfs_update, we have to get the list of collinding nodes in the hasmap by descending height and check two by two they are really repetitive.