![]() |
Development Lifecycle »
Design and Architecture »
Data Structures
Intermediate
Tree data class for C++By Alexander KovachevSimple class to represent tree data structures in C++ |
VC6, VC7Win2K, WinXP, Visual Studio, STL, Dev
|
|
Advanced Search Add to IE Search |
|
|
|
||||||||||||||||
Not so long ago in one of my recent projects I needed a tree class for representing data structures. I looked all over the web and didn't find any acceptable solution. A tree is a structure which is not as simple as an array or list, so unfortunately STL comes without it and I had to write one myself.
I divided the implementation on two main parts: Data and Node. Data object is responsible for holding the data, and the Node (Tree) for the tree structure.
The purpose of the Data class is to keep the actual data. It keeps the data until all actual references to it are dead. This is done with reference counting (COM like). I know somebody may find this worthless and useless, but it makes the data more capsulated and secure. The implementation is divided in two classes Data and Ref (reference). All the data is stored in the Data class. All the job is done by Ref class, which manipulates the data class:
template <class Type> class Data { private: ...// all methods and variables are private friend class Ref<Type>; // Ref class will manipulate us }; template <class Type> class Ref { Ref(Type *p); Ref(); Ref(const Ref<Type> rhs); //destructor virtual ~Ref(); //operators = Ref operator=(const Ref<Type> rhs); Ref operator=(const Type t); Ref operator=(Type *p); // operator == bool operator==(const Ref<Type> rhs) // misc Ref Clone(); void Release(); bool IsNull(); // accessors to the actual data // (check if it's null first) Type *operator->(); Type get_Data(); operator Type(); }
Tree class represents a node in the tree, so it has parent and it has children. in this way i use a single class for representing a node and a tree, so the the tree is a node without parent, and leaf is a node without children. It also has reference (Ref) to the data. It's implementation is divided between two classes NodeData and Tree. NodeData objects holds the actual data for the parent and the children, but Tree object manipulates this data and gives access to them. Actually you'll always use only Tree class directly.
Definitons:
template <class Type> class NodeData { private: .... // all methods vars are private friend class Tree<Type>; } template <class Type> class Tree { public: // we'll call the tree node typedef Tree<Type> Node; // parent Node Parent(); // children - Nodes __declspec( property( get=get_Nodes) ) Node Nodes[]; __declspec( property( get=get_Count) ) int Count; Node get_Nodes(int nIndex); int get_Count(); // data acess __declspec( property( get=get_Data) ) Ref<Type> Data; operator Type(); Type *operator->(); Ref<Type> get_Data(); // node functions (isLeaf and so on bool IsLeaf(); bool IsNode(); bool IsRoot(); // comparision bool operator == (const Node rhs) { return *(NodeBase*)this==(NodeBase )rhs;}; // node operations Node AddNode(const Type t); void Delete(); void DeleteNode(int nIndex); void DeleteNode(Node node); // constructors Tree(const Type Data); Tree(Type *Data); Tree(); Tree(const Tree<Type> rhs); Tree(const NodeBase rhs); // destructor virtual ~Tree(); }
#include "stdio.h" #include "tree.h" #include "string" using namespace std; typedef Tree<string> StringTree; typedef StringTree::Node StringNode; // recursive function for prionitng nodes void PrintNode(StringNode node,int nLevel) { // print new line fputs("\n",stdout); // print spaces for indent (2 for every level) string s; s.resize(nLevel*2,' '); fputs(s.c_str(),stdout); // print the value fputs(node.get_Data()->c_str(),stdout); // iterate through children nLevel++; for(int n= 0;n<&;node.Count;n++) { PrintNode(node.Nodes[n],nLevel); } } int main(int argc, char* argv[]) { // define the tree StringTree tree; ((string&)tree)="Root"; //add few nodes StringNode node=tree; node.AddNode("1").AddNode("11"); StringNode node2=node.AddNode("2"); node2.AddNode("21").AddNode("211"); node2.AddNode("22"); node2.AddNode("23"); node.AddNode("3"); // print the tree PrintNode(tree,0); // wait for enter char buf[3]; fputs("\nPress ENTER :",stdout); fgets(buf,3,stdin); return 0; }
The presented Tree class is not the best solution, and is not also not the best performer since it uses vector internally, but is flexible and easy to use. Most of available Tree structures you'll find we'll require direct work with pointers, and a lot of code to be filled and indexed. This one is very easy to use (with the price for this of course).
Contact me if you have comments and opinions (akovache@san.rr.com)
| You must Sign In to use this message board. | |||||||||||||||||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||||||||||||||||
General
News
Question
Answer
Joke
Rant
Admin
|
PermaLink |
Privacy |
Terms of Use
Last Updated: 12 Jan 2002 Editor: Chris Maunder |
Copyright 2002 by Alexander Kovachev Everything else Copyright © CodeProject, 1999-2009 Web18 | Advertise on the Code Project |