一般树实现

    这里用C++实现了一个一般树,也就是那种通用型的树,例如文件系统所用的树。除了一些树的基本操作外,还支持了节点和数据项的迭代器。

    实现:

#ifndef GENERAL_TREE_H
#define GENERAL_TREE_H

#include
<stdlib.h>
#include
<string>

template
<typename Object>
struct TreeNode
{
Object element;
TreeNode
*parent;
TreeNode
*firstChild;
TreeNode
*nextSibling;
};

template
<class T>
class GeneralIterator
{
public:
virtual T* Next() = 0;
virtual void Reset() = 0;
};

template
<typename Object>
class GeneralTree
{
public:
/** Constructor **/
GeneralTree();
GeneralTree(
const Object& rootElement);
~GeneralTree();

/** Get node operations **/
const TreeNode<Object>* GetRoot() const;
TreeNode
<Object>* GetRoot();
const TreeNode<Object>* GetParent(const TreeNode<Object>* v) const;

/** Iterators **/
GeneralIterator
<Object>* ElementsIterator();
GeneralIterator
< TreeNode<Object> >* NodesIterator();

/** Check the node type **/
bool IsInternal(const TreeNode<Object>* v) const;
bool IsExternal(const TreeNode<Object>* v) const;
bool IsRoot(const TreeNode<Object>* v) const;

/** Get node count **/
int Size() const;

/** Elements operations **/
void SwapElement(TreeNode<Object>* v, TreeNode<Object>* w);
void SetElement(TreeNode<Object>* v, const Object& element);

/** Node operations **/
TreeNode
<Object>* Insert(TreeNode<Object>* parent, const Object& element);
TreeNode
<Object>* InsertAfter(TreeNode<Object>* previousSibling,
const Object& element);
void Remove(TreeNode<Object>* v);
void Remove(const Object& element);
TreeNode
<Object>* Find(const Object& element);

int GetHeight(const TreeNode<Object>* v) const;
int GetDepth(const TreeNode<Object>* v) const;

/** traversal **/
//param is used to pass in parameters and store results
//the boolean returned value indicates if the traversal is done
typedef bool (*Action)(TreeNode<Object>* v, void* param);
bool PreorderTraversal(Action action,
void* param=NULL, TreeNode<Object>* pNode=NULL);
bool PostorderTraversal(Action action,
void* param=NULL, TreeNode<Object>* pNode=NULL);
private:
TreeNode
<Object>* _root;
int _count;
};

template
<typename Object>
TreeNode
<Object>* CreateEmptyNode(const Object* pElement)
{
TreeNode
<Object>* pNode = new TreeNode<Object>();
if(pElement != NULL) pNode->element = *pElement;
pNode
->firstChild = NULL;
pNode
->parent = NULL;
pNode
->nextSibling = NULL;
return pNode;
}

template
<typename Object>
GeneralTree
<Object>::GeneralTree()
{
this->_root = CreateEmptyNode<Object>(NULL);
this->_count = 1;
}

template
<typename Object>
GeneralTree
<Object>::GeneralTree(const Object& rootElement)
{
this->_root = CreateEmptyNode<Object>(&rootElement);
this->_count = 1;
}

template
<typename Object>
GeneralTree
<Object>::~GeneralTree()
{
this->Remove(this->_root);
}

template
<typename Object>
inline
const TreeNode<Object>* GeneralTree<Object>::GetRoot() const
{
return this->_root;
}

template
<typename Object>
inline TreeNode
<Object>* GeneralTree<Object>::GetRoot()
{
return this->_root;
}

template
<typename Object>
inline
const TreeNode<Object>* GeneralTree<Object>::GetParent(const TreeNode<Object>* v) const
{
return v->parent;
}

