4.40 Write a routine to list out the nodes of a binary tree in level-order. List the root, then nodes at depth 1, followed by nodes at depth 2, and so on.
4.44 Write a procedure to traverse a tree stored with child/sibling links.
4.49 Since a binary search tree with N nodes has N + 1 NULL pointers, half the space allocated in a binary search tree for pointer information is wasted. Suppose that if a node has a NULL left child, we make its self child link to its inorder predecessor, and if a node has a NULL right child, we make its right child link to its inorder successor. This is known as a threaded thre and the extra links are called threads.
a. How can we distinguish threads from real children pointers?
b. Write routines to perform insertions and deletions into a tree threaded in the manner described above.
c. What is the advantage of using threaded trees?
//4.40 bstree.hpp
#ifndef BSTREE_HPP__
#define BSTREE_HPP__
#include <iosfwd>
#include <vector>
template< typename Object >
class BSTree;
template< typename Object >
void levelOrderTraverse(const typename BSTree<Object>::Node*);
const int XIncrement = 30;
const int YIncrement = 40;
template< typename Object >
class BSTree {
private:
class Node {
public:
Node(const Object& val = Object(), Node* l = NULL, Node* r = NULL,
Node* p = NULL) : parent(p), lChild(l),
rChild(r), data(val), x(10), y(10)
{}
public:
Object data;
Node* lChild;
Node* rChild;
Node* parent;
int x, y;
};
public:
BSTree() : root(NULL), parent(NULL) {}
~BSTree(){ clear(); }
BSTree(const BSTree& rhs){}
BSTree& operator=(const BSTree& rhs){}
public:
bool contains(const Object& val) const
{ return contains(val, root); }
bool empty() const
{ return root == NULL; }
void printTree(std::ostream& out)
{
if(empty())
out << "empty tree/n";
else
printTree(root, out);
}
void clear()
{ clear(root); }
void add(const Object& val)
{ insert(val, root, parent); }
void del(const Object& val)
{ remove(val, root, parent); }
void calcXCoordinate()
{
int c = 0;
calcXCoordinate(root, c);
}
void calcYCoordinate()
{
int c = 0;
calcYCoordinate(root, c);
}
void levelOrderTraverse()
{ levelOrderTraverse(root); }
void postOrderTraverse()
{ postOrderTraverse(root); }
private:
void insert(const Object& val, Node* &t, Node* &parent)
{
if(t == NULL)
t = new Node(val, NULL, NULL, parent);
else if(val < t->data)
insert(val, t->lChild, t);
else if(t->data < val)
insert(val, t->rChild, t);
else
return;
}
void remove(const Object& val, Node* &t, Node* &parent)
{
if(t == NULL)
return;
if(val < t->data)
remove(val, t->lChild, t);
else if(t->data < val)
remove(val, t->rChild, t);
else if(t->lChild != NULL && t->rChild != NULL)
{
t->data = findMin(t->rChild)->data;
remove(t->data, t->rChild, t);
}
else if((t->lChild != NULL && t->rChild == NULL) ||
(t->lChild == NULL && t->rChild != NULL))
{
Node* old = t;
t = (t->lChild != NULL) ? t->lChild : t->rChild;
t->parent = old->parent;
delete old;
}
else
{
t->parent->rChild == t ? t->parent->rChild = NULL :
t->parent->lChild = NULL;
delete t;
}
}
bool contains(const Object& val, Node* t) const
{
if(t == NULL)
return false;
else if(val < t->data)
return contains(val, t->lChild);
else if(t->data < val)
return contains(val, t->rChild);
else
return true;
}
static Node* findMin(Node* t)
{
if(t != NULL)
while(t->lChild != NULL)
t = t->lChild;
return t;
}
static Node* findMax(Node* t)
{
if(t != NULL)
while(t->rChild != NULL)
t = t->rChild;
return t;
}
void clear(Node* &t)
{
if(t != NULL)
{
clear(t->lChild);
clear(t->rChild);
delete t;
}
t = NULL;
}
void printTree(Node* t, std::ostream& out)
{
if(t != NULL)
{
printTree(t->lChild, out);
out << "[ " << t->x << ", "
<< t->y << " ]" << t->data << "/n";
printTree(t->rChild, out);
}
}
void calcXCoordinate(Node* t, int& count)
{
if(t != NULL)
{
calcXCoordinate(t->lChild, count);
t->x += XIncrement * (count++);
calcXCoordinate(t->rChild, count);
}
}
void calcYCoordinate(Node* t, int count)
{
if(t != NULL)
{
t->y += YIncrement * (count++);
calcYCoordinate(t->lChild, count);
calcYCoordinate(t->rChild, count);
}
}
void levelOrderTraverse(const Node* t)
{
if(t != NULL)
{
std::cout << t->data << "/n";
if(!vec.empty())
{
vec.push_back(t);
const Node* p = vec.front();
vec.erase(vec.begin());
levelOrderTraverse(p->rChild);
}
else
vec.push_back(t);
if(t->lChild != NULL && t->rChild != NULL)
{
levelOrderTraverse(t->lChild);
}
else if(t->lChild != NULL || t->rChild != NULL)
{
levelOrderTraverse(t->rChild != NULL ? t->rChild : t->lChild);
}
}
}
void postOrderTraverse(Node* t)
{
if(t != NULL)
{
std::cout << t->data << "/n";
postOrderTraverse(t->lChild);
postOrderTraverse(t->rChild);
}
}
private:
Node* root;
Node* parent;
std::vector< const Node* > vec;
};
#endif
//4.44 tree.hpp
#ifndef TREE_HPP__
#define TREE_HPP__
#include <iosfwd>
template< typename Object >
class Tree {
public:
class Node { //haven't write insert routines so keep the Node public
public:
Node(const Object d = Object(),
Node* c = NULL, Node* s = NULL) :
data(d), child(c), sibling(s)
{}
public:
Node* child;
Node* sibling;
Object data;
};
public:
Tree(){}
~Tree(){}
void printTree()
{ printTree(root); }
Node* root;
private:
void printTree(Node* t)
{
if(t != NULL)
{
std::cout << t->data << "/n";
if(t->sibling != NULL)
printTree(t->sibling);
if(t->child != NULL)
printTree(t->child);
}
}
private:
Tree(const Tree&);
Tree& operator=(const Tree&);
};
#endif
//4.49 tbstree.hpp
#ifndef TBSTREE_HPP__
#define TBSTREE_HPP__
#include <iosfwd>
template< typename Object >
class ThreadBSTree {
private:
class Node {
public:
Node(const Object val = Object(), Node* l = NULL,
Node* r = NULL, bool p = true, bool s = true)
: data(val), left(l), right(r), pre(p), suc(s)
{}
Node(const Node& rhs)
{
left = rhs.left;
right = rhs.right;
data = rhs.data;
pre = rhs.pre;
suc = rhs.suc;
}
Node& operator=(const Node& rhs)
{ return Node(rhs); }
public:
Node* left;
Node* right;
bool pre;
bool suc;
Object data;
};
public:
class iterator {
public:
iterator() : current(NULL)
{}
Object& operator*()
{ return current->data; }
const Object& operator*() const
{ return current->data; }
const iterator& operator++()
{
if(current->suc)
{
current = current->right;
return current;
}
else
return current = findMin(current->right);
}
iterator operator++(int)
{
iterator old = *this;
++(*this);
return old;
}
const iterator& operator--()
{
if(current->pre)
return current = current->left;
else
return current = findMax(current->left);
}
iterator operator--(int)
{
iterator old = *this;
--(*this);
return old;
}
bool operator==(const iterator& rhs) const
{ return current == rhs.current; }
bool operator!=(const iterator& rhs) const
{ return !(rhs == *this); }
private:
Node* current;
iterator(Node* c) : current(c)
{}
friend class ThreadBSTree;
};
public:
ThreadBSTree() : root(NULL)
{}
~ThreadBSTree()
{ clear(); }
iterator begin()
{ return iterator(findMin(root)); }
const iterator begin() const
{ return iterator(findMin(root)); }
iterator end()
{ return iterator(NULL); }
const iterator end() const
{ return iterator(NULL); }
bool empty() const
{ return root == NULL; }
void insert(const Object val)
{ insert(val, root); }
void erase(const Object val)
{ erase(val, root); }
void printTree()
{ printTree(root); }
void clear()
{ clear(root); }
private:
static Node* findMin(Node* t)
{
while(t != NULL && t->pre == false)
while(t->left != NULL && t->pre == false)
t = t->left;
return t;
}
static Node* findMax(Node* t)
{
while(t != NULL && t->suc == false)
while(t->right != NULL && t->suc == false)
t = t->right;
return t;
}
void clear(Node* &t)
{
if(t != NULL)
{
clear(t->left);
clear(t->right);
delete t;
}
t = NULL;
}
void insert(const Object val, Node* &t, bool pre = true, bool suc = true)
{
if(t == NULL)
t = new Node(val, NULL, NULL, pre, suc);
else if(t->data < val)
{
Node* old = t->right;
t->right = (t->suc == true ? NULL : t->right);
insert(val, t->right);
if(t->suc)
{
t->suc = false;
t->right->left = t;
t->right->right = old;
}
}
else if(val < t->data)
{
Node* old = t->left;
t->left = (t->pre == true ? NULL : t->left);
insert(val, t->left);
if(t->pre)
{
t->pre= false;
t->left->right = t;
t->left->left = old;
}
}
else
;
}
void erase(const Object& val, Node* &t)
{
if(t == NULL)
return;
if(val < t->data)
{
if(!t->pre)
{
erase(val, t->left);
}
return;
}
else if(t->data < val)
{
if(!t->suc)
erase(val, t->right);
return;
}
else if((t->pre == false && t->left != NULL) &&
(t->suc == false && t->right != NULL))
{
t->data = findMin(t->right)->data;
erase(t->data, t->right);
}
else
{
Node* old = t;
if(t->pre == true && t->suc == false)
{
if(t->left->right == t) //right-right case
t->left->right = t->right;
else //left-right case
findMax(t->right)->right->left = t->right;
t = t->right;
}
else if(t->pre == false && t->suc == true)
{
if(t->right->left == t) //left-left case
t->right->left = t->left;
else //right-left case
findMin(t->left)->left->right = t->left;
t = t->left;
}
else
{
if(t->left != NULL && t->left->right == t) //right sub-tree case
{
t->left->suc = true;
t->left->right = t->right;
}
else if(t->right != NULL && t->right->left == t) //left sub-tree case
{
t->right->pre = true;
t->right->left = t->left;
}
}
delete old;
}
}
void printTree(Node* t)
{
if(t != NULL)
{
if(!t->pre)
printTree(t->left);
std::cout << t->data << "/n";
if(!t->suc)
printTree(t->right);
}
}
private:
Node* root;
};
#endif