May as well show the beast I came up with. Not as clever as Morris. Uses a stack. I put both algorithms below, added a tree-displaying algorithm and random tree generation. Give a number at the command line to get a random tree of that size (start with 20). 0 or no number uses a 15-node balanced tree.
The tree is printed sideways, like this:
Code:
.---97
: '---95
: '---83
.---83
: '---81
: '---80
: '---78
.---76
+---75
: .---73
: .---67
: : : .---65
: : '---58
: : '---55
'---54
: .---52
: .---50
: .---46
: : : .---44
: : : : '---42
: : '---41
: : : .---38
: : '---29
: .---22
: : : .---20
: : '---14
'---12
: .---6
: : '---4
'---1
Code:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define MAX_STACK_SIZE 100 // for Iterator stack
#define MAX_PATH_DEPTH 100 // for printTreeStructure
typedef struct BTNODE_ {
int data;
struct BTNODE_ *left, *right;
} BTNODE;
typedef struct Iterator {
int top;
BTNODE *st[MAX_STACK_SIZE];
} Iterator;
BTNODE* MorrisTraversal (BTNODE *cur);
BTNODE* UT5000First (BTNODE *t, Iterator *it);
BTNODE* UT5000Next (Iterator *it);
BTNODE* newbtNode (int data);
void insert (BTNODE **pt, int data);
void printTree (BTNODE *t);
void err (const char *msg);
int main(int argc, char **argv) {
int size = 0;
if (argc > 1) {
size = atoi(argv[1]);
if (size < 0) size = 0;
}
BTNODE *root = NULL;
if (size > 0) {
srand(time(NULL));
for (int i = 0; i < size; i++)
insert(&root, rand() % 100);
}
else {
int a[] = {8,4,2,1,3,6,5,7,12,10,9,11,14,13,15};
for (size_t i = 0; i < sizeof a / sizeof *a; i++)
insert(&root, a[i]);
}
printTree(root);
for(BTNODE *cur = root; cur; cur = cur->right){
cur = MorrisTraversal(cur);
printf("%2d ", cur->data);
}
printf("\n");
Iterator it;
BTNODE *nd = UT5000First(root, &it);
while (nd) {
printf("%2d ", nd->data);
nd = UT5000Next(&it);
}
printf("\n");
return 0;
}
void err(const char *msg) {
fprintf(stderr, "Error: %s\n", msg);
exit(EXIT_FAILURE);
}
BTNODE* newbtNode(int data) {
BTNODE* btNode = malloc(sizeof *btNode);
btNode->left = btNode->right = NULL;
btNode->data = data;
return btNode;
}
void insert(BTNODE **pt, int data) {
for (BTNODE *t; (t = *pt) != NULL; )
pt = data < t->data ? &t->left : &t->right;
*pt = newbtNode(data);
}
void printTree(BTNODE *t) {
static int depth = 0;
static char path[MAX_PATH_DEPTH];
if (!t) return;
if (t->right) {
if (depth == MAX_PATH_DEPTH) err("MAX_PATH_DEPTH");
path[depth++] = 1;
printTree(t->right);
--depth;
}
for (int i = 0; i < depth; i++)
printf("%c ", i == 0 || path[i] == path[i - 1] ? ' ' : ':');
printf("%c---%d\n",
depth == 0 ? '+' : path[depth-1] ? '.' : '\'', t->data);
if (t->left) {
if (depth == MAX_PATH_DEPTH) err("MAX_PATH_DEPTH");
path[depth++] = 0;
printTree(t->left);
--depth;
}
}
//// MorrisTraversal //////////////////////////////////
BTNODE *MorrisTraversal(BTNODE *cur) {
while (cur && cur->left){
BTNODE *pre = cur->left;
while (pre->right && pre->right != cur)
pre = pre->right;
if (!pre->right) {
pre->right = cur;
cur = cur->left;
} else {
pre->right = NULL;
return cur;
}
}
return cur;
}
//// UltraTraverse5000 ////////////////////////////////
BTNODE *UT5000First(BTNODE *t, Iterator *it) {
if (!t) return NULL;
it->top = 0;
for ( ; t->left; t = t->left) it->st[it->top++] = t;
return it->st[it->top] = t;
}
BTNODE *UT5000Next(Iterator *it) {
BTNODE *t = it->st[it->top];
if (!(t = t->right) && it->top)
t = it->st[--it->top];
else
for ( ; t && t->left; t = t->left)
it->st[it->top++] = t;
return it->st[it->top] = t;
}