Environment:
all
Class
for presenting tree
structures in C++.
1. Data objects:
- 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 vars 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();
}
2. Tree
object:
- 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 praent. 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 manipualtes this data and gives access to them.
Actually you'll always use only
Tree class directly.
- definitions
- node - a simple node or leaf in the tree
- leaf - a node without children
- root (tree) - a node without parent (i.e. prent is Null)
- Null - null node
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();
}
3. Simple usage:
// function for printing 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;
}
Downloads
Download
source Code & demo project - 5 Kb