C++ Remove last comma when printing AVL tree elements - c++

I know similar questions have been asked but I can't seem to find an answer for printing via a recursively called function. I am trying to print preorder, postorder, and inorder traversals of an AVL tree and have implemented the functions recursively.
i.e.
void inOrder(Node* root)
{
if(root != nullptr) {
inOrder(root->left);
cout << root->data << ", ";
inOrder(root->right);
}
}
The data should print comma-separated except for the last value, but I am not sure how to do so. I've done research but can't find anything that seems to apply when traversing an AVL tree recursively. Is this possible or should I implement the functions without recursion?

The pattern I usually use for this sort of thing is to use a separator pointer that I change in the loop. The first iteration it's "", so prints nothing, and every subsequent iteration prints the separator. For your recursive case it would be passed as a parameter, and look like this:
void inOrder(Node* root, char ** sep)
{
if(root != nullptr) {
inOrder(root->left, sep);
cout << **sep << root->data;
*sep = ", ";
inOrder(root->right, sep);
}
}
Call it like:
char * sep = "";
inOrder(root, &sep);
It looks a lot nicer for loops. The main advantage is there is no if/else branch in every loop, just a fast pointer assignment to update the separator.

Make an internal implementation function that maintains a flag that indicates whether the data item to be output is the first one. Then prepend the output with a comma for all items but the first.
void inOrderImpl(Node* root, bool& first)
{
if(root != nullptr) {
inOrderImpl(root->left, first);
if (first)
first = false;
else
cout << ", ";
cout << root->data;
inOrderImpl(root->right, first);
}
}
void inOrder(Node* root)
{
bool first = true;
inOrderImpl(root, first);
}

As my comment suggested, an ambitious (and better) way to write the code to do any of the BST traversals would be to use a more generic approach:
template <typename Fn>
void inOrder(Node* root, Fn& func)
{
if(root != nullptr)
{
inOrder(root->left, func);
func(root);
inOrder(root->right, func);
}
}
So given the above, you can basically do anything, since func will be called using the current value of root.
So how does this help us? Consider now the following:
struct TreePrinter
{
bool initial = true;
void operator()(Node *root)
{
if ( initial )
initial = false;
else
std::cout << ",";
std::cout << root->data;
}
};
The above is a class that has overriden operator(). This allows us to pass this to the traversal function, and the traversal function simply calls it.
Note that the initial is a state that gets set in the TreePrinter object.
Then this is how it's implemented:
TreePrinter tp;
Node root;
//...
inOrder(&root, tp);
Here is a live example using a dummy BST.
So not only can you just print a comma, any callable object (function pointer, function object, lambda, etc.) can be provided that can basically use the passed in root to do whatever needs to be done.

Related

push_back() is not adding element to the vector? (C++ Tree Traversal)

I'm working through a tree traversal problem and using 'push_back' vector function to update a vector with the in-order traversal. Alongside using this I am using cout to print out the solution to debug. The print output is correct but my returning vector doesn't match the print so I can only put this down to me not understanding how the push_back function works.
This is the function I am using:
vector<int> inorderTraversal(TreeNode* root) {
vector<int> order {};
if (root != nullptr) {
inorderTraversal(root->left);
cout << "pushing back : " << root->val << std::endl;
order.push_back(root->val);
inorderTraversal(root->right);
}
return order;
}
For the input tree [1,null,2,3] My stdout is printing:
pushing back : 1
pushing back : 3
pushing back : 2
Which is correct but my returning array (order) is only [1].
You're ignoring the results from each recursion. You should be doing this:
vector<int> inorderTraversal(TreeNode *root)
{
vector<int> order;
if (root != nullptr)
{
order = inorderTraversal(root->left);
cout << "pushing back : " << root->val << std::endl;
order.push_back(root->val);
auto tmp = inorderTraversal(root->right);
order.insert(order.end(), tmp.begin(), tmp.end());
}
return order;
}
Much More Efficient
That said, if you counted the number of local vectors created in this, though short, they will be many (as many as there are nodes in your tree, in fact). You can eliminate all of those middle-men vectors by providing a shim between the actual traversal and the creation of the order vector:
void inorderTraversal_v(TreeNode const *root, std::vector<int>& order)
{
if (root != nullptr)
{
inorderTraversal(root->left, order);
order.push_back(root->val);
inorderTraversal(root->right, order);
}
return order;
}
std::vector<int> inorderTraversal(TreeNode const *root)
{
std::vector<int> order;
inorderTraversal_v(root, order);
return order;
}
Doing this creates a single vector, and in so doing eliminates (N-1) temporary vectors along the way, where N is the number of nodes in the tree.

How to do InOrder traversal with B-Tree?

