二叉树的遍历

本文介绍了二叉树的遍历方法,包括递归和非递归两种方式。尽管两者时间复杂度相同为O(n),但非递归算法在空间复杂度上具有优势。代码参考自邓俊辉老师的教材。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

二叉树的遍历分为递归和非递归。渐进的时间复杂度都是O(n),非递归算法由于没有函数递归调用的开销,有比较好的空间复杂度。

代码是根据邓俊辉老师的书来写的。

代码:

//traverse a binary tree in recursive or non recursive way
#include <iostream>
#include <stack>
#include <queue>
#include <cmath>
#include <ctime>

using std::cin;
using std::cout;
using std::endl;
using std::cerr;
using std::stack;
using std::queue;

#define BinNodePosi(T) BinNode<T>*
#define IsRoot(x) (!(x).parent)
#define HasLChild(x) ((x).lc)
#define HasRChild(x) ((x).rc)
#define IsLChild(x) (!IsRoot(x)&&(&(x)==(x).parent->lc))
#define IsRChild(x) (!IsRoot(x)&&(&(x)==(x).parent->rc))

template <typename T>
void visit(T t)
{
	cout<<t<<" "<<endl;
}

template <typename T> class BinNode
{
public:
	T data;
	BinNodePosi(T) parent;
	BinNodePosi(T) lc;
	BinNodePosi(T) rc;
	int height;
	
	BinNode():parent(NULL),lc(NULL),rc(NULL),height(0){}
	BinNode(T e,BinNodePosi(T) p=NULL,BinNodePosi(T) lc=NULL,BinNodePosi(T) rc=NULL,int h=0):
	data(e),parent(p),lc(lc),rc(rc),height(h){}

	BinNodePosi(T) succ();
	
	template <typename VST> 
	void travPost(VST &visit)
	{
		travPost_I(this,visit);
	}

	template <typename VST>
	void travPre(VST &visit)
	{
		travPre_I(this,visit);
	}

	template <typename VST>
	void travIn(VST &visit)
	{
		srand(time(NULL));
		switch(rand()%2)
		{
			case 0:
				cout<<"(use a stack)"<<endl;
				travIn_I(this,visit);
				break;
			case 1:
				cout<<"(not use a stack)"<<endl;
				travIn_II(this,visit);
				break;
			default:
				break;
		}
	}

	template <typename VST> 
	void travPost_recursion(VST &visit)
	{
		if(this==nullptr)
			return;

		lc->travPost_recursion(visit);
		rc->travPost_recursion(visit);
		visit(this->data);
	}

	template <typename VST> 
	void travPre_recursion(VST &visit)
	{
		if(this==nullptr)
			return;

		visit(this->data);
		lc->travPre_recursion(visit);
		rc->travPre_recursion(visit);
	}

	template <typename VST> 
	void travIn_recursion(VST &visit)
	{
		if(this==nullptr)
			return;

		lc->travIn_recursion(visit);
		visit(this->data);
		rc->travIn_recursion(visit);
	}

	template <typename VST>
	void travLevel(VST &visit,queue<BinNodePosi(T)> &Q)
	{
		visit(this->data);
		if(lc)
			Q.push(lc);
		if(rc)
			Q.push(rc);
	}
	
	BinNodePosi(T) insertAsLC(T const &);
	BinNodePosi(T) insertAsRC(T const &);
	
};

template <typename T>
BinNodePosi(T) BinNode<T>::insertAsLC(T const &e)
{
	lc=new BinNode(e,this);
	return lc;
}

template <typename T>
BinNodePosi(T) BinNode<T>::insertAsRC(T const &e)
{
	rc=new BinNode(e,this);
	return rc;
}

template <typename T>
BinNodePosi(T) BinNode<T>::succ()
{
	BinNodePosi(T) s=this;
	if(rc)
	{
		s=rc;
		while(HasLChild(*s))
			s=s->lc;
	}
	else
	{
		while(IsRChild(*s))
			s=s->parent;
		s=s->parent;
	}
	return s;
}

template <typename T> class BinTree
{
public:
	int _size;
	BinNodePosi(T) _root;

public:
	BinTree():_size(0),_root(NULL){}
	int size() const {return _size;}
	bool empty() const {return !_root;}

	BinNodePosi(T) insertASRoot(T const &e);

	BinNodePosi(T) insertASLC(BinNodePosi(T) x,T const &);

	BinNodePosi(T) insertASRC(BinNodePosi(T) x,T const &);

	template <typename VST> 
	void travPost_recursion(VST &visit)
	{
		if(_root)
			_root->travPost_recursion(visit);
	}

	template <typename VST> 
	void travPre_recursion(VST &visit)
	{
		if(_root)
			_root->travPre_recursion(visit);
	}

	template <typename VST> 
	void travIn_recursion(VST &visit)
	{
		if(_root)
			_root->travIn_recursion(visit);
	}
	
	template <typename VST> 
	void travPost(VST &visit)
	{
		if(_root) 
			_root->travPost(visit);
	}

	template <typename VST> 
	void travPre(VST &visit)
	{
		if(_root) 
			_root->travPre(visit);
	}

	template <typename VST> 
	void travIn(VST &visit)
	{
		if(_root) 
			_root->travIn(visit);
	}

	template <typename VST>
	void travLevel(VST &visit)
	{
		queue<BinNodePosi(T)> Q;
		if(_root)
		{
			Q.push(_root);
			while(!Q.empty())
			{
				BinNodePosi(T) cur=Q.front();
				Q.pop();
				cur->travLevel(visit,Q);
			}
		}
	}
};

