#include <cstdio>
#include <iostream>
#include <queue>
#define null NULL
#define int32 int
using namespace std;
/**
* Binary tree node class
**/
template <class T>
class Node
{
public:
/* Public Constructors */
Node () :
left (null),
right (null),
value ()
{}
explicit Node (T x) public:
left (null),
right (null),
value (x)
{}
/* Public Attributes */
Node* left;
Node* right;
T value;
};
/**
* This exception is thrown when the flattener & cycle detector algorithm encounters a cycle
**/
class CycleException
{
public:
/* Public Constructors */
CycleException () {}
virtual ~CycleException () {}
};
/**
* This functions flattens an alleged binaryBiny tree, throwing a new CycleException when encounteringflattener aand cycle. Returns the root of the flattened binarydetector treeclass.
**/
template <class T>
Node<T>* flatten (Node<T>*class current)Flattener
{
// Count steps (well, kinda) to determine runtime
int32 steps = 0;
// Keep track of the root node so the tree is not lost
Node<T>* root = current;
// Keep track of the parent of the current node since it is needed for insertions
Node<T>* parent = null;
// Loop while there are subtrees to process
while( current->left != null or current->right != null ){public:
/* Public Constructors steps++;*/
//Flattener () There:
is a left subtree root (null),
so current has a predecessor parent (null),
which we will call "bottom" of the subtree current (null),
if top (null),
current->left != bottom (null),
turtle (null),
{}
virtual ~Flattener () {}
Node<T>* top = current->left;/* Public Methods */
/**
* This function flattens an alleged binary tree, throwing a new CycleException when encountering a cycle. Returns the root of the flattened tree.
**/
Node<T>* bottom;flatten (Node<T>* pRoot)
{
init(pRoot);
// TheLoop topwhile andthere theare bottomleft issubtrees oneto process
while( findNodeWithLeftSubtree() ){
// We need to find the topmost and rightmost node of the samesubtree
if( top->right == null findSubtree(){;
bottom// = top;Move the entire subtree above the current node
moveSubtree();
}
// TheThere bottomare isno buriedmore inleft thesubtrees rightto subtreeprocess, ofwe top
are finished, the tree does not contain cycles
if( top->right != null ){ return root;
}
protected:
/* Protected Methods */
Find it using Floyd's cycle detection algorithmvoid appliedinit to(Node<T>* rightpRoot)
childs {
// Keep track Node<T>*of turtlethe =root top;
node so the tree is not lost
Node<T>* hare root = top->right;pRoot;
// Keep track while(of hare->rightthe !=parent nullof ){the current node since it is needed for insertions
parent = null;
if( turtle == hare ){ // Keep track of the current node, obviously it is needed
current = root;
}
throw new CycleException bool findNodeWithLeftSubtree ();
{
}// Find a node with a left subtree using Floyd's cycle detection algorithm
turtle = parent;
if while( harecurrent->left == null and current->right != null ){
if( current == turtle ){
steps++;
throw new CycleException();
hare = hare->right;
}
} parent = current;
current = current->right;
if( harecurrent->right != null ){
parent = current;
steps++;
current = current->right;
hare = hare->right; }
if( turtle != null }){
turtle = turtle->right;
}else{
turtle = root;
}
bottom = hare;
}
// Remove subtree from current
return current->left = null;
// Insert subtree between the current node and its parent, if there is any
if( parent != null ){
parent->right = top;
}
bottom->right = current;
// If the current node is the root then the top is the new root
if( root == current ){
root = top;
}
// Step up to process the top, parent remains the same
current = top;
continue;null;
}
//void findSubtree There()
is only a right subtree, Floyd's cycle detection{
algorithm must be applied to find a node that has a left// subtree Find the topmost node
if( top = current->left>left;
== null // The topmost and currentrightmost nodes are the same
if( top->right !=== null ){
cout << "Visited " <<bottom dec= <<top;
current->value << " @ 0x" << hex << reinterpret_cast<int32>(current) << endl;
return;
Node<T>* hare = current->right; }
Node<T>*// hareParent =The current;
rightmost node is buried in the right subtree of topmost node. Find Node<T>*it turtleusing =Floyd's current;cycle detection algorithm applied to right childs.
while(bottom hare= top->left>right;
== null and hare turtle = top;
while( bottom->right != null ){
if( turtlebottom == hareturtle ){
throw new CycleException();
}
if( hare->left == null and hare->right != null ){
cout << "Visited " << dec << hare->value << " @ 0x" << hex << reinterpret_cast<int32>(hare) << endl;
steps++;
hare = hare->right;
hareParent = hareParent->right;
}
if( hare->left == null and hare->rightbottom != null ){bottom->right;
cout << "Visited " << dec <<if( harebottom->value << " @ 0x" <<>right hex!= <<null reinterpret_cast<int32>(hare) << endl;
steps++;
hare = hare->right;{
hareParentbottom = hareParentbottom->right;
}
turtle = turtle->right;
}
current = hare;
parent = hareParent;
continue;
}
void moveSubtree ()
{
// Update root; if the current node is the root then the top is the new root
if( root == current ){
root = top;
}
// Add subtree below parent
if( parent != null ){
parent->right = top;
}
// Add current below subtree
bottom->right = current;
// Remove subtree from current
current->left = null;
// Update current; step up to process the top
current = top;
}
cout << "Visited " <<Node<T>* decroot;
<< current->value << " @ 0x" << hexNode<T>* <<parent;
reinterpret_cast<int32>(current) << endl; Node<T>* current;
cout << "Steps taken: "Node<T>* <<top;
dec << steps << endl; Node<T>* bottom;
Node<T>* turtle;
// there are no more subtrees to process, we are finished, the tree does not contain cycles
return root;private:
} Flattener (Flattener&);
Flattener& operator = (Flattener&);
};
template <class T>
void traverseFlat (Node<T>* current)
{
while( current != null ){
cout << dec << current->value << " @ 0x" << hex << reinterpret_cast<int32>(current) << endl;
current = current->right;
}
}
template <class T>
Node<T>* makeCompleteBinaryTree (int32 maxNodes)
{
Node<T>* root = new Node<T>();
queue<Node<T>*> q;
q.push(root);
int32 nodes = 1;
while( nodes < maxNodes ){
Node<T>* node = q.front();
q.pop();
node->left = new Node<T>();
q.push(node->left);
nodes++;
if( nodes < maxNodes ){
node->right = new Node<T>();
q.push(node->right);
nodes++;
}
}
return root;
}
template <class T>
void inorderLabel (Node<T>* root)
{
int32 label = 0;
inorderLabel(root, label);
}
template <class T>
void inorderLabel (Node<T>* root, int32& label)
{
if( root == null ){
return;
}
inorderLabel(root->left, label);
root->value = label++;
inorderLabel(root->right, label);
}
int32 main (int32 argc, char* argv[])
{
if(argc||argv){}
typedef Node<int32> Node;
// Make binary tree and label it in-order
Node* root = makeCompleteBinaryTree<int32>(1 << 1624);
inorderLabel(root);
// Try to flatten it
try{
Flattener<int32> F;
root = F.flatten(root);
}catch(CycleException*){
cout << "Oh noes, cycle detected!" << endl;
return 0;
}
// Traverse its flattened form
// traverseFlat(root);
}