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 }