Working version, with test code.

Limited to trees where node key values are unique.  Seems to have the
advantage of better access locality.  But I suspect the average time
per node is typically greater than for Morris Traversal.

typedef struct Node_
  {
    unsigned val;
    struct Node_ *left, *right;
  }
Node;

extern void visit(Node *);

Node * const Null = 0;

typedef enum { false, true } bool;

void traverse(Node *root)
  {
    Node *curr = root;
    Node *stack = Null;
    Node *temp;

    bool popped = false;

    for ( ; ; )
      {
        if (!popped)
          while (curr->left != Null)
            {
              /* Use left pointer to push current node onto
              ** linked list stack, and make left child
              ** current. */
              temp = stack;
              stack = curr;
              curr = stack->left;
              stack->left = temp;
            }
        else
          popped = false;

        visit(curr);

        if (curr->right == Null)
          {
            if (stack == Null)
              /* Traversal done. */
              break;

            while (curr->val > stack->val)
              {
                /* Pop top of stack and make it current,
                ** and restore right child pointer. */
                temp = curr;
                curr = stack;
                stack = stack->right;
                curr->right = temp;

                if (stack == Null)
                  /* Traversal done. */
                  break;
              }

            if (stack == Null)
              /* Traversal done. */
              break;

            /* Pop top of stack and make it current,
            ** and restore left child pointer. */
            temp = curr;
            curr = stack;
            stack = stack->left;
            curr->left = temp;

            popped = true;
          }
        else
          {
            /* Use right pointer to push current node onto
            ** linked list stack, and make right child
            ** current. */
            temp = stack;
            stack = curr;
            curr = stack->right;
            stack->right = temp;
          }
      }
  }

#define N 14

Node n[N];

Node *first(unsigned base, unsigned count)
  {
    unsigned i;

    if (count == 0)
      return(Null);

    n[base].left = Null;
    n[base].right = Null;

    for (i = 1; i < count; ++i)
      {
        n[base + i].left = n + base + i - 1;
        n[base + i].right = Null;
      }

    return(n + base + count - 1);
  }

void range(Node *sub, unsigned *base, unsigned *count)
  {
    if (sub == Null)
      *count = 0;
    else
      {
        Node *ll = sub, *rr = sub;

        while (ll->left != Null)
          ll = ll->left;

        while (rr->right != Null)
          rr = rr->right;

        *base = ll - n;
        *count = rr - ll + 1;
      }
  }

bool next(Node **sub)
  {
    if (*sub == Null)
      return(false);

    if (!next(&((*sub)->left)))
      {
        unsigned base, count;

        if (next(&((*sub)->right)))
          {
            range((*sub)->left, &base, &count);
            (*sub)->left = first(base, count);
          }
        else if ((*sub)->left == Null)
          return(false);
        else
          {
            unsigned r = *sub - n - 1;

            range(*sub, &base, &count);

            n[r].left = first(base, r - base);
            n[r].right = first(r + 1, count - (r - base) - 1);

            *sub = n + r;
          }
      }

    return(true);
  }

unsigned inc;

#include <stdio.h>
#include <stdlib.h>

void visit(Node *n)
  {
    if (n->val != inc)
      {
        printf("FAIL %u %u\n", n->val, inc);
        exit(1);
      }

    ++inc;
  }

void test(unsigned count)
  {
    unsigned tree_count = 0;

    Node *root = first(0, count);

    do
      {
        inc = 0;
        traverse(root);
        if (inc != count)
          {
            printf("FAIL2 %u %u\n", inc, count);
            exit(1);
          }
        ++tree_count;
      }
    while (next(&root));

    printf("TEST: nodes=%u trees=%u\n", count, tree_count);
  }

int main(void)
  {
    unsigned i;

    for (i = 0; i < N; ++i)
      n[i].val = i;

    test(1);
    test(2);
    test(3);
    test(N);

    printf("SUCCESS\n");
    return(0);
  }

-- 
You received this message because you are subscribed to the Google Groups 
"Algorithm Geeks" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to 
[email protected].
For more options, visit this group at 
http://groups.google.com/group/algogeeks?hl=en.

Reply via email to