二叉树——从建立到销毁

目录

结构体和类定义

一、二叉树建立

前序遍历建立二叉树

二、遍历

2.1前序遍历

2.2中序遍历

2.3后序遍历

2.4层次遍历

三、求结点

3.1求父结点

3.2求左子结点、右子结点

四、求高度、深度、判空等

4.1高度

4.2结点个数

4.3判空

4.4结点是否存在

4.5结点数据

4.6销毁二叉树

五、主函数

六、总代码

七、总结


前言

个人认为二叉树的核心是递归,绝大部分的操作,都可以使用递归来实现。

主要操作

结构体和类定义

template <class T>
struct BinTreeNode{
	T data;
	BinTreeNode *leftChild,*rightChild;
	BinTreeNode():leftChild(NULL),rightChild(NULL){}
	BinTreeNode(T x,BinTreeNode<T> *l=NULL,BinTreeNode<T> *r=NULL)
	:data(x),leftChild(l),rightChild(r){}
};

//类定义 
//对象: 结点的有限集合, 二叉树是有序树
template <class T>
class BinaryTree {

public:
     //构造函数
     BinaryTree ():root(NULL){}			
     BinaryTree(T value):RefValue(value),root(NULL){}
     BinaryTree(BinaryTree<T>& s);
     ~BinaryTree(){destroy(root);}
	 BinaryTree (BinTreeNode<T> *lch,BinTreeNode<T> *rch, T item);
     //构造函数, 以item为根, lch和rch为左、右子


     //树构造一棵二叉树
	 //BinTreeNode<T> *createpretree(int l,int i,string &a);
	 void CreatTree(BinTreeNode<T> *& root);

    //高度、深度、判空、取结点
	 int Height (BinTreeNode<T> * root);//求树深度或高度{return Height(root);}
	 int Size (BinTreeNode<T> * root);//求树中结点个数{return Size(root);}
     bool IsEmpty (){return (root==NULL)?true:false;};		//判二叉树空否? 
     bool Find (T& item,BinTreeNode<T> * root);		//判断item是否在树中
     BinTreeNode<T> *getData(T& item,BinTreeNode<T> * root);	//取得结点数据
	 
     //求结点
     BinTreeNode<T> *Parent (BinTreeNode <T> *subTree,BinTreeNode<T> *t); 
	 //求结点 t 的双亲{return (root==NULL||root==t)?NULL:Parent(root,t);}					
     BinTreeNode<T> *LeftChild (BinTreeNode<T> *t)//求结点 t 的左子女
     {return (t!=NULL)?t->leftChild:NULL;}       				
     BinTreeNode<T> *RightChild (BinTreeNode<T> *t)//求结点 t 的右子女
	 {return (t!=NULL)?t->rightChild:NULL;}
	 
     
     //遍历
	 BinTreeNode<T> *getRoot (){return root;}	//取根
	 BinTreeNode<T> *CopyTree( BinTreeNode<T> *orignode); 
	void preOrder ( BinTreeNode<T> *root);//前序遍历 	
           
	 void inOrder ( BinTreeNode<T> * root);//中序遍历 
		
	 void postOrder ( BinTreeNode<T> * root);//后序遍历 
		
	 void levelOrder (BinTreeNode<T> * root);//层次序遍历 
		

	protected:
		BinTreeNode<T> * root;
		T RefValue;
		void destroy (BinTreeNode<T> * subTree);

};

一、二叉树建立

前序遍历建立二叉树

空传入

template <class T>
void BinaryTree<T>::CreatTree(BinTreeNode<T> *& root) 
{  T item;
   cin>>item;
   if(item!=RefValue)
   {   root=new BinTreeNode<T>(item);
       if(root ==NULL)
        {  cerr<<"分配结点失败!\n";  exit(1);  }
       CreatTree(root->leftChild);
       CreatTree(root->rightChild);
   }
   else root=NULL;
}

传引用

template <class T>
BinTreeNode<T> * BinaryTree<T>::createpretree(int l,int i,string &a)
{//l为数组a的长度,i为数组下标
	BinTreeNode<T> *root;
	if(l==0||a[i]=='#'||i==l)root=NULL;
	else
	{
		root=new BinTreeNode<T>(a[i++]);
		root->leftChild=createpretree(l,i,a);
		root->rightChild=createpretree(l,++i,a);
	}
	return root; 
}

二、遍历

2.1前序遍历

