二叉树遍历可以分为深度优先遍历和广度优先遍历;
其中深度优先又可根据访问根节点的次序不同分为:先序遍历(前序遍历)、中序遍历和后序遍历;
前序遍历:根----->左子树---->右子树
中序遍历:左子树---->根----->右子树
后序遍历:左子树---->右子树----->根
以下是递归的代码:
//前序遍历(递归)
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();
}
}