// $Id: tree2.h,v 1.2 1999/06/05 23:29:16 greear Exp $ // $Revision: 1.2 $ $Author: greear $ $Date: 1999/06/05 23:29:16 $ // //ScryMUD Server Code //Copyright (C) 1998 Ben Greear // //This program is free software; you can redistribute it and/or //modify it under the terms of the GNU General Public License //as published by the Free Software Foundation; either version 2 //of the License, or (at your option) any later version. // //This program is distributed in the hope that it will be useful, //but WITHOUT ANY WARRANTY; without even the implied warranty of //MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //GNU General Public License for more details. // //You should have received a copy of the GNU General Public License //along with this program; if not, write to the Free Software //Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. // // To contact the Author, Ben Greear: greear@cyberhighway.net, (preferred) // greearb@agcs.com // ///********************** tree2.h *********************************/// /* This is the most heinous piece of code I have ever produced, other than that failed attempt at a suffix tree. Hope I can get it working. */ #ifndef TREE_2_INCLUDE #define TREE_2_INCLUDE template <class T> class Tree2Node; template <class T> class Tree2; template <class T> class Tree2Cell { friend class Tree2Node<T>; friend class Tree2<T>; private: Tree2Node<T>* ptr; public: operator const int() const { if (ptr) return TRUE; return FALSE; } Tree2Cell(Tree2<T>& tree) { ptr = tree.root; } Tree2Cell(Tree2Node<T>& node) { ptr = &node; } Tree2Cell() { ptr = NULL; } void Head(Tree2<T>& tree) { ptr = tree.root;} void Head(Tree2Node<T>& nd) { ptr = &nd; } T& Data() { if (ptr) { return ptr->data; }//if //log("TRACK: ERROR: FATAL trying to get->NULL data in Data().\n"); exit(102); }//Data() /* return current value, THEN increment by one */ T& Next_Breadth() { //will crash if let run too far if (!ptr) { //log("TRACK: ERROR: ptr is NULL, Next_Breadth.\n"); exit(102); }//if T* tmp_ptr = &(ptr->data); ptr = ptr->next; return *tmp_ptr; } T& Parent() { //will crash if let run too far if (!ptr) { //log("TRACK: ERROR: ptr is NULL, Parent.\n"); exit(102); }//if T* tmp_ptr = &(ptr->data); ptr = ptr->parent; return *tmp_ptr; } /* This next one should add a child to the first of the children of the Tree2Node pointed to by the current TreeCell. A pointer to the just inserted Tree2Node will be returned. */ Tree2Node<T>* Push_Child(T& dat) const { Tree2Node<T>* tmp, *tmp_par; if (!ptr) { //log("TRACK: ERROR: Tree2Cell is NULL in Push_Child()\n"); return NULL; }//if else if (!ptr->prev && !ptr->next) { //if empty tree //log("TRACK: inserting in an empty tree.\n"); ptr->Insert_After(ptr, ptr->level + 1, dat); ptr->first = ptr->next; return ptr->next; }//else else if (ptr->first) { //if has a first child ptr->first->Insert_Before(ptr, ptr->level + 1, dat); ptr->first = ptr->first->prev; //new one is now first return ptr->first; }//if else { //no immediate children of this node, /* If previous sibs have children, put it after them, else put it after last sibling */ /* first, check for previous sibs with children */ tmp = ptr;// tmp points to current tree node while (TRUE) { if (tmp->prev->level != tmp->level) { //left most end, no dice break; }//if if (tmp->first) { //found a child, good to go tmp_par = tmp; tmp = tmp->first; while (TRUE) { if (!tmp->next) { // end of tree, good do it here break; }//if if (tmp->next->parent != tmp_par) { //also good, end of //tmp_par's children break; }//if tmp = tmp->next; //keep walking foward through children }//while /* now we are at posn */ tmp->Insert_After(ptr, ptr->level + 1, dat); ptr->first = tmp->next; return ptr->first; }//if tmp = tmp->prev; //keep walking left through cibs }//while /* if got to here, then at left most cib, no children. Must now find right most cib and place the new node after it, with 'ptr' as its parent. */ while (TRUE) { if (!tmp->next) { //if last one then done break; }//if if (tmp->level != tmp->next->level) { //at end of level, done break; }//if tmp = tmp->next; //walk on down cibs }//while /* ok, good to go, insert after tmp */ tmp->Insert_After(ptr, ptr->level + 1, dat); ptr->first = tmp->next; //original ptr gets child return ptr->first; }//else no immediate children }//Push_Child() };//Tree2Cell template <class T> class Tree2Node { friend class Tree2Cell<T>; friend class Tree2<T>; private: short level; Tree2Node<T>* first; Tree2Node<T>* parent; T data; Tree2Node<T>* next; Tree2Node<T>* prev; public: Tree2Node(int lvl, Tree2Node<T>* frst, Tree2Node<T>* par, T& dat, Tree2Node<T>* nxt, Tree2Node<T>* prv) { level = lvl; first = frst; parent = par; data = dat; next = nxt; prev = prv; } Tree2Node() { parent = first = next = prev = NULL; level = 0; } ~Tree2Node() { delete next; next = prev = first = parent = NULL; }//destructor T& Data() { return data; } void Insert_Before(Tree2Node<T>* par, short lvl, T& data) { Tree2Node<T>* nn = new Tree2Node<T>(lvl, NULL, par, data, NULL, NULL); if (this->prev) { nn->prev = this->prev; this->prev = nn; nn->prev->next = nn; nn->next = this; }//if else { //new beginning of list nn->next = this; this->prev = nn; }//else }//Insert_Before void Insert_After(Tree2Node<T>* par, short lvl, T& data) { Tree2Node<T>* nn = new Tree2Node<T>(lvl, NULL, par, data, NULL, NULL); if (this->next) { nn->prev = this; nn->next = this->next; nn->next->prev = nn; this->next = nn; }//if else { //new end nn->prev = this; this->next = nn; }//else }//Insert_After }; //Tree2Node template <class T> class Tree2 { friend class Tree2Node<T>; friend class Tree2Cell<T>; private: Tree2Node<T>* root; public: Tree2(T& data) { root = new Tree2Node<T>(); root->data = data; } ~Tree2() { Clear(); root = NULL; } void Clear() { delete root; //should fire destructors root = NULL; }//if void Log() { //write to logfile String buf(100); //log("TRACK: Tree2 Log.\n"); //what other kind can there be?? :) Tree2Cell<T> cll(*this); if (!cll.ptr) { //log("TRACK: cll.ptr is NULL.\n"); }//if while (cll) { Sprintf(buf, "TRACK: this: %i, prv: %i, nxt: %i, par: %i, frst: %i, data: %i, lvl: %i", (int)(cll.ptr), (int)(cll.ptr->prev), (int)(cll.ptr->next), (int)(cll.ptr->parent), (int)(cll.ptr->first), (int)(cll.ptr->data), (int)(cll.ptr->level)); //log(buf); cll.Next_Breadth(); }//while }//log }; //Tree2 #endif