二叉树是一种有些特殊的数据结构,因为单独一个顶点也算二叉树。那么,我们不妨定义二叉树的结点类,而不是去定义整个二叉树类。下面是二叉树的节点类:
#include <iostream> using namespace std; #ifndef TREENODE_H_INCLUDED #define TREENODE_H_INCLUDED template <class ElemType> class TreeNode { private: TreeNode* lchild; TreeNode* rchild; public: ElemType data; TreeNode(const ElemType& item,TreeNode* lptr=NULL,TreeNode* rptr=NULL): lchild(lptr),rchild(rptr),data(item){ } ~TreeNode(){ } TreeNode*& LeftChild(){return lchild;} TreeNode*& RightChild(){return rchild;} }; #endif // TREENODE_H_INCLUDED
下面是对二叉树进行的遍历操作,包括先序、中序、后序遍历的递归形式和非递归形式,还包括了按层遍历:
#include <iostream> #include "TreeNode.h" #include "../LinkQueue/LinkQueue.h" #include "../LinkStack/LinkStack.h" using namespace std; #ifndef TREESCAN_H_INCLUDED #define TREESCAN_H_INCLUDED template <class ElemType> void PreOrderTraverse(TreeNode<ElemType>* t,void (*Visit)(ElemType &e)) { if(t) { Visit(t->data); PreOrderTraverse(t->LeftChild(),Visit); PreOrderTraverse(t->RightChild(),Visit); } } template <class ElemType> void InOrderTraverse(TreeNode<ElemType>* t,void (*Visit)(ElemType& e)) { if(t) { InOrderTraverse(t->LeftChild(),Visit); Visit(t->data); InOrderTraverse(t->RightChild(),Visit); } } template <class ElemType> void PostOrderTraverse(TreeNode<ElemType>* t,void (*Visit)(ElemType& e)) { if(t) { PostOrderTraverse(t->LeftChild(),Visit); PostOrderTraverse(t->RightChild(),Visit); Visit(t->data); } } template <class ElemType> void LevelTraverse(TreeNode<ElemType>* t,void (*Visit)(ElemType& e)) { LinkQueue<TreeNode<ElemType>*> Q; TreeNode<ElemType>* p; Q.EnQueue(t); while(!Q.QueueEmpty()) { Q.DeQueue(p); Visit(p->data); if(p->LeftChild()) { Q.EnQueue(p->LeftChild()); } if(p->RightChild()) { Q.EnQueue(p->RightChild()); } } } template <class ElemType> void PreOrderTraverse_I(TreeNode<ElemType>* t,void (*Visit)(ElemType& e)) { LinkStack<TreeNode<ElemType>*> S; TreeNode<ElemType>* p=t; while(p||!S.StackEmpty()) { while(p) { Visit(p->data); S.Push(p); p=p->LeftChild(); } if(!S.StackEmpty()) { S.Pop(p); p=p->RightChild(); } } } template <class ElemType> void InOrderTraverse_I(TreeNode<ElemType>* t,void (*Visit)(ElemType& e)) { LinkStack<TreeNode<ElemType>*> S; TreeNode<ElemType>* p=t; while(p||!S.StackEmpty()) { while(p) { S.Push(p); p=p->LeftChild(); } if(!S.StackEmpty()) { S.Pop(p); Visit(p->data); p=p->RightChild(); } } } template <class ElemType> struct StackNode { TreeNode<ElemType>* ptr; int tag; }; template <class ElemType> void PostOrderTraverse_I(TreeNode<ElemType>* t,void (*Visit)(ElemType& e)) { StackNode<ElemType> curnode,topnode; LinkStack<StackNode<ElemType> > S; TreeNode<ElemType>* p=t; do { while(p) { curnode.ptr=p; curnode.tag=0; S.Push(curnode); p=p->LeftChild(); } S.GetTop(topnode); while(!S.StackEmpty()&&topnode.tag==1) { S.Pop(curnode); p=curnode.ptr; Visit(p->data); S.GetTop(topnode); } if(!S.StackEmpty()) { S.Pop(topnode); topnode.tag=1; S.Push(topnode); p=topnode.ptr->RightChild(); } } while(!S.StackEmpty()); } #endif // TREESCAN_H_INCLUDED
下面是一些常用的二叉树操作,包括建立二叉树、求二叉树节点数、求二叉树叶子数、求二叉树深度、销毁二叉树等:
#include <iostream> #include "TreeNode.h" using namespace std; #ifndef BITREE_H_INCLUDED #define BITREE_H_INCLUDED template <class ElemType> TreeNode<ElemType>* GetTreeNode(ElemType item,TreeNode<ElemType>* lptr,TreeNode<ElemType>* rptr) { TreeNode<ElemType>* p=new TreeNode<ElemType>(item,lptr,rptr); return p; } template <class ElemType> void FreeTreeNode(TreeNode<ElemType>* p) { delete p; } template <class ElemType> int CountLeaf(TreeNode<ElemType>* t) { if(t) { if(!t->LeftChild()&&!t->RightChild()) { return 1; } else { return CountLeaf(t->LeftChild())+CountLeaf(t->RightChild()); } } else { return 0; } } template <class ElemType> int CountNode(TreeNode<ElemType>* t) { if(t) { if(!t->LeftChild()&&!t->RightChild()) { return 1; } else { return CountNode(t->LeftChild())+CountNode(t->RightChild())+1; } } else { return 0; } } template <class ElemType> int Depth(TreeNode<ElemType>* t) { int depthleft,depthright,depthval; if(!t) { depthval=0; } else { depthleft=Depth(t->LeftChild()); depthright=Depth(t->RightChild()); depthval=1+(depthleft>depthright?depthleft:depthright); } return depthval; } template <class ElemType> TreeNode<ElemType>* CopyTree(TreeNode<ElemType>* t) { TreeNode<ElemType>* newnode,*newlptr,*newrptr; if(!t) { return NULL; } if(t->LeftChild()) { newlptr=CopyTree(t->LeftChild()); } else { newlptr=NULL; } if(t->RightChild()) { newrptr=CopyTree(t->RightChild()); } else { newrptr=NULL; } newnode=new TreeNode<ElemType>(t->data,newlptr,newrptr); return newnode; } template <class ElemType> void DeleteTree(TreeNode<ElemType>* t) { if(t) { DeleteTree(t->LeftChild()); DeleteTree(t->RightChild()); FreeTreeNode(t); } } template <class ElemType> void ClearTree(TreeNode<ElemType>* &t) { DeleteTree(t); t=NULL; } #endif // BITREE_H_INCLUDED
写二叉树的时候用到了自己之前写的链栈类和链队列类。参考了国外的经典教材《数据结构C++语言描述》。