www.delorie.com/gnu/docs/avl/libavl_239.html   search  
 
Buy GNU books!


GNU libavl 2.0.1

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

14.6 Copying

To copy BSTs with parent pointers, we use a simple adaptation of our original algorithm for copying BSTs, as implemented in &#60;@xref{\NODE\, , \TITLE\}.&#62;{BST copy function,83}. That function used a stack to keep track of the nodes that need to be revisited to have their right subtrees copies. We can eliminate that by using the parent pointers. Instead of popping a pair of nodes off the stack, we ascend the tree until we moved up to the left:

 
&#60;@xref{\NODE\, , PBST copy error helper function.&#62;,510}
struct pbst_table *
pbst_copy (const struct pbst_table *org, pbst_copy_func *copy, pbst_item_func *destroy, struct libavl_allocator *allocator)
{ struct pbst_table *new; const struct pbst_node *x; struct pbst_node *y; assert (org != NULL); new = pbst_create (org-&#62;pbst_compare, org-&#62;pbst_param, allocator != NULL ? allocator : org-&#62;pbst_alloc); if (new == NULL) return NULL; new-&#62;pbst_count = org-&#62;pbst_count; if (new-&#62;pbst_count == 0) return new; x = (const struct pbst_node *) &org-&#62;pbst_root; y = (struct pbst_node *) &new-&#62;pbst_root; for (;;)
{ while (x-&#62;pbst_link[0] != NULL)
{ y-&#62;pbst_link[0] =
new-&#62;pbst_alloc-&#62;libavl_malloc (new-&#62;pbst_alloc, sizeof *y-&#62;pbst_link[0]); if (y-&#62;pbst_link[0] == NULL)
{ if (y != (struct pbst_node *) &new-&#62;pbst_root)
{ y-&#62;pbst_data = NULL; y-&#62;pbst_link[1] = NULL; } copy_error_recovery (y, new, destroy); return NULL; } y-&#62;pbst_link[0]-&#62;pbst_parent = y; x = x-&#62;pbst_link[0]; y = y-&#62;pbst_link[0]; } y-&#62;pbst_link[0] = NULL; for (;;)
{ if (copy == NULL) y-&#62;pbst_data = x-&#62;pbst_data; else
{ y-&#62;pbst_data = copy (x-&#62;pbst_data, org-&#62;pbst_param); if (y-&#62;pbst_data == NULL)
{ y-&#62;pbst_link[1] = NULL; copy_error_recovery (y, new, destroy); return NULL; } } if (x-&#62;pbst_link[1] != NULL)
{ y-&#62;pbst_link[1] =
new-&#62;pbst_alloc-&#62;libavl_malloc (new-&#62;pbst_alloc, sizeof *y-&#62;pbst_link[1]); if (y-&#62;pbst_link[1] == NULL)
{ copy_error_recovery (y, new, destroy); return NULL; } y-&#62;pbst_link[1]-&#62;pbst_parent = y; x = x-&#62;pbst_link[1]; y = y-&#62;pbst_link[1]; break; } else
y-&#62;pbst_link[1] = NULL; for (;;)
{ const struct pbst_node *w = x; x = x-&#62;pbst_parent; if (x == NULL)
{ new-&#62;pbst_root-&#62;pbst_parent = NULL; return new; } y = y-&#62;pbst_parent; if (w == x-&#62;pbst_link[0]) break; } } } }
This code is included in @refalso{489

Recovering from an error changes in the same way. We ascend from the node where we were copying when memory ran out and set the right children of the nodes where we ascended to the right to null pointers, then destroy the fixed-up tree:

 
static void 
copy_error_recovery (struct pbst_node *q, struct pbst_table *new, pbst_item_func *destroy)
{ assert (q != NULL && new != NULL); for (;;)
{ struct pbst_node *p = q; q = q-&#62;pbst_parent; if (q == NULL) break; if (p == q-&#62;pbst_link[0]) q-&#62;pbst_link[1] = NULL; } pbst_destroy (new, destroy); }
This code is included in @refalso{509


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

  webmaster   donations   bookstore     delorie software   privacy  
  Copyright 2003   by The Free Software Foundation     Updated Jun 2003