class treenode {Run with this input, using "." to represent empty tree links:
public:
std::string data;
treenode *left;
treenode *right;
treenode(std::string v,treenode *l,treenode *r) {data=v; left=l; right=r;}
};
void print(treenode *cur,int level=0)
{
if (cur==0) { return; } // base case
for (int indent=0;indent<level;indent++) cout<<" ";
cout<<cur->data<<"\n";
print(cur->left,level+1);
print(cur->right,level+1);
}
treenode *make_tree(void) {
std::string x;
if (cin>>x && x!=".") {
treenode *left=make_tree();
treenode *right=make_tree();
return new treenode(x,left,right);
}
else { return NULL; }
}
int foo(void) {
treenode *cur=make_tree();
print(cur);
return 0;
}
bigglesI get this output:
marketing
chmoozy . .
haargei intern . . .
engineering
olgei . marty . .
cousins . .
bigglesThis is a "preorder" tree traversal. Changing the print function to print the current tree node after the children gives a "postorder" traversal:
marketing
chmoozy
haargei
intern
engineering
olgei
marty
cousins
Program complete. Return 0 (0x0)
void print(treenode *cur,int level=0)And the corresponding postorder output is:
{
if (cur==0) { return; } // base case
print(cur->left,level+1);
print(cur->right,level+1);
for (int indent=0;indent<level;indent++) cout<<" ";
cout<<cur->data<<"\n";
}
chmoozyFor an "inorder" traversal, I print one child, then myself, then the other child:
intern
haargei
marketing
marty
olgei
cousins
engineering
biggles
Program complete. Return 0 (0x0)
void print(treenode *cur,int level=0)
{
if (cur==0) { return; } // base case
print(cur->left,level+1);
for (int indent=0;indent<level;indent++) cout<<" ";
cout<<cur->data<<"\n";
print(cur->right,level+1);
}
chmoozyNote that all these functions are purely recursive.
marketing
intern
haargei
biggles
olgei
marty
engineering
cousins
Program complete. Return 0 (0x0)
#include <stack>
void print(treenode *cur)
{
std::stack<treenode *> s;
s.push(cur);
while (s.size()>0) {
treenode *cur=s.top(); s.pop();
if (cur==0) continue;
cout<<cur->data<<"\n";
s.push(cur->right);
s.push(cur->left); // subtle: push left last, so it'll pop first!
}
}
Changing this to inorder or postorder is harder than it looks--see below.
#include <deque>The breadth-first order is:
void print(treenode *cur,int level=0)
{
std::deque<treenode *> s;
s.push_front(cur);
while (s.size()>0) {
treenode *cur=s.back(); s.pop_back();
if (cur==0) continue;
cout<<cur->data<<"\n";
s.push_front(cur->right);
s.push_front(cur->left); // subtle: push left last, so it'll pop first!
}
}
biggles
engineering
marketing
cousins
olgei
haargei
chmoozy
marty
intern
Program complete. Return 0 (0x0)
#include <stack>This is annoyingly tricky, but you can replace *any* recursive function with a series of manual stack manipulations and state checks. Note how the separate phases in the original inorder traversal are now just cases for a switch statement (works like a series of nested "if" blocks). This switch-on-what-to-do-next trick is one way to write coroutines in C++.
class node_and_phase {
public:
treenode *cur; // where we're at in the tree
int phase; // which stage we're at traversing cur
node_and_phase(treenode *c,int p) :cur(c), phase(p) {}
};
void print(treenode *root)
{
std::stack<node_and_phase> s;
s.push(node_and_phase(root,0));
while (s.size()>0) {
node_and_phase &n=s.top();
if (n.cur==0) { s.pop(); }
else
switch (n.phase++) {
case 0: s.push(node_and_phase(n.cur->left,0)); break;
case 1: cout<<n.cur->data<<"\n"; break;
case 2: s.push(node_and_phase(n.cur->right,0)); break;
case 3: s.pop(); break; // <- like "return"!
};
}
}