template <class T>
void BinaryTree<T>::preOrder(BinTreeNode<T> * root)   
{   
     if (root != NULL)
      {
    	cout<<root->data<<" ";        //先序访问根结点
	    preOrder(root->leftChild);     //遍历左子树
	    preOrder(root->rightChild);   //先序遍历右子树
       }
}

2.2中序遍历

template <class T>
void BinaryTree<T>::inOrder(BinTreeNode<T> * root)   
{   
     if (root != NULL)
      {
	  	inOrder(root->leftChild);      //中序遍历左子树
        cout<<root->data<<" ";       //访问根结点
	    inOrder(root->rightChild);   //中序遍历右子树
       }
}

2.3后序遍历

template <class T>
void BinaryTree<T>::postOrder(BinTreeNode<T> * root)   
{   
     if (root != NULL)
      {	
	    postOrder(root->leftChild);     //后序遍历左子树
	    postOrder(root->rightChild);   //遍历右子树
        cout<<root->data<<" ";         //后序访问根结点
       }
}

2.4层次遍历

template <class T>
void BinaryTree<T>::levelOrder(BinTreeNode<T> *root)
{    if (root == NULL) return;
     queue<BinTreeNode<T> * > Q;
     BinTreeNode<T> *p;   
     Q.push(root); 	//根结点入队列
     while (!Q.empty()) 
     {   
         p=Q.front();
          cout<<(Q.front())->data<<" ";  //输出出队结点的数据
		  Q.pop();             //队头结点出队
          if (p->leftChild != NULL)  //若出队结点有左孩子
              { Q.push(p->leftChild);}  //左孩子入队列p=p->leftChild;
          if (p->rightChild != NULL) 
	     {Q.push(p->rightChild);
		 }
     }     
}

有一种方法是使用自定义的队列,思路大致和上面相同,但在此不写怎么麻烦的方法了。

三、求结点

3.1求父结点

template <class T>
BinTreeNode<T> *BinaryTree<T>::
Parent (BinTreeNode <T> *subTree,BinTreeNode <T> *t)
{
     if (subTree == NULL) return NULL;
     if (subTree->leftChild == t ||subTree->rightChild == t)
	  return subTree;	//找到, 返回父结点地址
     BinTreeNode <T> *p;
     if ((p = Parent (subTree->leftChild, t)) != NULL)  
         return p;	         //递归在左子树中搜索
         else return Parent (subTree->rightChild, t);
 				         //递归在右子树中搜索
}

3.2求左子结点、右子结点

    //定义在类中
     BinTreeNode<T> *LeftChild (BinTreeNode<T> *t)
     {return (t!=NULL)?t->leftChild:NULL;}//求结点 t 的左子女
            				
     BinTreeNode<T> *RightChild (BinTreeNode<T> *t)
	 {return (t!=NULL)?t->rightChild:NULL;}	//求结点 t 的右子女

四、求高度、深度、判空等

4.1高度

template <class T>
int  BinaryTree<T>::Height(BinTreeNode<T> * root) 
{
     if (root == NULL) return 0;	
     else 
	 {     
	  int i = Height(root->leftChild);
      int j = Height(root->rightChild);
	  return (i < j) ? j+1 : i+1; 
	}
}

4.2结点个数

template <class T>
int BinaryTree<T>::Size(BinTreeNode<T> * root)  
{
    if (root == NULL) return 0;	  //空树
    else 
       return 1+Size(root->leftChild)+Size(root->rightChild);
}

4.3判空

//在类中
bool IsEmpty (){return (root==NULL)?true:false;};

4.4结点是否存在

template<class T>
bool BinaryTree<T>::Find (T& item,BinTreeNode<T> * root)
{
	if(this->getData(item,root)==NULL)return false;
	else return true;
} 

4.5结点数据

template<class T>
BinTreeNode<T> *BinaryTree<T>::getData(T& item,BinTreeNode<T> * root)
{
	if(root==NULL)return NULL;
	if(root->data==item)return root;
	return getData(item,root->leftChild)!=NULL?getData(item,root->leftChild):getData(item,root->rightChild);
  
} 

4.6销毁二叉树

template<class T>
void BinaryTree<T>::destroy (BinTreeNode<T>* subTree) {
//私有函数: 后序遍历删除根为subTree的子树;
     if (subTree != NULL) {
          destroy (subTree->leftChild);     //删除左子树
 	      destroy (subTree->rightChild);   //删除右子树
 	      delete subTree; 			 //删除根结点
	 }
}

五、主函数

