[小记]二叉树的先序中序后序递归非递归遍历,层次遍历和完全二叉树的判断[4.24更新]

// BinaryTree.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
/************************************************************************/
/* 二叉树的递归,非递归的前序,中序和后序遍历
/* 二叉树的层次遍历,和完全二叉树的判断
/************************************************************************/

#include 
#include 
#include 
#include 

using namespace std;

template
struct tree_node{
	T value;
	tree_node* left;
	tree_node* right;
	tree_node():value(),left(0),right(0){}
	tree_node(tree_node* l, tree_node* r):value(),left(l),right(r){}
};

template
struct visit{
	void operator()(const T& t){cout<
void PreOrderTraverse_Rec(tree_node* root,F func)
{
	if(root)
	{
		func(root->value); //访问节点
		PreOrderTraverse_Rec(root->left,func);
		PreOrderTraverse_Rec(root->right,func);
	}
}

//递归,中序遍历
template
void InOrderTraverse_Rec(tree_node* root, F func)
{
	if(root)
	{
		InOrderTraverse_Rec(root->left,func);
		func(root->value);
		InOrderTraverse_Rec(root->right,func);
	}
}

//递归,后序遍历
template
void PostOrderTraverse_Rec(tree_node* root, F func)
{
	if(root)
	{
		PostOrderTraverse_Rec(root->left,func);
		PostOrderTraverse_Rec(root->right,func);
		func(root->value);
	}
}

//非递归,先序遍历,版本1
template
void PreOrderTraverse_Non_Rec_v1(tree_node* root, F func)
{
	typedef tree_node* node;
	stack< tree_node* > st;
	while(root || !st.empty()) //root不为空或者栈不空,则循环遍历
	{
		if (root)//root不为空,则访问此root节点
		{
			func(root->value); 
			st.push(root);
			root = root->left; //往左访问
		}else{
			node n=st.top(); //弹出栈顶,访问右子树
			root = n->right;
			st.pop();
		}
	}
}

//非递归,先序遍历,版本2(简单版本)
template
void PreOrderTraverse_Non_Rec_v2(tree_node* root, F func)
{
	if(!root) return;
	stack< tree_node* > st;
	st.push(root);
	while(!st.empty())
	{
		func(root->value);
		if(root->right)	st.push(root->right); //右子树非空,先压入右子树
		if(root->left) st.push(root->left);
		root = st.top();
		st.pop();
	}
}

//非递归,中序遍历
template
void InOrderTraverse_Non_Rec(tree_node* root, F func)
{
	stack< tree_node* > st;
	typedef tree_node* node;

	while(root || !st.empty())
	{
		while(root) //一直往左到左子树的最左边,即整棵树的最左下
		{
			st.push(root);
			root=root->left;
		}

		if(!st.empty()) //如果不空,则弹出栈顶,访问
		{
			node n = st.top();
			func(n->value);
			st.pop();
			root = n->right; //置root为右子树,然后循环到头去访问右子树
		}
	}
}

//非递归,后续遍历
template
void PostOrderTraverse_Non_Rec(tree_node* root, F func)
{
	typedef tree_node* node;
	stack st;
	node pre=0; //表示最近的前一个访问的节点

	while(root || !st.empty())
	{
		while(root) //一直往左访问
		{
			st.push(root);
			root=root->left;
		}

		//判断是否应该访问栈顶元素,注意这里需要用root访问
		root = st.top();  //这里不用判断st是否为空,因为前面已经判断过了
		//如果右节点为空(此节点无左右孩子),或者前面访问的节点是其右节点,则轮到自己访问
		if( ! root->right || root->right == pre) 
		{
			func(root->value);
			st.pop(); //弹出已经访问的栈顶
			pre = root;
			root = 0; //这里需要置root为空,因为无法继续往下继续访问,需要弹栈回溯访问节点
		}else{
			//继续访问右子树
			root = root->right; //如果有右子树,则不用弹栈,继续往下访问右子树
		}
	}

}

//层次遍历二叉树
template
void LevelTraverse(tree_node* root, F func)
{
	if(!root) return; 
	typedef tree_node* node;
	queue _q;
	_q.push(root);
	while(!_q.empty())
	{	
		node n=_q.front();
		func(n->value);
		_q.pop();
		if(n->left) _q.push(n->left);
		if(n->right) _q.push(n->right);
	}
}

//完全二叉树判断
template
bool judge(tree_node* root)
{
	if(!root) return true; //空树
	typedef tree_node* node;
	queue _q;
	_q.push(root);
	node n;
	while(!_q.empty())
	{
		n=_q.front();
		_q.pop();
		if(n->left && n->right){
			_q.push(n->left);
			_q.push(n->right);
		}else
			break; //第一个缺少左或右孩子的节点,退出循环进行判断
	}

	if(_q.empty())
		return true;
	else
	{
		if(!n->left && n->right)
			return false;
		else
		{
			if(n->left) //如果左孩子不为空,则将其节点压入队列
				_q.push(n->left);

			//对于仅左孩子为空和左右孩子均为空的情况,判断队列里剩余的节点都为叶子节点
			while(!_q.empty())
			{
				node tmp=_q.front();
				_q.pop();
				if(tmp->left || tmp->right) 
					return false;
			}
		}
	}
	return true;
}

//测试
//已知前序,中序,建树,并后序访问打印后序遍历结果,以字符表示节点
tree_node* GenTreeByPreInOrder(const string& preOrderS,const string& inOrderS)
{
	//std::cout<<"pre:"<* nd=new tree_node(0,0);
		nd->value = v;

		int idx = inOrderS.find(v);
		if (idx != string::npos)
		{
			nd->left = GenTreeByPreInOrder(preOrderS.substr(1,idx), inOrderS.substr(0,idx));
			nd->right = GenTreeByPreInOrder(preOrderS.substr(idx+1),inOrderS.substr(idx+1));
		}
		return nd;	
	}

	return 0;
}

//测试
//已知中序和后序,建树,并打印结果
tree_node* GenTreeByInPostOrder(const string& inOrderS, const string& postOrderS)
{
	//cout<* n=new tree_node(0,0);
		n->value = v;

		int idx=inOrderS.find(v);
		if(idx != string::npos)
		{
			n->left = GenTreeByInPostOrder(inOrderS.substr(0,idx),postOrderS.substr(0,idx));
			n->right= GenTreeByInPostOrder(inOrderS.substr(idx+1),postOrderS.substr(idx,postOrderS.length()-idx-1));
		}
		return n;
	}
	//一定要返回空,其实是空指针
	return 0;
}

