孩子兄弟表示法实现树

因本人能力有限,参考了另一位大牛的代码,在此向他表示感谢!

vs2008运行正确,如有误,请各位大牛指正!

// CSTree.cpp : 定义控制台应用程序的入口点。
//孩子兄弟表示法实现树
#include "stdafx.h"
#include <iostream>
using namespace std;

const int MaxCSTreeSize = 20; 
//结点类
template<class T>
class CSNode
{
public:
	CSNode();
	CSNode(CSNode<T>* firstchild,CSNode<T>* nextsibling,T newdata);
	CSNode<T>* getFirstChild();
	CSNode<T>* getNextSibling();
	T getData();
	void setFirstChild(T newData);
	void setNextsibling(T newData);
public:
	T data;
	CSNode* firstchild;
	CSNode* nextsibling;
};

template<class T>
CSNode<T>::CSNode()
{
	firstchild = NULL;
	nextsibling = NULL;
}

template<class T>
CSNode<T>::CSNode(CSNode<T>* firstchild,CSNode<T>* nextsibling,T newdata):firstchild(firstchild),nextsibling(nextsibling),data(newdata)
{}

template<class T>
CSNode<T>* CSNode<T>::getFirstChild()
{
	return firstchild;
}

template<class T>
CSNode<T>* CSNode<T>::getNextSibling()
{
	return nextsibling;
}

template<class T>
T CSNode<T>::getData()
{
	return data;
}

template<class T>
void CSNode<T>::setFirstChild(T newData)
{
	firstchild->data = newData;
}

template<class T>
void CSNode<T>::setNextsibling(T newData)
{
	nextsibling->data = newData;
}

//树类
template<class T>
class CSTree
{
public:
	CSTree();  
	CSTree(const CSTree<T>& csTree);  //拷贝构造函数
	~CSTree();  
	const CSTree<T>& operator=(const CSTree<T>& csTree);//重载赋值运算符
	void  createCSTree(); //按建立树   
	void  InitCSTree();   //初始化树   
	void  destoryCSTree();//销毁树   
	bool  isEmptyCSTree();//检查树是否为空    
	void  preOrderTraverse();//先序遍历   
	void  postOrderTraverse(); //后序遍历   
	void  levelOrderTraverse();//层序遍历   
	int   heightCSTree();//树高度   
	int   widthCSTree(); //树宽度 
	int   getDegreeCSTree();//树的度--树中所有结点度的最大值
	int   nodeCountCSTree();  //树结点个数
	int   LeavesCountCSTree();//树叶子个数   
	int   nodeLevelCSTree(T item);//结点item在的层次
	int   getChildrenCount(const CSNode<T>* p)const;//返回结点孩子个数
	void  getAllParentCSTree(T item)const;//找item的所有祖先   
	void  longPathCSNode();//输出从每个叶子结点到根结点的最长路径 ----- 未实现
	bool  findCSNode(const T item,CSNode<T>*& ret)const; //查找结点 
	bool  getParentCSTree(const T item,CSNode<T>*& ret)const;//查找结点item的父亲结点
	bool  getleftChild(const CSNode<T>* p,CSNode<T>*& ret) const; //返回最左边的兄弟
	bool  getrightSibling(const CSNode<T>* p,CSNode<T>*& ret) const; //返回最右边的兄弟
	bool  getAllSibling(const T item) const;//输出所有兄弟
	bool  getAllChildren(T item);//输出所有的孩子
private:
	void create(CSNode<T>*& p);//以p为根创建子树
	void  copyTree(CSNode<T>*& copyTreeRoot,CSNode<T>* otherTreeRoot);//把以otherTreeRoot为根节点的部分拷贝到copyTreeRoot为根节点的部分   
	void  destory(CSNode<T>*& p,int& num);//销毁以p为根节点的部分    
	void  preOrder(CSNode<T>* p);//先序遍历以p为根节点的部分   
	void  postOrder(CSNode<T>* p);//后序遍历以p为根节点的部分   
	void  levelOrder(CSNode<T>* p);//层次遍历以p为根节点的部分   
	int   height(CSNode<T>* p);//计算以p为根节点的高度   
	int   width(CSNode<T>* p);//计算以p为根子树的宽度
	int   nodeCount(CSNode<T>* p);//计算以p为根节点的结点个数   
	int   leavesCount(CSNode<T>* p);//计算以p为根节点的叶子个数   
	void  nodeLevel(T item,CSNode<T>* p,int level,int& nlevel);//计算以p为根节点的中item所在层次,如有多个元素,则遇到第一个则返回(离根最近),如果没有出现,则返回0   
	bool  find(CSNode<T>*p,const T item,bool& isFind,CSNode<T>*& cur)const;//在p指向的树中,返回 值为item的指针  
	bool  getParent(CSNode<T>*p,const T item,bool& isFind,bool& isFirst,CSNode<T>*& ret)const;//在p指向子树中,找item的父亲
	bool getAllParent(T item,CSNode<T>* p,CSNode<T>* path[MaxCSTreeSize],int& seat,bool& isFind)const;//找item的所有祖先,seat表示最后一个父亲的下标 
	void  longPath(CSNode<T>* p,int len,int& maxLen,CSNode<T>*& longNode);//输出从每个叶子结点到根结点的最长路径    
	int getDegree(CSNode<T>* p);//输出树的度(书中结点的孩子最大值)
private:
	CSNode<T>* root;
};

