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