int main()
{
	
	char ch;
	cout<<"输入结束标志:";
	cin>>ch;
    BinaryTree<char> t(ch);
	BinTreeNode<char>* head=t.getRoot();
	t.CreatTree(head);
	return 0;
 } 

六、总代码

#include<bits/stdc++.h>
using namespace std;
template <class T>
struct BinTreeNode{
	T data;
	BinTreeNode *leftChild,*rightChild;
	BinTreeNode():leftChild(NULL),rightChild(NULL){}
	BinTreeNode(T x,BinTreeNode<T> *l=NULL,BinTreeNode<T> *r=NULL)
	:data(x),leftChild(l),rightChild(r){}
};

//类定义 
//对象: 结点的有限集合, 二叉树是有序树
template <class T>
class BinaryTree {

public:
     BinaryTree ():root(NULL){}			//构造函数
     BinaryTree(T value):RefValue(value),root(NULL){}
     BinaryTree(BinaryTree<T>& s);
     ~BinaryTree(){destroy(root);}
	 BinaryTree (BinTreeNode<T> *lch,BinTreeNode<T> *rch, T item);
	    //构造函数, 以item为根, lch和rch为左、右子
        //树构造一棵二叉树
		//BinTreeNode<T> *createpretree(int l,int i,string &a);
	void CreatTree(BinTreeNode<T> *& root);
	 int Height (BinTreeNode<T> * root);//求树深度或高度{return Height(root);}
	 int Size (BinTreeNode<T> * root);//求树中结点个数{return Size(root);}
     bool IsEmpty (){return (root==NULL)?true:false;};		//判二叉树空否? 
	 
     BinTreeNode<T> *Parent (BinTreeNode <T> *subTree,BinTreeNode<T> *t); 
	 //求结点 t 的双亲{return (root==NULL||root==t)?NULL:Parent(root,t);}
						
     BinTreeNode<T> *LeftChild (BinTreeNode<T> *t)
     {return (t!=NULL)?t->leftChild:NULL;}//求结点 t 的左子女
            				
     BinTreeNode<T> *RightChild (BinTreeNode<T> *t)
	 {return (t!=NULL)?t->rightChild:NULL;}	//求结点 t 的右子女
	 
     //bool Insert (const T& item);		//在树中插入新元素
     //bool Remove (T item);	//在树中删除元素
     bool Find (T& item,BinTreeNode<T> * root);		//判断item是否在树中
     BinTreeNode<T> *getData(T& item,BinTreeNode<T> * root);	//取得结点数据
	 BinTreeNode<T> *getRoot (){return root;}	//取根
	 BinTreeNode<T> *CopyTree( BinTreeNode<T> *orignode); 
	void preOrder ( BinTreeNode<T> *root);//前序遍历 	
           
	 void inOrder ( BinTreeNode<T> * root);//中序遍历 
		
	 void postOrder ( BinTreeNode<T> * root);//后序遍历 
		
	 void levelOrder (BinTreeNode<T> * root);//层次序遍历 
		

	protected:
		BinTreeNode<T> * root;
		T RefValue;
		void destroy (BinTreeNode<T> * subTree);

};

//template <class T>
//BinaryTree::BinaryTree()
/*
//建立二叉树 
template <class T>
BinTreeNode<T> * BinaryTree<T>::createpretree(int l,int i,string &a)
{
	BinTreeNode<T> *root;
	if(l==0||a[i]=='#'||i==l)root=NULL;
	else
	{
		root=new BinTreeNode<T>(a[i++]);
		root->leftChild=createpretree(l,i,a);
		root->rightChild=createpretree(l,++i,a);
	}
	return root; 
}*/

//先序遍历创建一棵二叉树
template <class T>
void BinaryTree<T>::CreatTree(BinTreeNode<T> *& root) 
{  T item;
   cin>>item;
   if(item!=RefValue)
   {   root=new BinTreeNode<T>(item);
       if(root ==NULL)
        {  cerr<<"分配结点失败!\n";  exit(1);  }
       CreatTree(root->leftChild);
       CreatTree(root->rightChild);
   }
   else root=NULL;
}

//遍历
//先序遍历
template <class T>
void BinaryTree<T>::preOrder(BinTreeNode<T> * root)   
{   
     if (root != NULL)
      {	cout<<root->data<<" ";        //先序访问根结点
	preOrder(root->leftChild);     //遍历左子树
	preOrder(root->rightChild);   //先序遍历右子树
       }
}