template
<typename Object>
class ElementsIterator : public GeneralIterator<Object>
{
public:
ElementsIterator(GeneralTree
<Object>* tree)
{
_current
= -1;
_count
= tree->Size();
_elements
= new Object*[_count];
this->FillPointers(tree);
_current
= -1;
}
~ElementsIterator()
{
delete _elements;
}

Object
* Next()
{
++_current;
if(_current < _count)
return _elements[_current];
else
return NULL;
}
void Reset()
{
_current
= -1;
}
private:
Object
** _elements;
int _current;
int _count;

void FillPointers(GeneralTree<Object>* tree);

//friend functions
template<typename T>
friend
bool AddPointer(TreeNode<T>* v, void* param);
};

template
<typename T>
bool AddPointer(TreeNode<T>* v, void* param)
{
ElementsIterator
<T>* itr = (ElementsIterator<T>*)param;
++(itr->_current);
(itr
->_elements)[itr->_current] = &(v->element);

return false;
}

template
<typename Object>
void ElementsIterator<Object>::FillPointers(GeneralTree<Object>* tree)
{
tree
->PreorderTraversal(AddPointer,this);
}

template
<typename Object>
GeneralIterator
<Object>* GetElementsIterator(GeneralTree<Object>* tree)
{
return new ElementsIterator<Object>(tree);
}

template
<typename Object>
GeneralIterator
<Object>* GeneralTree<Object>::ElementsIterator()
{
return GetElementsIterator<Object>(this);
}

template
<typename Object>
class NodesIterator : public GeneralIterator< TreeNode<Object> >
{
public:
NodesIterator(GeneralTree
<Object>* tree)
{
_current
= -1;
_count
= tree->Size();
_elements
= new TreeNode<Object>*[_count];
this->FillPointers(tree);
_current
= -1;
}
~NodesIterator()
{
delete _elements;
}

TreeNode
<Object>* Next()
{
++_current;
if(_current < _count)
return _elements[_current];
else
return NULL;
}
void Reset()
{
_current
= -1;
}
private:
TreeNode
<Object>** _elements;
int _current;
int _count;

void FillPointers(GeneralTree<Object>* tree);

// friend functions
template<typename T>
friend
bool AddNodePointer(TreeNode<T>* v, void* param);
};

template
<typename T>
bool AddNodePointer(TreeNode<T>* v, void* param)
{
NodesIterator
<T>* itr = (NodesIterator<T>*)param;
++(itr->_current);
(itr
->_elements)[itr->_current] = v;

return false;
}
template
<typename Object>
void NodesIterator<Object>::FillPointers(GeneralTree<Object>* tree)
{
tree
->PreorderTraversal(AddNodePointer,this);
}

template
<typename Object>
GeneralIterator
< TreeNode<Object> >* GetNodesIterator(GeneralTree<Object>* tree)
{
return new NodesIterator<Object>(tree);
}

template
<typename Object>
GeneralIterator
< TreeNode<Object> >* GeneralTree<Object>::NodesIterator()
{
return GetNodesIterator<Object>(this);
}

template
<typename Object>
inline
bool GeneralTree<Object>::IsInternal(const TreeNode<Object>* v) const
{
return v->firstChild != NULL;
}

template
<typename Object>
inline
bool GeneralTree<Object>::IsExternal(const TreeNode<Object>* v) const
{
return v->firstChild == NULL;
}

template
<typename Object>
inline
bool GeneralTree<Object>::IsRoot(const TreeNode<Object>* v) const
{
return v->parent == NULL;
}

template
<typename Object>
inline
int GeneralTree<Object>::Size() const
{
return this->_count;
}

template
<typename Object>
void GeneralTree<Object>::SwapElement(TreeNode<Object>* v, TreeNode<Object>* w)
{
Object tem
= v->element;
v
->element = w->element;
w
->element = tem;
}

template
<typename Object>
void GeneralTree<Object>::SetElement(TreeNode<Object>* v, const Object& element)
{
v
->element = element;
}

