I have a binary search class and i want to write a function for deleting a special node but i don't know how.
the basic class is :
class Node {
friend class Tree;
private:
long long rep;
Node *left, *right;
string data;
public:
Node( string d )
: data( d ), left( NULL ), right( NULL ), rep( 1 ) {}
};
class Tree {
private:
Node *root;
public:
void delete_node( Node *cur , string s );
void delete_node_helper( string s );
};
There're 3 parts in deletion of a node from the binary search tree:
Find a node to delete.
Delete a node (free memory, etc).
Merge children of the deleted node.
In your particular code example, I'd say that looking for the node should be the responsibility of void delete_node_helper(string s);, deleting a node should be the responsibility of void delete_node(Node *cur, string s);, and merging the children should be the responsibility of the newly created function.
Given that the algorithms of the first two parts are pretty straighforward, let me explain in detail only the third one.
To merge two BSTs (of which we know which one is left and which one is right) we should decide who will be whose child and perform the recursive merging if necessary. The code looks like this:
Node* merge(Node* left, Node* right) {
if (left == nullptr) {
return right;
}
if (right == nullptr) {
return left;
}
if (rand() & 1) { // <- chose parent
left->right = merge(left->right, right);
return left;
}
right->left = merge(left, right->left);
return right;
}
On the marked line we actually make a decision on which node will be whose parent. In this particular example, the result is random, but any other strategy may be implemented. For example, you could store heights (or sizes) in all nodes of your tree and make the smaller tree root child of a larger tree root.
Delete a special node from a BST tree
I just tried the deletion code in above link and it worked nice.
Related
I am writing a templated binary search tree class, the function I use to create the binary search tree is the following:
void insert(const Comparable & x, BinaryNode<Comparable> * & t)
{
if (t==NULL)
t = new BinaryNode<Comparable>(x, NULL, NULL);
else if (x < t->element)
insert(x, t->left);
else if (x>t->element)
insert(x, t->right);
else
; // Duplicate;
}
and BinaryNode is another templated class as the following:
template <class Comparable>
class BinaryNode
{
public:
Comparable element;
BinaryNode *left;
BinaryNode *right;
BinaryNode(const Comparable & theElement,
BinaryNode *lt, BinaryNode *rt)
: element(theElement), left(lt), right(rt) { }
};
The problem is, whenever I create a new tree, it adds the first element as the root. Then even if the next element I want to add is greater than the root it adds to the left of the root. For the elements on the left of the tree, this problem does not occur, it propoerly adds it to the right whenever necessary. Can you help?
EDIT: Problem solved. I was reading a file line by line and storing those lines into nodes, it turned out that the getline gets the first line of the file in a way that it starts with weird characters-even though there exists none. Those characters always had a greater value from other normal letters, thus it always goes to the left of the tree.
I tried searching for this problem on stackoverflow but couldn't find it, so pardon me if it already existed.
So, what I wish to do is to create a function that traverses a tree and returns a pointer to the Node with the highest value. The Tree would be unordered and asymmetric, and will not have a fixed depth. Each node has a pointer to its Parent node, a list containing its Child nodes, and an integer named 'value'. And the tree would have a pointer to its root node, like this:
struct Node
{
private:
Node* parent;
list<Node> childs;
int value;
public:
// Getters, setters and constructors
}
struct Tree
{
private:
Node* root;
public:
// Getters, setters and constructors
}
And, as I stated before, I wish to make a function that traverses the entire tree, aka every single Node in the entire tree regardless of the depth, and returns a pointer to the node with the highest value. I assume it'll require recursion, but I can't figure out a way to do this.
Pardon me if my question seems dumb / stupid, but I really need help
You can use recursive method, which returns the pointer to the node with maximal value of current and child nodes:
struct Node
{
...
Node* getMaxNode()
{
Node* maxNode = this;
for (auto& child : this->childs) {
Node* childsMaxNode = child.getMaxNode();
if (childsMaxNode->getValue() > maxNode->getValue())
maxNode = childsMaxNode;
}
return maxNode;
}
}
If current node doesn't have child nodes, it will return pointer to the current node. So, in struct Tree you can implement something like this:
struct Tree
{
Node* getMax()
{
return this->root->getMaxNode();
}
}
I have to make an implementation of the following class in C++:
struct Node {
Node* parent;
Node* left;
Node* right;
std::string name;
};
class BinaryTree {
public:
BinaryTree();
std::string ToString() const;
void RotateLeft(Node* node);
void RotateRight(Node* node);
void MakePerfect();
private:
void CreateVine();
void MakePerfectFromVine();
private:
Node *root;
};
This class implements the DSW algorithm for making a Binary tree perfect (all levels are full, except the last one)
I have done an implementation which works, I tested it and everything seem fine but I had to change the rotate functions thus:
void RotateLeft(Node*& node);
void RotateRight(Node*& node);
Unfortunately the person who set me this task said that I'm forbidden to change them. But the unaltered functions don't work. I use them in CreateVine() and MakePerfectFromVine():
void CreateVine() {
Node *current = root;
while(current != NULL)
if(current->left != NULL){
current=current->left;
rotateRight(current);
}
else
current = current->right;
}
In this fragment the pointer current points to a node in the tree. After the node is rotated, it will have changed its parent and/or left and/or right child, but current will point to the old node with the old information. In order for the changes made in the rotate function to be reflected outside of the rotate function, I have to use reference-to-pointer, pointer-to-pointer or the function itself has to return the node;
The only way I can think of to fix this problem is if I know that the binary tree doesn't allow duplicate elements, after I rotate the node I search for its string value and set current to point to it, but I'm not sure if the binary tree doesn't allow duplicate elements and that would increase the time complexity of the algorithm.
Is there any way of avoiding the use of reference-to-pointer and pointer-to-pointer?
Excluding the root of the tree, for which you might have to think something else, the pointer to a given node inside the tree can be obtained with an extra level of indirection:
Node **pp;
if (node->parent->left == node)
pp = &node->parent->left;
else
pp = &node->parent->right;
So you can actually maintain your algorithm and just resolve the reference doing this inside the function. Note that this is a sketch, you will have to check for the root (parent==0) and operate differently there
I'm writing a program in C++ that uses genetic techniques to optimize an expression tree.
I'm trying to write a class Tree which has as a data member Node root. The node constructor generates a random tree of nodes with +,-,*,/ as nodes and the integers as leaves.
I've been working on this awhile, and I'm not yet clear on the best structure. Because I need to access any node in the tree in order to mutate or crossbreed the tree, I need to keep a dicionary of the Nodes. An array would do, but it seems that vector is the recommended container.
vector<Node> dict;
So the Tree class would contain a vector dict with all the nodes of the tree (or pointers to same), the root node of the tree, and a variable to hold a fitness measure for the tree.
class Tree
{
public:
typedef vector<Node>dict;
dict v;
Node *root;
float fitness;
Tree(void);
~Tree();
};
class Node
{
public:
char *cargo;
Node *parent;
Node *left;
Node *right;
bool entry;
dict v;
Node(bool entry, int a_depth, dict v, Node *pparent = 0);
};
Tree::Tree()
{
Node root(true, tree_depth, v);
};
There seems to be no good place to put typedef vector<Node>dict;, because if it goes in the definition of Tree, it doesn't know about Node, and will give an error saying so. I havn't been able to find a place to typedef it.
But I'm not even sure if a vector is the best container. The Nodes just need to be indexed sequentally. The container would need to grow as there could be 200 to 500 Nodes.
I think a standard Binary Tree should do... here is an example of a (binary) expression tree node:
const int NUMBER = 0, // Values representing two kinds of nodes.
OPERATOR = 1;
struct ExpNode { // A node in an expression tree.
int kind; // Which type of node is this?
// (Value is NUMBER or OPERATOR.)
double number; // The value in a node of type NUMBER.
char op; // The operator in a node of type OPERATOR.
ExpNode *left; // Pointers to subtrees,
ExpNode *right; // in a node of type OPERATOR.
ExpNode( double val ) {
// Constructor for making a node of type NUMBER.
kind = NUMBER;
number = val;
}
ExpNode( char op, ExpNode *left, ExpNode *right ) {
// Constructor for making a node of type OPERATOR.
kind = OPERATOR;
this->op = op;
this->left = left;
this->right = right;
}
}; // end ExpNode
So when you're doing crossover or mutation and you want to select a random node you just do the following:
Count the number of nodes in the tree (only need to do this ones in the constructor).
Select a random index from 0 to the size of the tree.
Visit each node and subtract 1 from the random index until you reach zero.
Return the node when the index is 0.
In this case you don't need to know anything about the parent of the node. So mating/mutation should look like this:
select nodeX
select nodeY
if( Rand(0,1) == 1 )
nodeY->left = nodeX;
else
nodeY->right = nodeX;
And that should be it...
I don't think the Node or the Tree are the first classes to write.
I'd start with Expression. In your case you need at least a BinaryExpression, as well as an expression with no subnodes (constants or variables). Each Binary expression should contain auto_ptr<Expression> lhs and auto_ptr<Expression> rhs.
You could then easily write a function to enumerate through the expression tree's members. If performance turns out to be relevant, you can cache the list of expressions in the tree, and invalidate it manually when you change the expression. Anything more advanced is likely to be slower and more error prone.
I don't see why an expression needs to know it's parent expression. It only makes life harder when you start editing expressions.
You may implement a list over nodes. Then, each node will have two additional pointers inside:
class Node{
...
Node* sequentialPrevious;
Node* sequentialNext;
...
}
And so will the tree:
class Tree{
...
Node* sequentialFirst;
Node* sequentialLast;
...
}
Than you will be albe to move bidirectionally over nodes just by jumping to sequentialFirst or sequentialLast and then iteratively to sequentialNext or sequentialPrevious. Of course, Node constructor and destructor must be properly implemented to keep those pointers up to date.
edit
Clafification: The intention is not to remove the node from the original list. But to create an identical node (data and children wise) to the original and insert that into the new list. In other words, a "move" does not imply a "remove" from the original.
endedit
The requirements:
Each Node in the list must contain a reference to its previous sibling
Each Node in the list must contain a reference to its next sibling
Each Node may have a list of child nodes
Each child Node must have a reference to its parent node
Basically what we have is a tree structure of arbitrary depth and length. Something like:
-root(NULL)
--Node1
----ChildNode1
------ChildOfChild
--------AnotherChild
----ChildNode2
--Node2
----ChildNode1
------ChildOfChild
----ChildNode2
------ChildOfChild
--Node3
----ChildNode1
----ChildNode2
Given any individual node, you need to be able to either traverse its siblings. the children, or up the tree to the root node.
A Node ends up looking something like this:
class Node
{
Node* previoius;
Node* next;
Node* child;
Node* parent;
}
I have a container class that stores these and provides STL iterators. It performs your typical linked list accessors. So insertAfter looks like:
void insertAfter(Node* after, Node* newNode)
{
Node* next = after->next;
after->next = newNode;
newNode->previous = after;
next->previous = newNode;
newNode->next = next;
newNode->parent = after->parent;
}
That's the setup, now for the question. How would one move a node (and its children etc) to another list without leaving the previous list dangling?
For example, if Node* myNode exists in ListOne and I want to append it to listTwo.
Using pointers, listOne is left with a hole in its list since the next and previous pointers are changed. One solution is pass by value of the appended Node. So our insertAfter method would become:
void insertAfter(Node* after, Node newNode);
This seems like an awkward syntax. Another option is doing the copying internally, so you'd have:
void insertAfter(Node* after, const Node* newNode)
{
Node *new_node = new Node(*newNode);
Node* next = after->next;
after->next = new_node;
new_node->previous = after;
next->previous = new_node;
new_node->next = next;
new_node->parent = after->parent;
}
Finally, you might create a moveNode method for moving and prevent raw insertion or appending of a node that already has been assigned siblings and parents.
// default pointer value is 0 in constructor and a operator bool(..)
// is defined for the Node
bool isInList(const Node* node) const
{
return (node->previous || node->next || node->parent);
}
// then in insertAfter and friends
if(isInList(newNode)
// throw some error and bail
I thought I'd toss this out there and see what folks came up with.
Let's call the node that we are going to remove current. Only the nodes pointed to by current, namely current->previous, current->next, current->child, and current->parent refer to the node current. For example, current->previous->next == current if the current node's previous node is non-null. So, we can easily excise the current node from the list like so:
Vertical Links
A node keeps its children, but it needs to be excised from its parent. This is done like so:
Let parent = current->parent
if parent is non-null:
if parent->child == current:
parent->child = current->next
current->parent = null
Horizontal Links
The following code unlinks the current node in the horizontal (next/previous) direction:
Let prev = current->previous
Let next = current->next
if prev is non-null:
prev->next = next
if next is non-null:
next->previous = prev
current->previous = null
current->next = null
Granted, this is still a bit messy, but if you break the linked list functionality into small functions (which it looks like you are already doing) and use good comments, then it's really not that bad, I don't think.
First, I agree that, if you're copying the node and not actually removing it from the original tree, the operation should be called a copy, not a move!
Second, I recommend you separate the operation that actually does the copying from the operation that does insertion. This will make it much more flexible, if say for example you need to insert nodes from other sources into your destination, or you want to copy the node for other purposes.
Third, you didn't specify whether Node is polymorphic. If it is, I would implement a method like the following to do the copy:
virtual Node* clone();
You have a couple of design decisions to make here:
Do you want to preserve next, prev, and parent when you do a clone? I think it makes sense to zero them out.
Do you want to do a deep copy of the children as well when you do a clone? Depending on the use case, you may want to do one or the other, or allow for both.
Fourth, you assume that insertion should fail if the parent/prev/next pointers are already set. You can do this, but you may benefit down the road from a more powerful insertion operation that simply removes nodes from their existing tree in this case. Either will behave consistently.
Fifth, you can't be passing const Nodes around if you're going to be fixing up that node's pointers.
Let's assume for the moment that you decide to zero out the linked list pointers but decide to deep copy the children. Then your code might look like:
class Node {
public:
Node() : prev(NULL), next(NULL), parent(NULL), child(NULL) { }
virtual Node* clone() {
Node* newN = new Node();
newN->cloneChildren(*this);
return newN;
}
Node* lastChild() const { /* left as exercise */ }
void insert(Node* node_) { insertAfter(node_, lastChild()); }
void insertAfter(Node* node_, Node* prevSibling_) {
ASSERT(node_);
if (! prevSibling_) { // assume we want to push to front of child list
prevSibling_ = child; // will be NULL if we have no children
}
ASSERT(! prevSibling_ || prevSibling_->parent == this);
if (node_->parent) {
// assume you want to move the child in this case
node_->parent->remove(node_);
}
node_->parent = this;
node_->prev = prevSibling_;
if (prevSibling_) {
node_->next = prevSibling_->next;
prevSibling_->next = node_;
} else {
/* the new child is the only child - left as exercise */
}
}
void remove(Node* child_) { /* left as exercise */ }
protected:
virtual void cloneChildren(const Node& rhs) { /* left as exercise */ }
};
And the code that does the copying from one tree to another simply looks something like:
Node* myNode = ...
Node* someChildInListTwo = findPlaceToInsert(listTwo);
listTwo->insertAfter(myNode->clone(), someChildInListTwo);
In this case we have turned your one somewhat tangled operation into a set of discrete operations that you can use in a wide variety of cases:
a clone() operation that allows you to copy arbitrary nodes, whether or not they've been added to trees yet
an insert() operation that will automatically do a move for you if you want, and correctly handles adding to the front of the child list
a remove() operation that fell out naturally as a byproduct of how we wanted insertion to behave, but which can be used on its own
a simple mechanism to copy+insert the node if you don't want to remove the node from the original tree