//中序遍历
template <class T>
void BinaryTree<T>::inOrder(BinTreeNode<T> * root)   
{   
     if (root != NULL)
      {
	  	inOrder(root->leftChild);      //中序遍历左子树
        cout<<root->data<<" ";       //访问根结点
	    inOrder(root->rightChild);   //中序遍历右子树
       }
}

//后序遍历
template <class T>
void BinaryTree<T>::postOrder(BinTreeNode<T> * root)   
{   
     if (root != NULL)
      {	
	    postOrder(root->leftChild);     //后序遍历左子树
	    postOrder(root->rightChild);   //遍历右子树
        cout<<root->data<<" ";         //后序访问根结点
       }
}

//层次遍历
template <class T>
void BinaryTree<T>::levelOrder(BinTreeNode<T> *root)
{    if (root == NULL) return;
     queue<BinTreeNode<T> * > Q;
     BinTreeNode<T> *p;   
     Q.push(root); 	//根结点入队列
     while (!Q.empty()) 
     {   
         p=Q.front();
          cout<<(Q.front())->data<<" ";  //输出出队结点的数据
		  Q.pop();             //队头结点出队
          if (p->leftChild != NULL)  //若出队结点有左孩子
              { Q.push(p->leftChild);}  //左孩子入队列p=p->leftChild;
          if (p->rightChild != NULL) 
	     {Q.push(p->rightChild);
		 }
     }     
}
//结点个数 
template <class T>
int BinaryTree<T>::Size(BinTreeNode<T> * root)  
{
    if (root == NULL) return 0;	  //空树
    else 
       return 1+Size(root->leftChild)+Size(root->rightChild);
}

//空树高度为0
template <class T>
int  BinaryTree<T>::Height(BinTreeNode<T> * root) 
{
     if (root == NULL) return 0;	
     else 
	 {     
	  int i = Height(root->leftChild);
      int j = Height(root->rightChild);
	  return (i < j) ? j+1 : i+1; 
	}
}

//二叉树复制 
template <class T>
BinTreeNode<T> * BinaryTree<T>::CopyTree( BinTreeNode<T> *orignode) 
{
    if(orignode==NULL)  return NULL;
    BinTreeNode<T> *temp=new BinTreeNode<T>;
    temp->data=orignode->data;
    temp->leftChild=CopyTree(orignode->leftChild);
    temp->rightChild=CopyTree(orignode->rightChild);
    return temp;
}

//寻找双亲结点 
template <class T>
BinTreeNode<T> *BinaryTree<T>::
Parent (BinTreeNode <T> *subTree,BinTreeNode <T> *t)
{
     if (subTree == NULL) return NULL;
     if (subTree->leftChild == t ||subTree->rightChild == t)
	  return subTree;	//找到, 返回父结点地址
     BinTreeNode <T> *p;
     if ((p = Parent (subTree->leftChild, t)) != NULL)  
         return p;	         //递归在左子树中搜索
         else return Parent (subTree->rightChild, t);
 				         //递归在右子树中搜索
}


//查找结点数据 
template<class T>
BinTreeNode<T> *BinaryTree<T>::getData(T& item,BinTreeNode<T> * root)
{
	if(root==NULL)return NULL;
	if(root->data==item)return root;
	return getData(item,root->leftChild)!=NULL?getData(item,root->leftChild):getData(item,root->rightChild);
  
} 

//查找结点是否在树中
template<class T>
bool BinaryTree<T>::Find (T& item,BinTreeNode<T> * root)
{
	if(this->getData(item,root)==NULL)return false;
	else return true; 
} 


//销毁二叉树 
template<class T>
void BinaryTree<T>::destroy (BinTreeNode<T>* subTree) {
//私有函数: 后序遍历删除根为subTree的子树;
     if (subTree != NULL) {
          destroy (subTree->leftChild);     //删除左子树
 	      destroy (subTree->rightChild);   //删除右子树
 	      delete subTree; 			 //删除根结点
	 }
}


//BinTreeNode<char> *root;
int main()
{
	
	char ch;
	cout<<"输入结束标志:";
	 cin>>ch;
    BinaryTree<char> t(ch);
//	 cout<<"输入遍历序列:";
//	string a;
//	cin>>a;
//	int l=a.length();
//	int i=0;	
	BinTreeNode<char>* head=t.getRoot();
	t.CreatTree(head);

	return 0;
 } 

七、总结

点个赞再走吧~~

  • 10
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值