Main Page | Modules | Alphabetical List | Data Structures | File List | Data Fields | Globals

rt_next.c

Go to the documentation of this file.
00001 /*
00002 ** Copyright (C) 2003 by Kevin L. Mitchell <klmitch@mit.edu>
00003 **
00004 ** This library is free software; you can redistribute it and/or
00005 ** modify it under the terms of the GNU Library General Public
00006 ** License as published by the Free Software Foundation; either
00007 ** version 2 of the License, or (at your option) any later version.
00008 **
00009 ** This library is distributed in the hope that it will be useful,
00010 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012 ** Library General Public License for more details.
00013 **
00014 ** You should have received a copy of the GNU Library General Public
00015 ** License along with this library; if not, write to the Free
00016 ** Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
00017 ** MA 02111-1307, USA
00018 **
00019 ** @(#)$Id: rt_next.c,v 1.2 2006/07/13 19:16:24 klmitch Exp $
00020 */
00028 #include "dbprim.h"
00029 #include "dbprim_int.h"
00030 
00031 RCSTAG("@(#)$Id: rt_next.c,v 1.2 2006/07/13 19:16:24 klmitch Exp $");
00032 
00033 unsigned long
00034 rt_next(rb_tree_t *tree, rb_node_t **node_io, unsigned long flags)
00035 {
00036   rb_node_t *node = 0;
00037 
00038   initialize_dbpr_error_table(); /* initialize error table */
00039 
00040   /* verify arguments */
00041   if (!rt_verify(tree) || !node_io ||
00042       ((node = *node_io) && !rn_verify(node)) || !(flags & RBT_ORDER_MASK))
00043     return DB_ERR_BADARGS;
00044 
00045   if (node && node->rn_tree != tree) /* node isn't in this tree */
00046     return DB_ERR_WRONGTABLE;
00047 
00048   if (!tree->rt_root) { /* empty tree? */
00049     *node_io = 0; /* clear the input node... */
00050     return 0;
00051   }
00052 
00053   switch (flags & (DB_FLAG_REVERSE | RBT_ORDER_MASK)) {
00054   case RBT_ORDER_PRE:
00055     if (!node) /* first node of preorder is the root node */
00056       node = tree->rt_root;
00057     else if (node->rn_left) /* go to the left subtree... */
00058       node = node->rn_left;
00059     else if (node->rn_right) /* go to the right subtree... */
00060       node = node->rn_right;
00061     else if (!node->rn_parent) /* node has no parent? */
00062       node = 0;
00063     else if (rn_isleft(node) && node->rn_parent->rn_right)
00064       node = node->rn_parent->rn_right; /* return sibling node to right */
00065     else { /* OK, must locate the next node */
00066       for (node = node->rn_parent;
00067            node->rn_parent && (rn_isright(node) || !node->rn_parent->rn_right);
00068            node = node->rn_parent)
00069         ; /* empty loop */
00070 
00071       if (!node->rn_parent)
00072         node = 0; /* hit the top of the tree, no next node */
00073       else
00074         node = node->rn_parent->rn_right; /* return the sibling node */
00075     }
00076     break;
00077   case (DB_FLAG_REVERSE | RBT_ORDER_POST):
00078     if (!node) /* first node of reverse postorder is the root node */
00079       node = tree->rt_root;
00080     else if (node->rn_right) /* go to the right subtree... */
00081       node = node->rn_right;
00082     else if (node->rn_left) /* go to the left subtree... */
00083       node = node->rn_left;
00084     else if (!node->rn_parent) /* node has no parent? */
00085       node = 0;
00086     else if (rn_isright(node) && node->rn_parent->rn_left)
00087       node = node->rn_parent->rn_left; /* return sibling node to left */
00088     else { /* OK, must locate the next node */
00089       for (node = node->rn_parent;
00090            node->rn_parent && (rn_isleft(node) || !node->rn_parent->rn_left);
00091            node = node->rn_parent)
00092         ; /* empty loop */
00093 
00094       if (!node->rn_parent)
00095         node = 0; /* hit the top of the tree, no next node */
00096       else
00097         node = node->rn_parent->rn_left; /* return the sibling node */
00098     }
00099     break;
00100 
00101   case RBT_ORDER_IN:
00102     if (!node) /* first node of inorder is the left-most node */
00103       for (node = tree->rt_root; node->rn_left; node = node->rn_left)
00104         ; /* empty loop */
00105     else if (node->rn_right) /* go to left-most node of right subtree */
00106       for (node = node->rn_right; node->rn_left; node = node->rn_left)
00107         ; /* empty loop */
00108     else if (!node->rn_parent) /* node has no parent? */
00109       node = 0;
00110     else if (rn_isleft(node)) /* is it a left node? */
00111       node = node->rn_parent; /* go up, then */
00112     else { /* OK, must find the next node */
00113       for (node = node->rn_parent; node->rn_parent && rn_isright(node);
00114            node = node->rn_parent)
00115         ; /* empty loop */
00116       if (!node->rn_parent)
00117         node = 0; /* hit the top of the tree, no next node */
00118       else
00119         node = node->rn_parent; /* return the node's parent */
00120     }
00121     break;
00122   case (DB_FLAG_REVERSE | RBT_ORDER_IN):
00123     if (!node) /* first node of reverse inorder is the right-most node */
00124       for (node = tree->rt_root; node->rn_right; node = node->rn_right)
00125         ; /* empty loop */
00126     else if (node->rn_left) /* go to right-most node of left subtree */
00127       for (node = node->rn_left; node->rn_right; node = node->rn_right)
00128         ; /* empty loop */
00129     else if (!node->rn_parent) /* node has no parent? */
00130       node = 0;
00131     else if (rn_isright(node)) /* is it a right node? */
00132       node = node->rn_parent; /* go up, then */
00133     else { /* OK, must find the next node */
00134       for (node = node->rn_parent; node->rn_parent && rn_isleft(node);
00135            node = node->rn_parent)
00136         ; /* empty loop */
00137       if (!node->rn_parent)
00138         node = 0; /* hit the top of the tree, no next node */
00139       else
00140         node = node->rn_parent; /* return the node's parent */
00141     }
00142     break;
00143 
00144   case RBT_ORDER_POST:
00145     if (!node) /* first node of postorder is bottom-most node */
00146       for (node = tree->rt_root; node->rn_left || node->rn_right;
00147            node = node->rn_left ? node->rn_left : node->rn_right)
00148         ; /* empty loop */
00149     else if (!node->rn_parent) /* node has no parent? */
00150       node = 0;
00151     else if (rn_isleft(node) && node->rn_parent->rn_right) /* go right! */
00152       for (node = node->rn_parent->rn_right; node->rn_left || node->rn_right;
00153            node = node->rn_left ? node->rn_left : node->rn_right)
00154         ; /* empty loop */
00155     else
00156       node = node->rn_parent; /* go up to the node's parent */
00157     break;
00158   case (DB_FLAG_REVERSE | RBT_ORDER_PRE):
00159     if (!node) /* first node of reverse preorder is bottom-most node */
00160       for (node = tree->rt_root; node->rn_right || node->rn_left;
00161            node = node->rn_right ? node->rn_right : node->rn_left)
00162         ; /* empty loop */
00163     else if (!node->rn_parent) /* node has no parent? */
00164       node = 0;
00165     else if (rn_isright(node) && node->rn_parent->rn_left) /* go left! */
00166       for (node = node->rn_parent->rn_left; node->rn_right || node->rn_left;
00167            node = node->rn_right ? node->rn_right : node->rn_left)
00168         ; /* empty loop */
00169     else
00170       node = node->rn_parent; /* go up to the node's parent */
00171     break;
00172   }
00173 
00174   *node_io = node; /* return the next node... */
00175 
00176   return 0;
00177 }

Generated on Sat Jul 15 14:10:33 2006 for DatabasePrimitivesLibrary by  doxygen 1.4.4