template
<typename Object>
TreeNode
<Object>* GeneralTree<Object>::Insert(TreeNode<Object>* parent, const Object& element)
{
// Create the new node
TreeNode<Object>* pNewNode = new TreeNode<Object>();
pNewNode
->element = element;
pNewNode
->parent = parent;
pNewNode
->firstChild = NULL;
pNewNode
->nextSibling = NULL;

// Insert the new node
if(parent->firstChild == NULL)
{
parent
->firstChild = pNewNode;
}
else
{
TreeNode
<Object>* pChild = parent->firstChild;
while(pChild->nextSibling != NULL) pChild = pChild->nextSibling;
pChild
->nextSibling = pNewNode;
}

// increment the count
++this->_count;

return pNewNode;
}

template
<typename Object>
TreeNode
<Object>* GeneralTree<Object>::InsertAfter(TreeNode<Object>* previousSibling,
const Object& element)
{
// Create the new node
TreeNode<Object>* pNewNode = new TreeNode<Object>();
pNewNode
->element = element;
pNewNode
->parent = previousSibling->parent;
pNewNode
->firstChild = NULL;

// Connect new node with its previous node
pNewNode->nextSibling = previousSibling->nextSibling;
previousSibling
->nextSibling = pNewNode;

// Increment the count
++this->_count;

return pNewNode;
}

template
<typename Object>
bool FreeNode(TreeNode<Object>* v, void* param)
{
int* size = (int*)param;
--(*size);
delete v;
return false;
}

template
<typename Object>
void GeneralTree<Object>::Remove(TreeNode<Object>* v)
{
if(v->parent != NULL)
{
// find the previous sibling
TreeNode<Object>* pChild = (v->parent)->firstChild;
if(pChild == v)
v
->parent->firstChild = NULL;
else
{
while(pChild->nextSibling != v) pChild = pChild->nextSibling;

// adjust the tree structure
pChild->nextSibling = v->nextSibling;
}

// free all the children and itself
}
this->PostorderTraversal(FreeNode,&(this->_count),v);
}

template
<typename Object>
void GeneralTree<Object>::Remove(const Object& element)
{
TreeNode
<Object>* pRemovedNode = Find(element);
this->Remove(pRemovedNode);
}

template
<typename Object>
struct TestParam
{
Object
* pElement;
TreeNode
<Object>* pNode;
};

template
<typename Object>
bool TestElement(TreeNode<Object>* v, void* param)
{
// the param is an array,
// in which the first element stores the pointer to the element
// and the second element will store the pointer to the found node
TestParam<Object>* pTestParam = (TestParam<Object>*)param;
Object
* pElement = pTestParam->pElement;
if(v->element == *pElement)
{
pTestParam
->pNode = v; // set the found node
return true; // it is done.
}
else
return false;
}

template
<typename Object>
TreeNode
<Object>* GeneralTree<Object>::Find(const Object& element)
{
Object findingElement
= element;
TestParam
<Object> testParam;
testParam.pElement
= &findingElement;
this->PreorderTraversal(TestElement, &testParam);
return testParam.pNode;
}

template
<typename Object>
int GeneralTree<Object>::GetHeight(const TreeNode<Object>* v) const
{
if(this->IsExternal(v))
return 0;
else
{
int maxChildHeight = 0;
TreeNode
<Object> pChild = v->firstChild;
while(pChild != NULL)
{
int childHeight = this->GetHeight(pChild);
if(childHeight > maxChildHeight)
maxChildHeight
= childHeight;
}
return maxChildHeight + 1;
}
}

template
<typename Object>
int GeneralTree<Object>::GetDepth(const TreeNode<Object>* v) const
{
if(this->IsRoot(v))
return 0;
else
return 1 + this->GetDepth(v->parent);
}

template
<typename Object>
bool GeneralTree<Object>::PreorderTraversal(Action action,
void* param, TreeNode<Object>* pNode)
{
if(pNode == NULL) pNode = this->_root;
// visit the node
bool isDone = action(pNode, param);
if(isDone == false)
{
// traverse the children
TreeNode<Object>* pChild = pNode->firstChild;
while(pChild != NULL)
{
bool isDone = this->PreorderTraversal(action,
param, pChild);
if(isDone)
break;
else
pChild
= pChild->nextSibling;
}
}
return isDone;
}

