线索二叉树的中序遍历

#include<iostream>
#include<vector>
using namespace std;
typedef enum{Link,Thread}PointTag;	//Link==0:指针,Thread==1:线索

template<class T>
class BiTrNode{
	template<class T> friend class BiTrTree;
private:
	T data;
	BiTrNode *lchild,*rchild;		//左右孩子指针
	PointTag ltag,rtag;				//左右标志
};
 
template<class T>
class BiTrTree
{
public:
	//BiTrTree<T>():elem={};
	void InputBiTrNode();							   //输入构成数的结点元素,‘#’表示空串  
    void Pre_CreateBiTrTree(BiTrNode<T> *&TT);			   //先序构造二叉树
	void InThreading(BiTrNode<T> *p);	   //中序遍历二叉树
	void InOrderThreading(BiTrNode<T> *&Thrt,BiTrNode<T> *TT);//中序遍历二叉树T,将其中序线索化,Thrt指向头结点
	void InOrderTraverse_Thr(BiTrNode<T> *TT);			   //中序遍历二叉线索树
	void visit(T data);								   //输出结点元素
private:  
    vector<T> elem;  
	BiTrNode<T> *pre;
};

template<class T>
void BiTrTree<T>::InputBiTrNode()  
{  
    T ch;  
    cout<<"!!!注意:(1)'#'表示空结点;(2)请在输入的字符串末尾加0,作为输入结束的标志。"<<endl;  
    while(cin>>ch&&ch!='0')  
    {  
        elem.push_back(ch); //在容器中加入结点元素  
    }//while  
}//InputBiTrNode

template<class T>
void BiTrTree<T>::Pre_CreateBiTrTree(BiTrNode<T> *&TT)  
{                               
    vector<T>::iterator it=elem.begin();   //迭代器it指向elem的开头  
    if(it!=elem.end())  
    {  
        if(*it=='#')//字符为空格,表示结点不存在  
        {  
            TT=NULL;  
            elem.erase(it); //删除迭代器it指向的elem中的元素,作用是依次删除elem的第一个元素  
        }//if  
        else  
        {  
            if(!(TT=new BiTrNode<T>))  
                exit(-1);  
            TT->data=*it;     //生成根结点  
            elem.erase(it); //删除迭代器it指向的elem中的元素,作用是依次删除elem的第一个元素  
            Pre_CreateBiTrTree(TT->lchild);    //构造左子树  
            Pre_CreateBiTrTree(TT->rchild); //构造右子树  
        }//else  
    }//if  
    else    //此时elem为空,使此时T=NULL;,即结束最初的T的结点的赋值  
        TT=NULL;   
}//Pre_CreateBiTrTree  

template<class T>
void BiTrTree<T>::InThreading(BiTrNode<T> *p)
{
	BiTrNode<T> *pt=pre;	//用p保存pre最初的值Thrt
	if(p)
	{
		InThreading(p->lchild);	//左子树线索化
		if(!(p->lchild))
		{
			p->ltag=Thread;p->lchild=pre;	//前驱线索
		}//if
		else					//左子树不为空,则左孩子标记为指针
			p->ltag=Link;
		if(!(pre->rchild))		
		{
			pre->rtag=Thread;pre->rchild=p;	//后继线索
		}//if
		else					//右结点指针不为空,则二叉树T中的结点右结点标志设置为指针Link型
		{
			if(pre!=pt)		//pre是二叉树T中的结点(不带头结点Thrt的二叉树)
				pre->rtag=Link;
		}//else
		pre=p;								//保持pre指向p的前驱
		InThreading(p->rchild);				//右子树线索化
	}//else
}//InOrderThreading

template<class T>
void BiTrTree<T>::InOrderThreading(BiTrNode<T> *&Thrt,BiTrNode<T> *TT)
{
	//BiTrNode<T> *pre=NULL;
	if(!(Thrt=new BiTrNode<T>))
		exit(-1);
	Thrt->ltag=Link;Thrt->data=0;Thrt->rtag=Thread;	//建立头结点,左标志为指针,右标志为线索
	Thrt->rchild=Thrt;					//右指针回指,指向自己实现二叉链表的循环操作if
	if(!TT)
		Thrt->lchild=Thrt;				//若二叉树为空,则左指针回指
	else
	{
		Thrt->lchild=TT;pre=Thrt;
		InThreading(TT);					//中序遍历进行中序线索化
		pre->rchild=Thrt;pre->rtag=Thread;	//最后一个结点线索化
		Thrt->rchild;
	}//else
}//InOrderThreading

template<class T>
void BiTrTree<T>::InOrderTraverse_Thr(BiTrNode<T> *TT)
{
	BiTrNode<T> *p=NULL;
	p=TT->lchild;
	while(p!=TT)
	{
		while(p->ltag==Link)	//找到二叉树左子树最左端的结点,即中序遍历的第一个结点
		{
			p=p->lchild;
		}//while
		visit(p->data);			//访问其左子树为空的结点
		while(p->rtag==Thread&&p->rchild!=TT) 
		{									 
			p=p->rchild;					 
			visit(p->data);					 
		}//
		/*假设没有进行while循环,则该结点无左孩子有右孩子,由于已被访问,则下一步就是访问其右结点 */
		/*假设执行了while循环,此时p不满足while条件,说明p有右孩子,以p为根节点,既然p被访问,则中*/
		/*序遍历剩下遍历其右子树                                                                  */
		p=p->rchild;
	}//while
}//InOrderTraverse_Thr

template<class T>
void BiTrTree<T>::visit(T data)
{
	cout<<data;
}//visit

void main()
{
	BiTrNode<char> *TT,*Thrt;
	BiTrTree<char>  BTT;
	BTT.InputBiTrNode();
	BTT.Pre_CreateBiTrTree(TT);
	BTT.InOrderThreading(Thrt,TT);
	cout<<"\n"<<"中序遍历线索二叉树:"<<endl;
	BTT.InOrderTraverse_Thr(Thrt);
}//mian


线索二叉树的中序遍历_第1张图片

你可能感兴趣的:(中序遍历,线索二叉树)