//测试
template
void out_tree(tree_node* root)
{
	typedef visit fun;
	cout<<"\n------------\nPre-Order:recursive,non-recursive-v1,non-recursive-v2\n";
	PreOrderTraverse_Rec(root,fun());
	cout<<"\n";
	PreOrderTraverse_Non_Rec_v1(root,fun());
	cout<<"\n";
	PreOrderTraverse_Non_Rec_v2(root,fun());
	cout<<"\n------------\nIn-Order:recursive,non-recursive\n";
	InOrderTraverse_Rec(root,fun());
	cout<<"\n";
	InOrderTraverse_Non_Rec(root,fun());
	cout<<"\n------------\nPost-Order:recursive,non-recursive\n";
	PostOrderTraverse_Rec(root,visit());
	cout<<"\n";
	PostOrderTraverse_Non_Rec(root,visit());
	cout<<"\n++++++++++++++++++++++++\n";
}



int _tmain(int argc, _TCHAR* argv[])
{
	string pre("abdgcefh"),in("dgbaechf"),post("gdbehfca");

	
	cout<<"Original test: pre-order-string:"<* t1=GenTreeByPreInOrder(pre,in);
	out_tree(t1);
	tree_node* t2=GenTreeByInPostOrder(in,post);
	out_tree(t2);
	
	return 0;
}

你可能感兴趣的:(tree,class,ALL,C/C++)