一般树实现
这里用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;
}