00001 #ifndef TREE_IMPLEMENTATION_FILE
00002 #define TREE_IMPLEMENTATION_FILE
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include "tree.h"
00019
00020 #include <basis/function.h>
00021 #include <basis/guards.h>
00022 #include <basis/log_base.h>
00023
00024
00025
00026
00027 #undef LOG
00028 #define LOG(s) CLASS_EMERGENCY_LOG(program_wide_logger(), s)
00029
00030 namespace nodes {
00031
00032 const int BACKWARDS_BRANCH = 0;
00033
00034
00035
00036
00037
00039
00040
00041
00042 tree::iterator::iterator(const tree *initial, traversal_directions direction)
00043 : path(initial), _order(direction), _aim(AWAY_FROM_ROOT)
00044 {
00045 }
00046
00047 tree::iterator::~iterator() { while (size()) pop(); }
00048
00049 bool tree::iterator::next_node(tree *&to_return)
00050 {
00051 FUNCDEF("next_node");
00052 to_return = NIL;
00053 #ifdef DEBUG_TREE
00054 if ( (_order != to_branches)
00055 && (_order != reverse_branches) ) {
00056 if (_aim == AWAY_FROM_ROOT) LOG("going down")
00057 else LOG("going up");
00058 }
00059 #endif
00060 switch (_order) {
00061 case prefix: {
00062 if (_aim == AWAY_FROM_ROOT) {
00063
00064
00065 to_return = (tree *)(*this)[size() - 1];
00066 #ifdef DEBUG_TREE
00067
00068 if (to_return->branches()) LOG("pushing 0")
00069 else LOG("switching direction");
00070 #endif
00071 if (to_return->branches())
00072 push(to_return->branch(0));
00073 else
00074 _aim = TOWARD_ROOT;
00075 } else {
00076
00077
00078 if (size() == 1) return false;
00079
00080 tree *last = (tree *)pop();
00081 tree *current_tree = (tree *)current();
00082 int lastnum = current_tree->which(last);
00083 #ifdef DEBUG_TREE
00084 if (lastnum < current_tree->branches() - 1)
00085 LOG(isprintf("going down %d", lastnum+1))
00086 else LOG("still going up");
00087 #endif
00088 if (lastnum < current_tree->branches() - 1) {
00089 _aim = AWAY_FROM_ROOT;
00090 push(current_tree->branch(lastnum + 1));
00091 }
00092 }
00093 break;
00094 }
00095 case infix: {
00096 if (_aim == AWAY_FROM_ROOT) {
00097
00098 tree *temp = (tree *)current();
00099 #ifdef DEBUG_TREE
00100 if (temp->branches()) LOG("pushing 0")
00101 else LOG("switching direction");
00102 #endif
00103 if (temp->branches()) push(temp->branch(0));
00104 else {
00105 _aim = TOWARD_ROOT;
00106 to_return = (tree *)current();
00107 #ifdef DEBUG_TREE
00108
00109 #endif
00110 }
00111 } else {
00112
00113
00114 if (size() == 1) return false;
00115
00116 tree *last = (tree *)pop();
00117 tree *current_tree = (tree *)current();
00118 int lastnum = current_tree->which(last);
00119 #ifdef DEBUG_TREE
00120 if (lastnum < 1) LOG(isprintf("going down %d", lastnum+1))
00121 else LOG("still going up");
00122 #endif
00123 if (lastnum < 1) {
00124 _aim = AWAY_FROM_ROOT;
00125 to_return = (tree *)current();
00126 #ifdef DEBUG_TREE
00128 #endif
00129 push(current_tree->branch(lastnum + 1));
00130 }
00131 }
00132 break;
00133 }
00134 case to_branches: {
00135 if (_aim == TOWARD_ROOT) return false;
00136 else {
00137 if (size() == 1) {
00138 tree *temp = (tree *)current();
00139 if (!temp->branches())
00140 _aim = TOWARD_ROOT;
00141 else
00142 push(temp->branch(0));
00143 } else {
00144 tree *last = (tree *)pop();
00145 tree *curr = (tree *)current();
00146 int lastnum = curr->which(last);
00147 if (lastnum < curr->branches() - 1)
00148 push(curr->branch(lastnum + 1));
00149 else _aim = TOWARD_ROOT;
00150 to_return = last;
00151 }
00152 }
00153 break;
00154 }
00155 case reverse_branches: {
00156 if (_aim == TOWARD_ROOT) return false;
00157 else {
00158 if (size() == 1) {
00159 tree *temp = (tree *)current();
00160 if (!temp->branches()) _aim = TOWARD_ROOT;
00161 else push(temp->branch(temp->branches() - 1));
00162 } else {
00163 tree *last = (tree *)pop();
00164 tree *curr = (tree *)current();
00165 int lastnum = curr->which(last);
00166 if (lastnum > 0) push(curr->branch(lastnum - 1));
00167 else _aim = TOWARD_ROOT;
00168 to_return = last;
00169 }
00170 }
00171 break;
00172 }
00173 default:
00174 case postfix: {
00175 if (_aim == AWAY_FROM_ROOT) {
00176
00177 tree *temp = (tree *)current();
00178 #ifdef DEBUG_TREE
00179 if (temp->branches()) LOG("pushing 0")
00180 else LOG("switching direction");
00181 #endif
00182 if (temp->branches()) push(temp->branch(0));
00183 else _aim = TOWARD_ROOT;
00184 } else {
00185
00186 if (!size()) return false;
00187 else if (size() == 1) {
00188 to_return = (tree *)pop();
00189
00190 return true;
00191 }
00192 tree *last = (tree *)pop();
00193 to_return = last;
00194 #ifdef DEBUG_TREE
00196 #endif
00197 tree *current_tree = (tree *)current();
00198 int lastnum = current_tree->which(last);
00199 #ifdef DEBUG_TREE
00200 if (lastnum < current_tree->branches() - 1)
00201 LOG(isprintf("going down %d", lastnum+1))
00202 else LOG("still going up");
00203 #endif
00204 if (lastnum < current_tree->branches() - 1) {
00205 _aim = AWAY_FROM_ROOT;
00206 push(current_tree->branch(lastnum + 1));
00207 }
00208 }
00209 break;
00210 }
00211 }
00212 return true;
00213
00214 }
00215
00216 void tree::iterator::whack(tree *to_whack)
00217 {
00218 FUNCDEF("whack");
00219 if (!to_whack) return;
00220 if (size()) {
00221 if (to_whack == current()) {
00222
00223 pop();
00224 #ifdef DEBUG_TREE
00225 LOG("found node in current top; removing it there.");
00226 #endif
00227 } else if (to_whack->parent() == current()) {
00228
00229 #ifdef DEBUG_TREE
00230 LOG("found node's parent as current top; don't know what to do.");
00231 #endif
00232 } else {
00233 #ifdef DEBUG_TREE
00234 LOG("found no match for either node to remove or parent in path.");
00235 #endif
00236 }
00237 }
00238 tree *parent = to_whack->parent();
00239 if (!parent) {
00240 #ifdef DEBUG_TREE
00241 LOG("no parent node for the one to whack! would have whacked "
00242 "root of tree!");
00243 #endif
00244 } else {
00245 parent->prune(to_whack);
00246 WHACK(to_whack);
00247 }
00248 }
00249
00250 tree *tree::iterator::next()
00251 {
00252 FUNCDEF("next");
00253 tree *to_return = NIL;
00254 bool found_tree = false;
00255 while (!found_tree) {
00256 bool still_running = next_node(to_return);
00257 if (to_return || !still_running) found_tree = true;
00258 }
00259 return to_return;
00260 }
00261
00263
00264
00265
00266 tree::tree()
00267 : node(1)
00268 { set_link(BACKWARDS_BRANCH, NIL); }
00269
00270 tree::~tree()
00271 {
00272
00273
00274 tree *my_parent = parent();
00275 if (my_parent) my_parent->prune(this);
00276
00277
00278 while (branches()) delete branch(0);
00279
00280 }
00281
00282 tree *tree::parent() const { return (tree *)get_link(BACKWARDS_BRANCH); }
00283
00284 int tree::branches() const { return links() - 1; }
00285
00286 tree *tree::branch(int branch_number) const
00287 {
00288 branch_number++;
00289 bounds_return(branch_number, 1, branches(), NIL);
00290 return (tree *)get_link(branch_number);
00291 }
00292
00293 int tree::which(tree *branch_to_find) const
00294 { return node::which((node *)branch_to_find) - 1; }
00295
00296 tree *tree::root() const
00297 {
00298 const tree *traveler = this;
00299
00300
00301 while (traveler->get_link(BACKWARDS_BRANCH))
00302 traveler = (tree *)traveler->get_link(BACKWARDS_BRANCH);
00303 return const_cast<tree *>(traveler);
00304 }
00305
00306 void tree::attach(tree *new_branch)
00307 {
00308 if (!new_branch) return;
00309 insert_link(links(), new_branch);
00310 new_branch->set_link(BACKWARDS_BRANCH, this);
00311 }
00312
00313 void tree::insert(int branch_place, tree *new_branch)
00314 {
00315 branch_place++;
00316 insert_link(links(), NIL);
00317 if (branch_place >= links())
00318 branch_place = links() - 1;
00319 for (int i = links() - 1; i > branch_place; i--)
00320 set_link(i, get_link(i-1));
00321 set_link(branch_place, new_branch);
00322 new_branch->set_link(BACKWARDS_BRANCH, this);
00323 }
00324
00325 outcome tree::prune(tree *branch_to_cut)
00326 {
00327 int branch_number = which(branch_to_cut);
00328 if (branch_number == common::NOT_FOUND) return common::NOT_FOUND;
00329 return prune_index(branch_number);
00330 }
00331
00332 outcome tree::prune_index(int branch_to_cut)
00333 {
00334 branch_to_cut++;
00335 bounds_return(branch_to_cut, 1, branches(), common::NOT_FOUND);
00336 tree *that_branch = (tree *)get_link(branch_to_cut);
00337 that_branch->set_link(BACKWARDS_BRANCH, NIL);
00338 zap_link(branch_to_cut);
00339 return common::OKAY;
00340 }
00341
00342 int tree::depth() const
00343 {
00344 tree *my_root = root();
00345 const tree *current_branch = this;
00346 int deep = 0;
00347 while (current_branch != my_root) {
00348 current_branch = current_branch->parent();
00349 deep++;
00350 }
00351 return deep;
00352 }
00353
00354
00355
00356 bool tree::generate_path(path &to_follow) const
00357 {
00358 if (to_follow.size()) {}
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376
00377 return false;
00378 }
00379
00380
00381
00382 tree::iterator tree::start(traversal_directions direction) const
00383 { return iterator(this, direction); }
00384
00385 }
00386
00387
00388 #endif //TREE_IMPLEMENTATION_FILE
00389