二叉树遍历方法总结
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; } } } };