template<class T>
CSTree<T>::CSTree()
{
	root = NULL;
}

template<class T>
CSTree<T>::CSTree(const CSTree<T>& csTree)//拷贝构造函数
{
	if (csTree.root != NULL)
	{
		copyTree(root,csTree.root);
	}
	else
	{
		root = NULL;
	}
}

template<class T>
void  CSTree<T>::copyTree(CSNode<T>*& copyTreeRoot,CSNode<T>* otherTreeRoot)//把以otherTreeRoot为根节点的部分拷贝到copyTreeRoot为根节点的部分   
{
	if (otherTreeRoot != NULL)
	{
		copyTreeRoot = new CSNode<T>;
		copyTreeRoot->data = otherTreeRoot->data;
		copyTree(copyTreeRoot->firstchild,otherTreeRoot->firstchild);
		copyTree(copyTreeRoot->nextsibling,otherTreeRoot->nextsibling);
	}
}

template<class T>
CSTree<T>::~CSTree() //析构函数 注意
{
	if(root != NULL)
	{
		int number = 0;//number记录被释放结点的个数,为了调试使用
		destory(root,number);
		InitCSTree();
	}
}

template<class T>
void  CSTree<T>::InitCSTree()   //初始化树
{	
	root = NULL;
}

template<class T>
void  CSTree<T>::destory(CSNode<T>*& p,int& num)//销毁以p为根节点的部分 
{
	if (p!=NULL)
	{
		destory(p->firstchild,num);
		destory(p->nextsibling,num);
		delete p;		
		num++;
	}
}

template<class T>
void  CSTree<T>::destoryCSTree()//销毁树 
{
	int number = 0;
	destory(root,number);
	root = NULL;
	cout<<"销毁了"<<number<<"个结点!"<<endl;
}

template<class T>
const CSTree<T>& CSTree<T>::operator=(const CSTree<T>& csTree)
{
	if (this!=&csTree)//避免自赋值
	{
		if (root!=NULL)//被赋值的对象不空,释放其资源
		{
			int number = 0;
            destory(root,number);
		}
		if (csTree.root != NULL)
		{
			copyTree(root,csTree.root);
		}
		else
		{
			root = NULL;
		}
	}
	return *this;
}

template<class T>
void  CSTree<T>::createCSTree() // 
{
	create(root);
}