template
<typename Object>
bool GeneralTree<Object>::PostorderTraversal(Action action,
void* param, TreeNode<Object>* pNode)
{
if(pNode == NULL) pNode = this->_root;

// traverse the children
TreeNode<Object>* pChild = pNode->firstChild;
while(pChild != NULL)
{
bool isChildDone = this->PostorderTraversal(action, param, pChild);
if(isChildDone)
return true;
else
pChild
= pChild->nextSibling;
}

// visit the element
return action(pNode, param);
}

#endif

 

 

 

    测试代码:
    

代码
#include<iostream>
#include
<string>
#include
"GeneralTree.h"

using namespace std;

bool display(TreeNode<string>* v, void* param)
{
GeneralTree
<string>* tree = (GeneralTree<string>*)param;
int depth = tree->GetDepth(v);
string prefix = "";
for(int i = 0; i < depth; i++) prefix += "----";
cout
<< prefix << v->element << endl;
return false;
}

bool addPrefix(TreeNode<string>* v, void* param)
{
string* pStr = (string*)param;
v
->element = *pStr + v->element;
return false;
}

int main()
{
// construct the tree
GeneralTree<string> tree("Paper");

TreeNode
<string>* insertedNode = tree.Insert(tree.GetRoot(), "Title");

insertedNode
= tree.InsertAfter(insertedNode, "Abstract");

insertedNode
= tree.InsertAfter(insertedNode, "$1");
TreeNode
<string>* insertedChild = tree.Insert(insertedNode, "$1.1");
insertedChild
= tree.InsertAfter(insertedChild, "$1.2");

insertedNode
= tree.InsertAfter(insertedNode, "$2");
insertedChild
= tree.Insert(insertedNode, "$2.1");
insertedChild
= tree.InsertAfter(insertedChild, "$2.2");
insertedChild
= tree.InsertAfter(insertedChild, "$2.3");

insertedNode
= tree.InsertAfter(insertedNode, "$3");
insertedChild
= tree.Insert(insertedNode, "$3.1");
insertedChild
= tree.InsertAfter(insertedChild, "$3.2");

insertedNode
= tree.InsertAfter(insertedNode, "References");

// display the tree
cout << "Preorder traversal:" << endl;
tree.PreorderTraversal(display,
&tree);

cout
<< "Postorder traversal:" << endl;
tree.PostorderTraversal(display,
&tree);

// edit the element
TreeNode<string>* pFoundNode = tree.Find("$3");
tree.SetElement(pFoundNode,
"$3 cource");
tree.SwapElement(tree.Find(
"$3.1"),tree.Find("$3.2"));
tree.Remove(
"$1");
cout
<< "after altering the elements" << endl;
tree.PreorderTraversal(display,
&tree);

// test the node
cout << "check if internal:" << (tree.IsInternal(pFoundNode)?"true":"false") << endl;
cout
<< "check if external:" << (tree.IsExternal(pFoundNode)?"true":"false") << endl;
cout
<< "check if root:" << (tree.IsRoot(pFoundNode)?"true":"false") << endl;
cout
<< "size:" << tree.Size() << endl;

// Iterator
cout << "Traverse elements:" << endl;
GeneralIterator
<string>* itr = tree.ElementsIterator();
string* pStr;
while((pStr = itr->Next()) != NULL) cout << *pStr << endl;
delete itr;

cout
<< "Traverse nodes:" << endl;
GeneralIterator
< TreeNode<string> >* nodesItr = tree.NodesIterator();
TreeNode
<string>* pNode;
while((pNode = nodesItr->Next()) != NULL)
cout
<< "Node:" << string(4*tree.GetDepth(pNode),'-') << pNode->element <<endl;

return 0;
}

 

posted @ 2010-12-14 21:42  李土鳖  阅读(419)  评论(1编辑  收藏  举报