二叉树的几种遍历方式

二叉树遍历可以分为深度优先遍历和广度优先遍历;

其中深度优先又可根据访问根节点的次序不同分为:先序遍历(前序遍历)、中序遍历和后序遍历;

前序遍历:根----->左子树---->右子树

中序遍历:左子树---->根----->右子树

后序遍历:左子树---->右子树----->根

以下是递归的代码:

//前序遍历(递归)
void _PreOrder(Node* _pRoot)   
{
	if (_pRoot)
	{
		cout << _pRoot->_data << " ";
		_PreOrder(_pRoot->_pLeft);
		_PreOrder(_pRoot->_pRight);
	}
}

//中序遍历(递归)
void _InOrder(Node* _pRoot)    
{
	if (_pRoot)
	{
		_InOrder(_pRoot->_pLeft);
		cout << _pRoot->_data << " ";
		 _InOrder(_pRoot->_pRight);
	}
}

//后序遍历(递归)
void _PostOrder(Node* _pRoot)    
{
	if (_pRoot)
	{
		_PostOrder(_pRoot->_pLeft);
		_PostOrder(_pRoot->_pRight);
		cout << _pRoot->_data << " ";
	}
}


如果不想用递归实现,也可以用非递归,这里非递归的时候要借助到栈,利用栈先进后出的特点可以完成遍历。

先序遍历:先让根节点入栈,取栈顶元素,访问栈顶元素并出栈,由于栈是先进后出,所以让栈顶元素的右孩子入栈(如果右孩子存在)然后再让左孩子入栈(如果左孩子存在)。如果栈不为空就一直这样重复做下去。

中序遍历:先让根入栈,然后一直让左边的结点入栈直到为空,取栈顶元素(此时栈顶元素就是最左边的结点)访问栈顶元素并出栈,使当前节点pCur走到它的子树(pCur = pCur->Right)。如果pCur不为空

后序遍历:后序遍历是三个中最难的,因为要保证先遍历完左右子树才可以访问根节点,在这里我们可以用中序遍历的思想先让左边的节点全部入栈,然后去判断右孩子,如果没有右孩子或者右孩子已经被访问过就可以直接访问该节点,如果有右孩子,则先去访问右孩子(把右孩子当做一棵子树来处理),所以需要一个指针prev来标记上一次访问过的节点。

下面是几种遍历的非递归代码:

// 先序遍历(非递归--->栈)
void _PreOrder_Nor(Node* _pRoot)
{
	if (_pRoot == NULL)
		return;

	Node* pCur = _pRoot;
	stack<Node*> s;
	s.push(pCur);

	while (!s.empty())
	{
		Node* top = s.top();
		cout << top->_data << " ";
		s.pop();

		if (top->_pRight)
			s.push(top->_pRight);
		if (top->_pLeft)
			s.push(top->_pLeft);
	}
}


// 中序遍历(非递归--->栈) 
void _InOrder_Nor(Node* _pRoot)
{
	if (_pRoot == NULL)
		return;

	Node* pCur = _pRoot;
	stack<Node*> s;

	while (pCur || !s.empty())
	{
		while (pCur)
		{
			s.push(pCur);
			pCur = pCur->_pLeft;
		}

		pCur = s.top();
		cout << pCur->_data << " ";
		s.pop();

		pCur = pCur->_pRight;
	}
}


// 后序遍历(非递归--->栈)
void _PostOrder_Nor(Node* _pRoot)
{
	if (_pRoot == NULL)
		return;

	Node* pCur = _pRoot;
	Node* prev = NULL;
	stack<Node*> s;

	while (pCur || !s.empty())
	{
		while (pCur)
		{
			s.push(pCur);
			pCur = pCur->_pLeft;
		}

		Node* top = s.top();

		if ((top->_pRight == NULL) || (top->_pRight == prev))
		{
			cout << top->_data << " ";
			prev = top;
			s.pop();
		}
		else
			pCur = pCur->_pRight;
	}
}
层序遍历则是利用了队列先进先出的特点,代码如下:

	//层序遍历(队列)
	void _LevelOrder(Node* _pRoot)    
	{
		if (_pRoot == NULL)
			return;
		queue<Node*> q;
		q.push(_pRoot);

		Node* pCur = _pRoot;
		while (!q.empty())
		{
			pCur = q.front();
			cout << pCur->_data << " ";
			if (pCur->_pLeft)
				q.push(pCur->_pLeft);
			if (pCur->_pRight)
				q.push(pCur->_pRight);
			q.pop();
		}
	}





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值