template<class T>
void CSTree<T>::create(CSNode<T>*& p)//以p为根创建子树 利用队列,整个过程中只入队,不出队列
{
   T parent;
   T child;

   //定义循环队列
   CSNode<T> *queue[MaxCSTreeSize];
   int front = 0;
   int rear = 0;

   CSNode<T> *current;
   cout<<"请输入父亲和孩子:"<<endl;
   cin>>parent>>child;
   while(child != '#')//输入结束
   {
     CSNode<T> *newNode = new CSNode<T>;
	 newNode->data = child;
	 newNode->firstchild = NULL;
	 newNode->nextsibling = NULL;

	 if (parent == '#')//根结点
	 {
		 p = newNode;
         queue[(rear++)%MaxCSTreeSize] = p;//根入队列
	 }
	 else
	 {
         current = queue[front]; //读取队顶元素
		 while(current->data != parent)//在队列中查找父亲结点
		 {
			 front = (front+1)%MaxCSTreeSize;
			 current = queue[front];
		 }

		 if (current->data == parent)//对顶元素是当前新建结点的父亲
		 {
             if (current->firstchild == NULL)
             {
				 current->firstchild = newNode;
             }
			 else
			 {
                 current = current->firstchild;
				 while(current->nextsibling!=NULL)
				 {
					 current = current->nextsibling;
				 }
				 current->nextsibling = newNode;
			 }
		 }	

		 if ((rear+1)%MaxCSTreeSize != front)//队列不满,将孩子入队列
		 {
			 queue[(rear++)%MaxCSTreeSize] = newNode;
		 }
	 }
	 cin>>parent>>child;
   }
}

template<class T>
bool  CSTree<T>::isEmptyCSTree()//检查树是否为空 
{
	if (root == NULL)
	{
		return true;
	}
	else
	{
		return false;
	}
}

template<class T>
void  CSTree<T>::preOrderTraverse()//先序遍历 
{
	preOrder(root);
}

template<class T>
void  CSTree<T>::preOrder(CSNode<T>* p)//树的先序遍历等价于cstree的先序遍历
{
	if (p!=NULL)
	{
		cout<<p->data<<" ";//cout<<p->getData()<<" ";
		preOrder(p->firstchild);
		preOrder(p->nextsibling);
	}
}

template<class T>
void  CSTree<T>::postOrderTraverse() //后序遍历 
{
	postOrder(root);
}

template<class T>
void  CSTree<T>::postOrder(CSNode<T>* p)//树的后序遍历等价于cstree的中序遍历   
{
	if (p!=NULL)
	{
		postOrder(p->firstchild);
		cout<<p->data<<" ";
		postOrder(p->nextsibling);
	}
}

template<class T>
void CSTree<T>::levelOrderTraverse()//层序遍历   
{
	levelOrder(root);
}

template<class T>
void CSTree<T>::levelOrder(CSNode<T>* p)//层次遍历以p为根节点的部分 
{//和二叉树的层序遍历一样
	//定义队列
	CSNode<T> *queue[MaxCSTreeSize];
	int front = 0;
	int rear = 0;

	CSNode<T> *current = p;
	queue[(rear++)%MaxCSTreeSize] = p;//根入队
	while(rear > front)
	{
		current = queue[(front++)%MaxCSTreeSize];//取出队顶元素
		cout<<current->data <<" ";
		if (current->firstchild!=NULL)
		{
			for (current=current->firstchild; current!=NULL; current=current->nextsibling)//孩子结点入队
			{
				queue[(rear++)%MaxCSTreeSize] = current;
			}
		}		
	}	
}

template<class T>
int CSTree<T>::heightCSTree()//树高度 
{
	return height(root);
}

template<class T>
int CSTree<T>::height(CSNode<T>* p)//计算以p为根节点的高度  
{
	int maxHeight = 0;
    if (p==NULL)//出口一
    {
        return 0;
    }
	
	if (p->firstchild == NULL)//出口二
	{
		return 1;
	}
	
	int max = 0;//max记录结点的孩子子树高度的最大值
	for (CSNode<T>* pNode=p->firstchild;pNode;pNode=pNode->nextsibling)
	{
		int temp = height(pNode);        
		if (temp > max)
		{
			max = temp;
		}
	}
	maxHeight = max+1;

	/*for (CSNode<T>* pNode=p->firstchild;pNode;pNode=pNode->nextsibling)
	{
		int temp = height(pNode)+1;        
		if (temp > maxHeight)
		{
			maxHeight = temp;
		}
	}*/
	return maxHeight;
}   

