二叉树遍历
二叉树遍历
2024年7月27日
21:39
非递归版本
树结点结构
leetcode树结点结构
structTreeNode{
intval;
TreeNode*left;
TreeNode*right;
TreeNode():val(0),left(nullptr),right(nullptr){}
TreeNode(intx):val(x),left(nullptr),right(nullptr){}
TreeNode(intx,TreeNode*left,TreeNode*right):val(x),left(left),right(right){}
};
- 先序遍历
- 创建一个栈s,把头结点head入栈
- 只要栈中还有数据
- 取出栈顶数据,作为当前要操作的结点
- 处理后,先入右节点(不为空),再入左节点(不为空)
- 中序遍历,左中右
- 创建一个栈s,结点指针p遍历树;s用于压入当前树的头结点保存数据,p用于指向树节点做处理
- 只要栈不为空(说明还有被保存的结点没有被操作),并且p还指向着待处理的结点
- p不为空,就一直压入栈,并持续往左子树递进。(处理左子树)
- 遇到空,取栈顶元素操作(中),并让p指向栈顶元素的右子树(右子树)。
- 代码
classSolution{
public:
vector<int>inorderTraversal(TreeNode*root){
if(!root)
returnvector<int>();
vector<int>ret;
stack<TreeNode*>s;
while(!s.empty()||root){
while(root){
s.push(root);;
root=root->left;
}
root=s.top();
s.pop();
ret.push_back(root->val);
root=root->right;
}
returnret;
}
};
- 后序遍历(单栈处理)
- 需要栈s保存待处理的结点,cur结点指向当前需要处理的结点,h指向已经遍历的结点,先把头结点入栈s
- cur获取栈顶元素,
- 如果cur的左子树存在且h不等于cur的左子树,那么说明左子树还没处理,把左子树压入s
- cur的右子树存在且h不等于cur右子树,说明右子树还没处理,把右子树压入s
- 其他情况(左右子树微空或者均被遍历过),那么操作cur,h = cur,出栈顶元素。
classSolution{
public:
vector<int>postorderTraversal(TreeNode*root){
if(!root)
returnvector<int>();
vector<int>ret;//返回值
stack<TreeNode*>s;//保留现场
s.push(root);
TreeNode*h=root;//保留刚刚处理的结点
TreeNode*cur=nullptr;//当前节点
while(!cur||!s.empty()){
cur=s.top();
if(cur->left&&
cur->left!=h&&
cur->right!=h){//有左子树且左树没处理,开始处理左子树
s.push(cur->left);
}
elseif(cur->right
&&cur->right!=h){//左树存在且已经没处理,开始处理右
s.push(cur->right);
}
else{//左右均不存在或被处理
ret.push_back(cur->val);
h=cur;
s.pop();
}
}
returnret;
}
};