1, 二叉树结构
struct TreeNode
{
int val;
TreeNode* left;
TreeNode* right;
TreeNode(int x) : val(x), left(NULL), right(NULL) {}
};
2, 遍历方法
class BinaryTree
{
public:
//二叉树的遍历
//递归遍历
//先序遍历
void preOrderTraversal( TreeNode* root )
{
if(root)
{
cout << root->val << " "; //visit()
preOrderTraversal( root->left );
preOrderTraversal( root->right );
}
}
//中序遍历
void inOrderTraverval( TreeNode* root )
{
if( root )
{
inOrderTraverval( root->left );
cout << root->val << " "; //visit()
inOrderTraverval( root->right );
}
}
//后序遍历
void postOrderTraverval( TreeNode* root )
{
if(root)
{
postOrderTraverval(root->left);
postOrderTraverval(root->right);
cout << root->val << " "; //visit()
}
}
//循环迭代法遍历二叉树
//先序遍历
void visitAlongLeftBranch(TreeNode* root, stack<TreeNode*> &S)
{
while(root)
{
cout << root->val << " "; //visit()
S.push(root->right); //右孩子入栈暂存(可优化,通过判断,避免空的右孩子入栈)
root = root->left; //往左分支深入一层
}
}
void preOrderVisit(TreeNode* root)
{
stack<TreeNode*> S; //辅助栈
while(true)
{
visitAlongLeftBranch(root, S); //从当前节点出发,逐批访问
if(S.empty()) break; //直到栈空为止
root = S.top(); //得到下一批的起点
S.pop();
}
}
//中序遍历1
void goAlongLeftBranch(TreeNode* root, stack<TreeNode *> &S)
{
//当前节点入栈后随即向左分支深入一层,迭代到无左孩子为止
while(root) { S.push(root); root = root->left; }
}
void inOrderVisit1(TreeNode * root)
{
stack<TreeNode *> S;
while(true)
{
goAlongLeftBranch(root, S); //从当前节点出发,逐批入栈
if(S.empty()) break; //直到所有节点处理完毕
root = S.top(); //弹出栈顶元素并访问
S.pop();
cout << root->val << " "; //visit()
root = root->right; //转向右孩子
}
}
//中序遍历2
void inOrderVisit2(TreeNode * root)
{
stack<TreeNode *> S;
while(true)
{
if(root)
{
S.push(root);
root = root->left;
}
else if(!S.empty())
{
root = S.top();
S.pop();
cout << root->val << " ";
root = root->right;
}
else
break;
}
}
//后续遍历
void postOrderVisit(TreeNode* root)
{
stack<TreeNode*> S;
TreeNode *ptr = NULL, *pre = NULL; //pre指向已访问过的最后一个节点
if(root) S.push(root); //根节点进栈
while(!S.empty())
{
ptr = S.top(); //获取栈顶元素
/*
如果当前节点有左子树,且左子树节点不是刚被访问的节点;如果当前节点有右子树,且右
子树节点不是刚被访问的节点,表明栈顶元素指向的树节点未被访问到,且左子树右子树均
未被访问到,将左子树节点入栈,深入一层。
*/
if(ptr->left && pre != ptr->left && !(ptr->right && pre == ptr->right))
S.push(ptr->left);
//如果栈顶元素的右子树存在,且不是刚被访问的节点,则将右子树节点入栈,深入一层。
else if(ptr->right && pre != ptr->right)
S.push(ptr->right);
//如果栈顶元素的左右子树均被访问过,则访问栈顶元素,将栈顶元素退栈。并更新pre
else
{
cout << ptr->val << " "; //visit()
S.pop();
pre = ptr;
}
}
}
};