template<class T>
int CSTree<T>::widthCSTree() //树宽度 
{
	return width(root);
}

template<class T>
int  CSTree<T>::width(CSNode<T>* p)//计算以p为根子树的宽度
{//定义一般队列
	CSNode<T> *queue[MaxCSTreeSize];
	int front = 0;
	int rear = 0;

	CSNode<T> *current;
	int temWidth = 0;
	int maxWidth = 0;
	int last = 0;//记录每层最后一个元素的位置下标
	if (p!=NULL)
	{
		queue[rear] = p;//根入队列 rear指向最后一个元素
		while(last >= front)
		{
           current = queue[front++];//出队列
           temWidth++;//记录本层宽度           
		 
		   for (current=current->firstchild;current;current=current->nextsibling)//当前出队列元素的孩子全部入队列
		   {
			   queue[++rear] = current;
		   }

		   if (front > last)//上层出队列完毕
		   {
			   last = rear;//更新last
			   if (temWidth > maxWidth)
			   {
				   maxWidth = temWidth;//更新最大宽度
			   }
			   temWidth = 0;
		   }		   
		}
	}
	return maxWidth;
}

template<class T>
int CSTree<T>::getDegreeCSTree()//树的度--树中所有结点度的最大值
{
	return getDegree(root);
}

template<class T>
int CSTree<T>::getDegree(CSNode<T>* p)//输出树的度
{	
	int degree = 0;
	if (p==NULL)
	{
		return 0;
	}
	if (p->firstchild == NULL)
	{
		return 1;
	}
	for (CSNode<T> *pNode=p->firstchild;pNode;pNode=pNode->nextsibling)//计算p的度
	{
        degree++;
	}
	for (CSNode<T> *pNode=p->firstchild;pNode;pNode=pNode->nextsibling)//计算p的所有孩子子树的度
	{
		int temDegree = getDegree(pNode);
		if (temDegree > degree)
		{
           degree = temDegree;
		}
	}
    return degree;
}

template<class T>
int CSTree<T>::nodeCountCSTree()  //树结点个数
{
	return nodeCount(root);
}

template<class T>
int   CSTree<T>::nodeCount(CSNode<T>* p)//计算以p为根节点的结点个数  
{
	int count = 0;
	if (p == NULL)
	{
		return 0;
	}
	if (p->firstchild == NULL)
	{
		return 1;
	}
	for (CSNode<T>* pNode=p->firstchild;pNode;pNode=pNode->nextsibling)
	{
        count += nodeCount(pNode);
	}	
	return count+1;
}

template<class T>
int CSTree<T>::LeavesCountCSTree()//树叶子个数  
{
	return leavesCount(root);
}

template<class T>
int CSTree<T>::leavesCount(CSNode<T>* p)//计算以p为根节点的叶子个数  
{
	int leavecount = 0;
    if (p==NULL)
    {
		return 0;
    }
	if (p->firstchild == NULL)
	{
		return 1;
	}
	for (CSNode<T>* pNode=p->firstchild;pNode;pNode=pNode->nextsibling)
	{
        leavecount += leavesCount(pNode);
	}
	return leavecount;
}

template<class T>
int CSTree<T>::nodeLevelCSTree(T item)//结点item在的层次
{	
	int nlevel = 0;
	nodeLevel(item,root,1,nlevel);
	return nlevel;
}

template<class T>
void  CSTree<T>::nodeLevel(T item,CSNode<T>* p,int level,int& nlevel)//计算以p为根节点的中item所在层次,如有多个元素,则遇到第一个则返回(离根最近),如果没有出现,则返回0   
{//level记录当前已经查到第几层
   if (p==NULL)
   {
	   return;
   }
   //if (nlevel)//nlevel不为0,表示已经找到   此步需要吗?经检验不需要
   //{
	  // return;
   //}
   if (p->data == item)
   {
	   nlevel = level;
	   return;
   }
   for (CSNode<T> *pNode=p->firstchild;pNode;pNode=pNode->nextsibling)
   {
	   nodeLevel(item,pNode,level+1,nlevel);
   }
}

