I'm having trouble implementing a threaded Binary Search Tree in C++. I have a non-threaded tree completely implemented (see below code). What I'm having difficulty with is setting the threads to point to the correct parent node (without having an explicit parent pointer). (I have two functions - print() and printInOrder() that both work fine for a non-threaded binary tree that I need to work for a threaded one.)
My trouble is in the inserthelp() function. I can't figure out how to set the threads correctly. I have looked at countless sites and tried what feels like everything but the right answer. I've tried using an array to keep track of previous nodes visited and using that to determine the proper left and right threads, but just couldn't get it to work right. I need the constructor and setLeft/setRight functions in BSTNode class to correctly assign threads when applicable and set isLeft/RightThreaded accordingly, and then the printHelp and printInOrder functions of class BST to use whether the nodes are threaded to traverse the tree.
A few points:
- I want to avoid recursion in printInOrder and print if at all possible. I'm aiming for a while loop that covers the whole tree.
- I don't want to store an explicit parent node pointer anywhere.
- I don't want to use a stack structure or any list of nodes to help in the printInOrder function. I want that to rely only on the current node and the nodes to which it points.
Here is a minimal (I think) reproducible example of what I have for a non-threaded tree:
using namespace std;
#include <iostream>
#include <stack> // want to avoid needing this
#include <string>
template <typename E>
class BinNode {};
template <typename Key, typename E>
class BSTNode : public BinNode<E> {
public:
E it;
BSTNode* lp;
BSTNode* rp;
bool isLpChildPointer;
bool isRpChildPointer;
bool isLeftThreaded;
bool isRightThreaded;
Key k;
BSTNode() { lp = rp = NULL; }
BSTNode(Key K, E e, BSTNode* l, BSTNode* r) {
k = K;
it = e;
lp = l;
rp = r;
isLpChildPointer = false;
isRpChildPointer = false;
isLeftThreaded = true;
isRightThreaded = true;
}
void setLeft(BinNode<E>* b) {
lp = (BSTNode*)b;
isLpChildPointer = true;
isLeftThreaded = false;
}
void setRight(BinNode<E>* b) {
rp = (BSTNode*)b;
isRpChildPointer = true;
isRightThreaded = false;
}
};
template <typename Key, typename E>
class BST {
public:
BSTNode<Key, E>* root;
int nodecount;
BSTNode<Key, E>* inserthelp(BSTNode<Key, E>*, const Key&, const E&,
BSTNode<Key, E>*[], int, int);
void printhelp(BSTNode<Key, E>* root, int level) const {
if (root == NULL) return;
printhelp(root->lp, level + 1);
for (int i = 0; i < level; i++) cout << " ";
cout << root->k << "\n";
printhelp(root->rp, level + 1);
}
BST() {
root = NULL;
nodecount = 0;
}
void printInOrder() {
std::stack<BSTNode<Key, E>*> stack; // how to get rid of stack here and only use while // loop, using only lp and rp to access all nodes
BSTNode<Key, E>* current = root;
while (current != nullptr || !stack.empty()) {
while (current != nullptr) {
stack.push(current);
current = current->lp;
}
current = stack.top();
cout << current->it << endl;
stack.pop();
current = current->rp;
}
}
void insert(const Key& k, const E& e) {
root = inserthelp(k, e, root);
nodecount++;
}
BSTNode<Key, E>* inserthelp(const Key& k, const E& e, BSTNode<Key, E>* node) {
if (node == nullptr) {
return new BSTNode<Key, E>(k, e, NULL, NULL); // what to put here instead of NULL.
// and how to keep track of what higher level nodes this new node should thread to.
} else {
if (k < node->k) {
node->setLeft(inserthelp(k, e, node->lp));
} else {
node->setRight(inserthelp(k, e, node->rp));
}
return node;
}
}
void print() const { printhelp(root, 0); }
};
int main() {
BST<int, string> tree;
tree.insert(77, "seventy-seven");
tree.insert(70, "seventy");
tree.insert(75, "seventy-five");
tree.insert(66, "sixty-six");
// other inserts...
tree.insert(83, "eighty-three");
tree.insert(87, "eighty-seven");
tree.insert(65, "sixty-five");
tree.print();
tree.printInOrder();
}
Again, the above code works fine for a non-threaded tree - no problems whatsoever - does exactly what I want it to do. But I need it to work for a threaded tree. I worked on this issue for the better part of four or five hours earlier and then just couldn't look at it anymore.
#include <thread>. Nopthreads, noCreateThreadcalls, and I'm thinking, "What? Asker post the working, non-threaded version? That's dumb." Nope. Mesa the dummy.new/delete) - can help a lot.