bad bug in tree class fixed, working on mac
[feisty_meow.git] / nucleus / library / nodes / tree.cpp
index a087b0b74edaeb032771f1b725eb80d3a4e000bb..2a88061cada797e432fc2108d0c4874395db22e7 100644 (file)
@@ -50,7 +50,7 @@ bool tree::iterator::next_node(tree *&to_return)
 #ifdef DEBUG_TREE
   FUNCDEF("next_node");
 #endif
-  to_return = NIL;
+  to_return = NULL_POINTER;
 #ifdef DEBUG_TREE
   if ( (_order != to_branches)
       && (_order != reverse_branches) ) {
@@ -255,7 +255,7 @@ tree *tree::iterator::next()
 #ifdef DEBUG_TREE
   FUNCDEF("next");
 #endif
-  tree *to_return = NIL;
+  tree *to_return = NULL_POINTER;
   bool found_tree = false;
   while (!found_tree) {
     bool still_running = next_node(to_return);
@@ -270,7 +270,7 @@ tree *tree::iterator::next()
 
 tree::tree()
 : node(1)
-{ set_link(BACKWARDS_BRANCH, NIL); }
+{ set_link(BACKWARDS_BRANCH, NULL_POINTER); }
 
 tree::~tree()
 {
@@ -278,10 +278,61 @@ tree::~tree()
   // cousin.
   tree *my_parent = parent();
   if (my_parent) my_parent->prune(this);
+  my_parent = NULL_POINTER;  // disavow since we are loose now.
+
+#if 0
+
+  //original version suffers from being too recursive on windoze,
+  //which blows out the stack.  linux never showed this problem.  so, i
+  //guess i'm glad i tested on windows.
+  //anyway, it's a general problem for a degenerate tree like the one
+  //i've constructed.  current version has ~40000 direct descendants of
+  //the root in a single line, so the stack has to support 40000 frames
+  //for the delete implementation below to work.
 
   // iterate over the child nodes and whack each individually.
   while (branches()) delete branch(0);
     // this relies on the child getting out of our branch list.
+#else
+
+  // newer version of delete doesn't recurse; it just iterates instead,
+  // which avoids the massive recursive depth of the original approach.
+  tree *curr_node = this;
+  while (curr_node != NULL_POINTER) {
+    // make a breadcrumb for getting back to 'here' in the tree.
+    tree *way_back = curr_node;
+    // our main operation here is to go down a node without using any
+    // stack frames.  so we just pick the first kid; it's either valid
+    // or there are no kids at all.
+    curr_node = curr_node->branch(0);
+
+    if (curr_node == NULL_POINTER) {
+      // wayback has no children, so we can take action.
+
+      // if wayback is the same as "this", then we exit from iterations since
+      // we've cleaned all the kids out.
+      if (way_back == this) {
+        break;
+      }
+
+      // we want to whack the wayback node at this point, since it's a parent
+      // with no kids, i.e. a leaf.  we've guaranteed we're not going beyond
+      // our remit, since wayback is not the same node as the top level one
+      // in the destructor (as long as there are no cycles in the tree...).
+      curr_node = way_back->parent();  // go up in tree on next iteration.
+      delete way_back;  // whack a node, finally.
+
+    } else {
+      // okay, there's a node below here.  we will spider down to it.
+      continue;
+    }
+
+
+  }
+
+#endif
+
+
 }
 
 tree *tree::parent() const { return (tree *)get_link(BACKWARDS_BRANCH); }
@@ -291,7 +342,7 @@ int tree::branches() const { return links() - 1; }
 tree *tree::branch(int branch_number) const
 {
   branch_number++;
-  bounds_return(branch_number, 1, branches(), NIL);
+  bounds_return(branch_number, 1, branches(), NULL_POINTER);
   return (tree *)get_link(branch_number);
 }
 
@@ -301,8 +352,8 @@ int tree::which(tree *branch_to_find) const
 tree *tree::root() const
 {
   const tree *traveler = this;
-  // keep looking at the backwards branch until it is a NIL.  the tree with
-  // a NIL BACKWARDS_BRANCH is the root.  return that tree.
+  // keep looking at the backwards branch until it is a NULL_POINTER.  the tree with
+  // a NULL_POINTER BACKWARDS_BRANCH is the root.  return that tree.
   while (traveler->get_link(BACKWARDS_BRANCH))
     traveler = (tree *)traveler->get_link(BACKWARDS_BRANCH);
   return const_cast<tree *>(traveler);
@@ -318,7 +369,7 @@ void tree::attach(tree *new_branch)
 void tree::insert(int branch_place, tree *new_branch)
 {
   branch_place++;
-  insert_link(links(), NIL);
+  insert_link(links(), NULL_POINTER);
   if (branch_place >= links())
     branch_place = links() - 1;
   for (int i = links() - 1; i > branch_place; i--)
@@ -339,7 +390,7 @@ outcome tree::prune_index(int branch_to_cut)
   branch_to_cut++;
   bounds_return(branch_to_cut, 1, branches(), basis::common::NOT_FOUND);
   tree *that_branch = (tree *)get_link(branch_to_cut);
-  that_branch->set_link(BACKWARDS_BRANCH, NIL);
+  that_branch->set_link(BACKWARDS_BRANCH, NULL_POINTER);
   zap_link(branch_to_cut);
   return basis::common::OKAY;
 }
@@ -364,7 +415,7 @@ if (to_follow.size()) {}
 /*
   tree *traveller = this;
   path to_accumulate(root());
-  while (traveller->parent() != NIL) {
+  while (traveller->parent() != NULL_POINTER) {
 //    int branch_number = traveller->parent()->which(traveller);
 //    if (branch_number == BRANCH_NOT_FOUND) non_continuable_error
 //      (class_name(), "generate_path", "branch not found during path construction");