template<class T>
int CSTree<T>::getChildrenCount(const CSNode<T>* p)const//返回结点孩子个数
{
	int count = 0;
	if (p!=NULL)
	{
		if (p->firstchild == NULL)
		{
			return 0;
		}
		else
		{
			for (CSNode<T> *pNode=p->firstchild;pNode;pNode=pNode->nextsibling)
			{
                count++;
			}
		}
	}
	return count;
}

template<class T>
void  CSTree<T>::getAllParentCSTree(T item)const//找item的所有祖先  
{
	CSNode<T> *path[MaxCSTreeSize];
	int len = 0;
	bool isFind = false;
	getAllParent(item,root,path,len,isFind);
	cout<<item<<"的所有祖先:";
	for (int i=0;i<len;i++)
	{
		cout<<path[i]->data<<" ";
	}
	cout<<endl;
}

/*思想: 
使用一个数组保存双亲结点 
双亲放入数组,之后当处理检查完自己和左子树的时候,如果没找到,则这个结点就不会再是其双亲结点,直接把该结点移除数组。 
*/  
template<class T>
bool CSTree<T>::getAllParent(T item,CSNode<T>* p,CSNode<T>* path[MaxCSTreeSize],int& len,bool& isFind)const//找item的所有祖先,seat表示最后一个父亲的下标 
{//好好考虑,与二叉树比较
     if (isFind)
     {
		 return isFind;
     }
	 if (p==NULL)
	 {
		 return false;
	 }
	 if (p->data == item)
	 {
		 isFind = true;
		 return isFind;
	 }
	 else
	 {
		 path[len++] = p;//没有找到,将访问的结点放入path数组中,有待剔除一些结点
		 getAllParent(item,p->firstchild,path,len,isFind);
		 if (!isFind)
		 {
			 len = len-1;
			 getAllParent(item,p->nextsibling,path,len,isFind);
		 }
	 }
	 return isFind;
}

template<class T>
void  CSTree<T>::longPathCSNode()//输出从每个叶子结点到根结点的最长路径 ----- 未实现
{
	int len = 0;
	int maxlen = 0;
	CSNode<T> *longNode;
	longPath(root,len,maxlen,longNode);
}

template<class T>
void  CSTree<T>::longPath(CSNode<T>* p,int len,int& maxLen,CSNode<T>*& longNode)//输出从每个叶子结点到根结点的最长路径    
{//思想:
  //未实现
}

template<class T>
bool  CSTree<T>::findCSNode(const T item,CSNode<T>*& ret)const //查找结点 
{
	bool isFind = false;	
	find(root,item,isFind,ret);
	return isFind;
}

template<class T>
bool  CSTree<T>::find(CSNode<T>*p,const T item,bool& isFind,CSNode<T>*& cur)const//在p指向的树中,返回值为item的指针  
{
	if (isFind)//出口一
	{
		return isFind;
	}
	if (p==NULL)//出口二
	{
		cur = NULL;
		return isFind;
	}
	if (p->data == item)//出口三
	{
		cur = p;
		isFind = true;
		return isFind;
	}
	else
	{
		for (CSNode<T> *pNode=p->firstchild;pNode;pNode=pNode->nextsibling)
		{
			find(pNode,item,isFind,cur);
			if (isFind)//找到即返回
			{
				return isFind;
			}
		}
	}
	return isFind;
}

template<class T>
bool  CSTree<T>::getParentCSTree(const T item,CSNode<T>*& ret)const//查找结点item的父亲结点
{
	bool isFind = false;
	bool isFirst = true;	
	getParent(root,item,isFind,isFirst,ret);
	return isFind;
}