struct BTreeNode {
bool is_leaf=true;
std::vector<int> elements;
std::vector<BTreeNode*> children;
BTreeNode() {}
BTreeNode (std::vector<int> v) {
this->elements = v;
}
};
void traverse(BTreeNode* root) {
for(int i = 0; i < (int)root->children.size(); ++i){
traverse(root->children[i]);
cout << root->elements[i] << endl;
}
traverse(root->children[root->children.size() -1]);
}
My method somehow segfaults. How do we write a correct inOrder Traversal for B-Tree?
It's probably the last traverse call when you are at a leaf. I don't think that this traverse is needed.
Assuming BTreeNode is a generic definition of your b-tree node, whereas T1 is the type of the keys and T2 is the type of the values in the tree, and sortedKeys is the list you are after, you can use the following recursive method. The idea is very similar to an inOrder traversal in binary search tree, first visit the left-most child, then visit the key- then continue, Since the number of children in B-tree is always one bigger than the number of keys, a check is needed before visiting the key [code is in c#, but can easily be converted to any other language, the purpose is to show the algorithm only].
public void InOrderTraversal(BTreeNode<T1, T2> node, List<KeyValuePair<T1, T2>> sortedKeys)
{
if (node != null)
{
for (int i = 0; i < node.Children.Count; i++)
{
InOrderTraversal(node.Children[i], sortedKeys);
if (i < node.KeyValues.Count)
sortedKeys.Add(node.KeyValues[i]);
}
}
}

Applying Greater than or Less than Checks to both Strings and Primitive Data Types?

I'm working on a project which requires that I create a template class for an Accumulator which returns weather or not the list passed to it is in order. The order is ascending.
I am probably overthinking the problem but I cannot seem to figure out how to do a greater than/ less than check on both primitive data types and strings. I'll clarify:
The process goes like this:
A list/vector is declared and stuff is stored in it.
Then a secondary Accumulator called apply is called.
This Accumulator(apply) iterates through the list calling the .put() method of the InOrder Accumulator on every value in the list. The values could be of type double, long, short, etc or string.
I have tried setting an arbitrary lower bound, setting it equal to the first element in the list and then doing checks based on that start point but this offers mixed results because it does not work on the strings.
I was thinking of checking typeid or something so that for strings I could then call the .size() method and compare that way. Were as for primitives I would simply use the > or < operator. But that would defeat the point of the template function. Any help would be greatly appreciated.
I'll post the Code were the function is called, the code for the Apply Accumulator, and my Code for InOrder. Let me know if anything else is required.
My InOrder:
template<typename T>
class InOrder
{
public:
InOrder(){}
~InOrder(){}
void put(T item)
{
_count++;
if(_count == 1)
{
_lowbound = item;
}
if(_count!=0 && _count!=1 && item<_lowbound)
{
_order = false;
}
if(_count!=0 && _count!=1 && item>_lowbound)
{
_order = true;
}
_count++;
}
bool get()
{
return _order;
}
private:
T _lowbound;
int _count = 0;
bool _order;
};
Apply Accumulator:
template<typename A, typename I>
void apply(A & anAccumulator, I begin, I end)
{
for (I iter = begin; iter != end; ++iter)
{
anAccumulator.put( *iter);
}
}
Code where InOrder is Called:
{
// Read a list of doubles into a List and check their order
cout << "apply InOrder to a List of doubles\n";
double sentinel = -1.23;
List<double> dList;
fillList(sentinel, dList);
InOrder<double> dblInOrder;
apply(dblInOrder, begin(dList), end(dList));
cout << "The doubles in dList are ";
if (!dblInOrder.get())
cout << "NOT ";
cout << "in order\n\n";
}
{
// Read a list of strings into a List and check their order
cout << "apply InOrder to a List of strings\n";
string strSent = "end";
List<string> sList;
fillList(strSent, sList);
InOrder<string> strInOrder;
apply(strInOrder, begin(sList), end(sList));
cout << "The strings in sList are ";
if (!strInOrder.get())
cout << "NOT ";
cout << "in order\n\n";
}
I should note that the the items put into the list are processed in the reverse order.
Eg: if I type my list in as [a,b,c] or [1,2,3] the first value/string to be processed will be c/3 and then so on for there to b/2 and a,1
Your mistake is that you do not stop when you detect that order is wrong:
_order = false; // here is you have to stop and skip all other items
This won't work:
if(_count!=0 && _count!=1 && item<_lowbound)
{
_order = false;
}
if(_count!=0 && _count!=1 && item>_lowbound)
{
_order = true;
}
because should be:
if(_count!=0 && _count!=1 && item<_lowbound)
{
_order = false;
}
Delete the second part, and add:
InOrder() : _order(true) {}
To your constructor.

list stays empty even after inserting an element C++

I am trying to insert pointers into a list but every time I try to print the list, or check whats in the list it says its empty. This means that my insertion is incorrect, but I don't understand why, my following classes are:
namespace {
template <typename T>
pair < node<T>*, bool> addElement (const T& elem, btree<T>* bt) {
class list < node<T>* >::iterator itr = bt->level().begin();
if (bt->level().empty()) {
node <T>*n = new node<T>(elem, bt->max());
cout << n->getItem() << endl;
bt->addElem(itr, n);
return make_pair(n, true);
}
for (; itr != bt->level().end(); ++itr) {
if (elem < (*itr)->getItem()) {
node <T>* n = new node<T> (elem, bt->max());
(*itr)->previous()->addNext(n);
n->addPrev((*itr)->previous());
n->addNext(*itr);
(*itr)->addPrev(n);
bt->addElem(itr, n);
return make_pair(n, true);
} else if (elem == (*itr)->getItem()) return make_pair(*itr, false);
}
// other stuff + return statement
}
addElem does the following:
void addElem (std::_List_iterator<node<T>*>& itr, node <T>* n) {
neighbours.insert(itr, n);
if (neighbours.empty()) cout << "wa?";
}
where btree class consists of:
size_t maxNodeElems;
list < node<T>*> neighbours;
the other things like addPrev() and previous() are just getters and setters. Anyways, I ran a test file on it that pretty much constructs a btree, and calls an insert function which directly calls this addElement function. But whenever I try to print the list inside the btree, it says its empty and seg faults. I don't understand why it's not storing.
Any help would be appreciated!
NOTE: the "Wa?" keeps printing
It seems you are trying to keep a sorted list, that's why you have:
// find the place to insert elem
for (; itr != bt->level().end(); ++itr) {
if (elem < (*itr)->getItem()) {
// insert...
}
}
But if the list is empty (initial state), itr will be probably equal bt->level().end() in the first place, so you will never insert anything...
You also should consider the case when you are trying to insert element for which (elem < (*itr)->getItem()) is always false (the new greatest element in the list). You need to handle that case as well.

How is this recursive function automatically converted into iterative function?

I am reading on tail recursion as below
Tail recursion refers to a recursive call at the last line. Tail
recursion can be mechanically eliminated by enclosing the body in a
while loop and replacing the recursive call with one assignment per
function argument.
For example
void print(Iterator start, Iterator end, ostream& out=cout) {
if(start == end)
return;
out << *start++ << endl;
print(start, end, out);
}
is converted to iterative by above specification as
void print(Iterator start, Iterator end, ostream& out=cout) {
while(true) {
if(start == end)
return;
out << *start++ << endl;
}
}
In above passage it is mentioned that "replacing recursive call with one assignment per function argument, but in given example we didn't have any assignment?
Can any one explain and provide example for above explanation about how to translate recursive to iterative function?
The assignment is hidden in the increment operator:
start++;
is in fact an assignment:
start = start+1;
Actually, the example (part one) is not very good.
out << *start++ << endl;
print(start, end, out);
should be
out << *start << endl;
print( start+1, end, out);
I don't think, whatever passage you are referring is important; just focus on the main problem, where you want to convert a recursive function to a normal iterative function, which can be done (effortlessly) as,
void print(Iterator start, Iterator end, ostream& out=cout) {
while(start != end) {
out << *start++ << endl;
}
}
It is hidden a little in C++, but start++ is assigning a new value to each time in the loop.
What they are talking about is, that you assign the arguments of the tail function call to the parameter variables of this function invocation, but in this case it is not neccessary, as you are calling the function with the exact same arguments (because like others said, the change to the first argument start happened before the function call).
Actually, if done precisely, the iterative function should look like
void print(Iterator start, Iterator end, ostream& out=cout) {
while(true) {
if(start == end)
return;
out << *start++ << endl;
start = start;
end = end;
out = out;
}
}
But these assignments are completely unneccessary, even if conpectually correct.
The general conversion of recursive to iterative would look like this.
Original code:
void print(Iterator start, Iterator end, ostream& out=cout) {
if(start == end)
return;
out << *start++ << endl;
print(start, end, out);
}
Converted code:
void print(Iterator start, Iterator end, ostream& out=cout) {
while(true) {
if(start == end)
return;
out << *start << endl;
// One assignment per function argument for 'general' tail recursion
start = start + 1; // (1)
end = end; // (2)
out = out; // (3)
}
}
The three assignments as in the explanation are included. Assignment (1) is embedded in the start++, assignments (2) and (3) are optimized away.