template <typename T>
BinNodePosi(T) BinTree<T>::insertASRoot(T const &e)
{
	_root=new BinNode<T>(e);
	_size=1;
	return _root;
}

template <typename T>
BinNodePosi(T) BinTree<T>::insertASLC(BinNodePosi(T) x,T const &e)
{
	x->insertAsLC(e);
	_size++;
	return x->lc;
}

template <typename T>
BinNodePosi(T) BinTree<T>::insertASRC(BinNodePosi(T) x,T const &e)
{
	x->insertAsRC(e);
	_size++;
	return x->rc;
}

template <typename T>
static void gotoHLVFL(stack<BinNodePosi(T)> &S)
{
	while(BinNodePosi(T) x=S.top())
	{
		if(HasLChild(*x))
		{
			if(HasRChild(*x))
				S.push(x->rc);
			S.push(x->lc);
		}
		else
			S.push(x->rc);
	}
	S.pop();
}

template <typename T,typename VST>
void travPost_I(BinNodePosi(T) x,VST &visit)
{
	stack<BinNodePosi(T)> S;
	if(x)
		S.push(x);
		
	while(!S.empty())
	{
		if(S.top()!=x->parent)
			gotoHLVFL(S);
		x=S.top();
		S.pop();
		visit(x->data);
	}
}

template <typename T,typename VST>
void visitAlongLeftPath(BinNodePosi(T) x,VST &visit,stack<BinNodePosi(T)> &S)
{
	while(x)
	{
		visit(x->data);
		if(HasRChild(*x))
			S.push(x->rc);
		x=x->lc;
	}
}

template <typename T,typename VST>
void travPre_I(BinNodePosi(T) x,VST &visit)
{
	stack<BinNodePosi(T)> S;
	S.push(x);
	while(!S.empty())
	{
		visitAlongLeftPath(x,visit,S);
		x=S.top();
		S.pop();
	}

}

template <typename T>
void goAlongLeftPath(BinNodePosi(T) x,stack<BinNodePosi(T)> &S)
{
	while(x)
	{
		S.push(x);
		x=x->lc;
	}
}

template <typename T,typename VST>
void travIn_I(BinNodePosi(T) x,VST &visit)
{
	stack<BinNodePosi(T)> S;
	goAlongLeftPath(x,S);
	while(!S.empty())
	{
		x=S.top();
		S.pop();
		visit(x->data);
		x=x->rc;
		goAlongLeftPath(x,S);
	}
}

template <typename T,typename VST>
void travIn_II(BinNodePosi(T) x,VST &visit)
{
	bool backtrack=false;
	while(true)
	{
		if(!backtrack&&HasLChild(*x))
			x=x->lc;
		else
		{
			visit(x->data);
			if(HasRChild(*x))
			{
				x=x->rc;
				backtrack=false;
			}
			else
			{
				if(!(x=x->succ()))
					break;
				backtrack=true;
			}
		}
	}
}


int main()
{
	BinTree<int> tree;

	tree.insertASRoot(1);
	BinNodePosi(int) l11=tree.insertASLC(tree._root,2);
	BinNodePosi(int) l12=tree.insertASRC(tree._root,3);
	BinNodePosi(int) l21=tree.insertASRC(l11,4);
	BinNodePosi(int) l31=tree.insertASLC(l21,5);
	BinNodePosi(int) l32=tree.insertASRC(l21,6);
	BinNodePosi(int) l41=tree.insertASRC(l32,7);

	cout<<"No recursion post order:"<<endl;
	tree.travPost(visit<int>);

	cout<<"recursion post order:"<<endl;
	tree.travPost_recursion(visit<int>);
	
	cout<<"No recursion pre order:"<<endl;
	tree.travPre(visit<int>);

	cout<<"recursion pre order:"<<endl;
	tree.travPre_recursion(visit<int>);

	cout<<"No recursion in order:"<<endl;
	tree.travIn(visit<int>);

	cout<<"recursion in order:"<<endl;
	tree.travIn_recursion(visit<int>);

	cout<<"level order:"<<endl;
	tree.travLevel(visit<int>);

	return 0;
}

运行结果:




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值