template<class T>
bool  CSTree<T>::getParent(CSNode<T>*p,const T item,bool& isFind,bool& isFirst,CSNode<T>*& ret)const
{//需要好好理解
   if (isFind)
   {
	   return isFind;
   }
   if (p==NULL)
   {
	   return false;
   }
   if (p->data == item)
   {
	   if (p == root)
	   {
		   cout<<"该元素是根结点,没有父亲!"<<endl;
		   isFind = false;
		   return isFind;
	   }
	   else
	   {
		   isFind = true;//此处不能给ret赋值,只能在递归出去后才能继续得到父亲的指针		   
		   return isFind;
	   }
   }
   for (CSNode<T> *pNode=p->firstchild;pNode;pNode=pNode->nextsibling)
   {
	   getParent(pNode,item,isFind,isFirst,ret);
	   if (isFind&&isFirst)
		   //检查递归回来的结果,如果找到,就为ret赋值,因为递归在回退的时候,isFind仍也是true,
		   //不引入isFirst就还会对结点ret赋值,即一路回退一路赋值。
		   //如果要避免这种情况,则需要引入这个变量,只有第一次出现这个情况的时候才为其赋值 
	   {
		   isFirst = false;		   
		   ret = p;
		   return isFind;
	   }
	 
   }
   return isFind;
}

template<class T>
bool  CSTree<T>::getleftChild(const CSNode<T>* p,CSNode<T>*& ret) const   //返回最左边的兄弟
{
	if (p==NULL)
	{
		return false;
	}
	else
	{
		if (getParentCSTree(p->data,ret))
		{
			ret = ret->firstchild;
			return true;
		}
		else
		{
			return false;
		}
	}
}

template<class T>
bool  CSTree<T>::getrightSibling(const CSNode<T>* p,CSNode<T>*& ret) const //返回最右边的兄弟
{
	if (p==NULL)
	{
		return false;
	}
	else
	{
		if (getParentCSTree(p->data,ret))
		{
			CSNode<T> *node = ret->firstchild;
			while(node->nextsibling)
			{
				node = node->nextsibling;
			}
			ret = node;
			return true;
		}
		else
		{
			return false;
		}
	}
}

template<class T>
bool  CSTree<T>::getAllSibling(const T item) const //输出所有兄弟
{
	bool isFind = false;
	CSNode<T> *ret = NULL;
	isFind = getParentCSTree(item,ret);
	if (!isFind)
	{
		return false;
	}
	else
	{
		isFind = false;
		cout<<item<<"的所有兄弟:";
		for (CSNode<T> *pNode=ret->firstchild;pNode;pNode=pNode->nextsibling)
		{
			if (pNode->data != item)
			{
				isFind = true;
				cout<<pNode->data<<" ";
			}
		}
		cout<<endl;
		return isFind;
	}
	
}

template<class T>
bool  CSTree<T>::getAllChildren(T item)//输出所有的孩子
{
	CSNode<T> *ret = NULL;
	bool isFind = false;
	findCSNode(item,ret);
	
	cout<<item<<"的所有孩子:";
	for(CSNode<T> *pNode=ret->firstchild;pNode;pNode=pNode->nextsibling)
	{
		isFind = true;
        cout<<pNode->data<<" ";
	}
	cout<<endl;
	
	return isFind;
}

int _tmain(int argc, _TCHAR* argv[])
{
	CSTree<char> tree;
	tree.createCSTree();
	cout<<"树的先序遍历:";
	tree.preOrderTraverse();
	cout<<endl;
	cout<<"树的后序遍历:";
	tree.postOrderTraverse();
	cout<<endl;
    cout<<"树的层序遍历:";
	tree.levelOrderTraverse();
	cout<<endl;
	cout<<"树的高度:"<<tree.heightCSTree()<<endl;
	cout<<"树的宽度:"<<tree.widthCSTree()<<endl;
    cout<<"树的结点个数:"<<tree.nodeCountCSTree()<<endl;
	cout<<"树的叶子结点的个数:"<<tree.LeavesCountCSTree()<<endl;	
	cout<<"树的度:"<<tree.getDegreeCSTree()<<endl;	
    cout<<"F在树中的层数:"<<tree.nodeLevelCSTree('F')<<endl;	
	tree.getAllParentCSTree('K');
	cout<<endl;
	CSNode<char>* ret;
    if ( tree.findCSNode('H',ret))
    {
		cout<<ret->data<<"的父亲结点:";
    }
	CSNode<char>* parent;
    tree.getParentCSTree(ret->data,parent);
	cout<<parent->data<<endl;
	
	system("pause");
	return 0;
}



 

评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值