问题:
假设二叉树节点的定义如下:
struct BTreeNode{
int val; // 节点值
BTreeNode* pLeft; // 左子树指针
BTreeNode* pRight; // 右子树指针
};
请用C++非递归算法分别实现二叉树的先序遍历,中序遍历,后序遍历和层序遍历。
1)先序遍历非递归算法
思路:遍历到某个节点时,如果该节点不为NULL,首先将该节点的值输出,然后将其右孩子节点压栈(如果有的话),然后令该节点指向其左孩子节点;如果当前节点为NULL,而且节点栈非空,则取栈顶节点作为当前节点,并且栈顶节点出栈。代码如下:
void preOrder(BTreeNode* root){
BTreeNode* pNode = root;
stack<BTreeNode*> s;
while (pNode){
cout << pNode->val << " ";
if (pNode->pRight) s.push(pNode->pRight);
pNode = pNode->pLeft;
if (!pNode && !s.empty()){
pNode = s.top();
s.pop();
}
}
cout << endl;
}
2)中序遍历非递归算法
思路:如果当前节点指针非NULL,则将当前节点指针压栈,并将当前节点指针指向左孩子节点;如果当前节点为NULL,而且栈非空,则输出栈顶节点值,并令当前节点指针指向栈顶节点的右孩子节点,栈顶节点出栈。
void inOrder(BTreeNode* root){
BTreeNode* pNode = root;
stack<BTreeNode*> s;
while (pNode || !s.empty()){
while (pNode){
s.push(pNode);
pNode = pNode->pLeft;
}
pNode = s.top();
s.pop();
cout << pNode->val << " ";
pNode = pNode->pRight;
}
cout << endl;
}
3)后序遍历非递归算法
思路:设置一个前驱节点,表示上一次访问的节点,初始为NULL。首先根节点入栈。当栈不为空时,取栈顶节点,判断栈顶节点是否为叶子节点,或者栈顶节点的左孩子或者右孩子刚被访问过,如果是,则栈顶节点出栈并输出;否则分别将栈顶节点右孩子节点入栈(如果非空的话),左孩子节点入栈(如果非空的话)。
void postOrder(BTreeNode* root){
if (root == NULL) return;
stack<BTreeNode*> s;
s.push(root);
BTreeNode* pNode = root;
BTreeNode* pPre = NULL;
while (!s.empty()){
pNode = s.top();
if ((!pNode->pLeft && !pNode->pRight) ||
(pPre && (pPre == pNode->pLeft || pPre == pNode->pRight))){
cout << pNode->val << " ";
pPre = pNode;
s.pop();
}
else{
if (pNode->pRight) s.push(pNode->pRight);
if (pNode->pLeft) s.push(pNode->pLeft);
}
}
cout << endl;
}
4)层序遍历算法
思路:用一个辅助队列。首先根节点进入队列。当队列不为空时,取队首元素并输出,然后依次将左孩子与右孩子(如果不为空的话)分别插入队列尾。
void levelOrder(BTreeNode* root){
if (root == NULL) return;
queue<BTreeNode*> q;
q.push(root);
while (!q.empty()){
BTreeNode* pNode = q.front();
q.pop();
cout << pNode->val << " ";
if (pNode->pLeft) q.push(pNode->pLeft);
if (pNode->pRight) q.push(pNode->pRight);
}
cout << endl;
}