二叉树的遍历

//二叉树前序遍历(递归版)
template <typename T, typename VST>//模板
void travPre_R(BinNodePosi(T) x, VST & visit)//使用函数对象
{
	if (x == nullptr) return;
	visit(x->data);
	travPre_R(x->lc, visit);
	travPre_R(x->rc, visit);
}
//二叉树中序遍历(递归版)
template <typename T, typename VST>//模板
void travIn_R(BinNodePosi(T) x, VST & visit)//使用函数对象
{
	if (x == nullptr) return;
	travPre_R(x->lc, visit);
	visit(x->data);
	travPre_R(x->rc, visit);
}
//二叉树后序遍历(递归版)
template <typename T, typename VST>//模板
void travPost_R(BinNodePosi(T) x, VST & visit)//使用函数对象
{
	if (x == nullptr) return;
	travPre_R(x->lc, visit);
	travPre_R(x->rc, visit);
	visit(x->data);
}
/*****************************二叉树前序遍历(迭代版1)**************************/
/*该方法对所有尾递归均适用*/
/*需要适用辅助栈*/
template <typename T, typename VST>//模板
void travPre_I1(BinNodePosi(T) x, VST & visit)//使用函数对象
{
	stack<BinNodePosi(T)> S;
	if (x!=nullptr) S.push(x);//根节点入栈
	while (!S.empty())
	{
		x = S.pop(); visti(x->data);
		if (x->rc != nullptr) S.push(x->rc);
		if (x->lc != nullptr) S.push(x->lc);
	}
}


/*****************************二叉树前序遍历(迭代版2)**************************/
/*需要适用辅助栈*/
template <typename T, typename VST>
static void visitAlongLeftBranch(BinNodePosi(T) x, VST & visit, Stack<BinNodePosi(T)> & S)//注意两个引用
{
	while (x != nullptr)
	{
		visit(x->data);
		if (x->rc != nullptr) S.push(x->rc);
		x = x->lc;
	}
}

template <typename T, typename VST>//模板
void travPre_I2(BinNodePosi(T) x, VST & visit)//使用函数对象
{
	Stack<BinNodePosi(T)> S;
	while (1)
	{
		visitAlongLeftBranch(x, visit, S);//访问该节点并不断深入访问左孩子,同时将右孩子不断入栈
		if (S.empty() == 1) break;
		x = S.pop();//即转向右分支
	}
}
/*二叉树中序遍历非常重要,后续的二叉搜索树需要用到*/

/*************************************二叉树中序遍历(迭代版1)**************************************/
template <typename T>
static void goAlongLeftBranch(BinNodePosi(T) x, Stack<BinNodePosi(T)> & S)
{
	while (x != nullptr) { S.push(x); x = x->lc; }
}

template <typename T, typename VST>
void travIn_I1(BinNodePosi(T) x, VST & visit)
{
	Stack<BinNodePosi(T)> S;
	while (1)
	{
		goAlongLeftBranch(x, S);//不断入栈x及其左子树
		if (S.empty()) break;
		x = S.pop(); visit(x->data);//出栈并访问
		x = x->rc;//访问完x,转向x的右子树
	}
}

/***********************二叉树中序遍历(迭代版2)*************************/
/*对迭代版1的改进*/
template <typename T, typename VST>
void travIn_I2(BinNodePosi(T) x, VST & visit)
{
	Stack<BinNodePosi(T)> S;
	while (1)
	{
		if (x != nullptr)
		{
			S.push(x);//根节点入栈
			x = x->lc;//深入遍历左子树
		}
		else if (!S.empty())
		{
			x = S.pop();
			visit(x->data);//出栈访问
			x = x->rc;//访问完,转向右子树
		}
		else break;
	}
}



/***************************二叉树的中序遍历(迭代版3)********************************/
/*该方法不需要额外的栈空间辅助,但是需要不断调用寻找直接后继的succ()函数*/
template <typename T> BinNodePosi(T) BinNode<T>::succ()//节点类的成员函数,寻找直接后继
{
	BinNodePosi(T) s = this;
	if (s->rc != nullptr)//如果有右子树,则为右子树最低层的左叶节点
	{
		s = rc;
		while (s->lc != nullptr) { s = s->lc; }
	}
	else//如果没有右子树,则不断网上溯源,直到不是右孩子的节点,其父节点即为直接后继
	{
		while (s->parent->rc == s) s = s->parent;
		s = s->parent;
	}
	return s;
}

template <typename T, typename VST>
void travIn_I3(BinNodePosi(T) x, VST & visit)
{
	bool backtrack = false;//前一步是否刚从左子树回溯
	while (1)
	{
		if (!backtrack && x->lc != nullptr)//有左子树且不是刚从左子树返回
		{
			x = x->lc;//不断寻找左子树
		}
		else//如果没有左子树,或者左子树已经访问过
		{
			visit(x->data);//访问该节点
			if (x->rc != nullptr)//访问完,并转向右子树
			{
				x = x->rc;
				backtrack = false;
			}
			else
			{
				x = x->succ();
				if (x == nullptr) break;
				backtrack = 1;
			}
		}
	}
}
/*二叉树的后序遍历(迭代版)*/
template <typename T>
static void gotoHLVFL(Stack < BinNodePosi(T) & S)//寻找第一个要访问的节点
{
	while (BinNodePosi(T) x = S.top())
	{
		if (x->lc != nullptr)
		{
			if (x->rc != nullptr) 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 != nullptr) S.push(x);
	while (!S.empty())
	{
		if (S.top() != x->parent)//栈顶不是其父节点,则必为其右兄弟节点
			gotoHLVFL(S);
		x = S.pop(); visit(x->data);
	}
}
/******************************二叉树的层次遍历*******************************/
template <typename T, typename VST>
void BinNode<T>::travLevel(VST & visit)
{
	Queue<BinNodePosi(T)> Q;//适用队列
	Q.enqueue(this);//根节点入队
	while (!Q.empty())
	{
		BinNodePosi(T) x = Q.dequeue(); visit(x->data);
		if (x->lc != nullptr) Q.enqueue(x->lc);
		if (x->rc != nullptr) Q.enqueue(x->rc);
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值