Do you need all these classes? The code would probably shrink by 50% or more if we can simplify it.
To that end, and because all the static casts were making my head hurt, I added left() and right() methods to threadBinNode():
1 2 3 4 5 6
|
threadBinNode<BaseData> * &left() {
return reinterpret_cast<threadBinNode<BaseData> * &>(GtNode<BaseData>::firstChild);
}
threadBinNode<BaseData> * &right() {
return reinterpret_cast<threadBinNode<BaseData> * &> (GtNode<BaseData>::sibling);
}
| |
I also added a root() method to BinThreadTree:
1 2 3
|
threadBinNode<BaseData> * &root() {
return reinterpret_cast<threadBinNode<BaseData> * &> (BinSearchTree<BaseData>::root);
}
| |
I also removed the root member from BinThreadTree since you already have a root in one of the lower tree classes.
And I added (or fixed? I don't remember now) a destructor to threadBinNode:
1 2 3 4 5 6
|
template <class BaseData>
threadBinNode<BaseData>::~threadBinNode()
{
if (!leftThread) delete left();
if (!rightThread) delete right();
}
| |
preOrderAdd()
was just a mess. For example, it never called precedes(). How can you know where to insert the item if you don't compare to nodes in the tree? Also why do you have preorderAdd and inOrderAdd?? There should be just one add() method (and it should probably overload BinTree::add(), but that's a totally different story).
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
|
template <class BaseData>
bool BinThreadTree<BaseData>::preOrderAdd( BaseData item)
{
threadBinNode<BaseData>* q, * p;
bool left, done;
p = new threadBinNode<BaseData>;
p->info = item;
q = root()->left();
left = true;
done = root()->leftThread;
while (!done)
{
left = BinSearchTree<BaseData>::precedes(item, q->info);
if (left) {
if (q->leftThread) {
break;
} else {
q = q->left();
}
} else {
if (q->rightThread) {
break;
} else {
q = q->right();
}
}
}
// Now insert p as the left or right child of q
p->leftThread = true;
p->rightThread = true;
if (left)
{
p->left() = q->left();
p->right() = q;
q->left() = p;
q->leftThread = false;
}
else
{
p->right() = q->right();
p->left() = q;
q->right() = p;
q->rightThread = false;
}
return true ;
}
| |
Then inorder() was pretty easy:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
|
template <class BaseData>
void BinThreadTree<BaseData>::inorder(void (*processNode)(BaseData &item))
{
threadBinNode<BaseData> *p;
p = root();
while (!p->leftThread) {
p = p->left();
}
while (p != root()) {
processNode(p->info);
if (p->rightThread)
p = p->right();
else
{
p = p->right();
while (!p->leftThread)
p = p->left();
}
}
}
| |
I think the big question is still "why so many classes?" There seem to be far more than necessary to me. Are you using these base classes somewhere else? Do you expect that you will be? Unless the answer to one of these questions is "yes" then the base classes just get in the way (as evidenced by having to write a cumbersome static cast every time you accessed a pointer to a node).