【done】【重点】二叉树三种遍历方式的迭代与递归实现

后续遍历最麻烦,对比记忆!

中序遍历(迭代)

力扣

class Solution {
	public List<Integer> inorderTraversal(TreeNode root) {
		List<Integer> res = new ArrayList<Integer>();
		Stack<TreeNode> stack = new Stack<TreeNode>();
		while(stack.size() > 0 || root != null) {
			//不断往左子树方向走,每走一次就将当前节点保存到栈中
			//这是模拟递归的调用
			if(root!=null) {
				stack.push(root);
				root = root.left;
			//当前节点为空,说明左边走到头了,从栈中弹出节点并保存
			//然后转向右边节点,继续上面整个过程
			} else {
				TreeNode tmp = stack.pop();
				res.add(tmp.val);
				root = tmp.right;
			}
		}
		return res;
	}
}
作者:王尼玛
链接:https://leetcode.cn/problems/binary-tree-inorder-traversal/solutions/96765/dong-hua-yan-shi-94-er-cha-shu-de-zhong-xu-bian-li/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

前序遍历(迭代)

力扣

class Solution {
    public List<Integer> preorderTraversal(TreeNode root) {
        List<Integer> res = new ArrayList<>();
        Stack<TreeNode> stack = new Stack<>();
        while (stack.size() > 0 || root != null) {
            if (root != null) {
                res.add(root.val);
                stack.push(root);
                root = root.left;
            } else {
                TreeNode tmp = stack.pop();
                root = tmp.right;
            }
        }

        return res;
    }
}

后序遍历

力扣
参考答案

class Solution {
    public List<Integer> postorderTraversal(TreeNode root) {
        List<Integer> res = new ArrayList<>();
        Stack<TreeNode> stack = new Stack<>();
        TreeNode pre = null;
        while (stack.size() > 0 || root != null) {
            if (root != null) {
                stack.push(root);
                root = root.left;
            } else {
                root = stack.pop();
                if (root.right == null || pre == root.right) {
                    res.add(root.val);
                    pre = root;
                    root = null;
                } else {
                   stack.push(root);
                   root = root.right;
                }
            }
        }

        return res;
    }
}

20180905更新:这个博客中的解法不是很好,看相应的LeetCode题目笔记~~~
我感觉此博客中的说法更容易让人理解:https://blog.csdn.net/woshinannan741/article/details/52825163,还是看这个博客比较好,下面的内容不是很好理解啊。。
本博客转载自:https://blog.csdn.net/xiaominkong123/article/details/51567437
二叉树的三种遍历为:前序遍历,中序遍历和后序遍历。
遍历的实现可分为递归和非递归。递归法与二叉树的定义相似,非递归法采用栈去模拟实现。
定义树节点

struct BinaryTreeNode {
    int val;
    struct BinaryTreeNode* left;
    struct BinaryTreeNode* right;
};

##一、前序遍历
遍历的次序为:根结点——左结点——右结点。
###递归

//前序遍历的递归实现  
void Pre_travel1(BinaryTreeNode* pRoot) {  
    if(pRoot == NULL)
        return;  
    cout<< pRoot->val << endl;  
    if(pRoot->left != NULL)  
       Pre_travel1(pRoot->left);  
    if(pRoot->right != NULL)  
       Pre_travel1(pRoot->right);  
}  

###非递归
前序遍历的访问顺序为:根,左和右。对于任一结点,其可看做根结点,因此可直接访问。访问完后,若其左孩子不为空,则按照相同规则访问它的左子树;访问完左子树,再访问它的右子树。处理过程如下:
对于任一结点P:
step 1:访问结点p,并将结点p入栈。
step 2:判断结点p的左孩子是否为空。若为空,则取栈顶结点并出栈,将栈顶元素的右孩子设为当前的结点p,循环至 第1步。若不为空,则将p的左孩子设为当前结点p。
step 3:直到p为NULL,并且栈为空,则遍历结束。

//前序遍历的非递归遍历  
void Pre_travel2(BinaryTreeNode* pRoot) {  
    stack<BinaryTreeNode*> s;  
    BinaryTreeNode *p = pRoot;  
    if(pRoot == NULL)  
        return;  
    while(p != NULL || !s.empty()) {  
       while(p != NULL) {  
           cout << p->val << endl;  
           s.push(p);  
           p=p->left;  
       }  
       if(!s.empty()) {  
           p=s.top();  
           s.pop();  
           p=p->right;  
       }  
    }  
}  

##二、中序遍历
遍历的次序为:左结点——根结点——右结点。
###递归

//中序遍历的递归实现  
void Inorder_travel1(BinaryTreeNode* pRoot) {  
    if(pRoot == NULL)
        return;
    if(pRoot->left != NULL)  
       Inorder_travel1(pRoot->left);  
    cout<< pRoot->val << endl;      
    if(pRoot->right != NULL)  
       Inorder_travel1(pRoot->right);  
}  

###非递归
根据中序遍历的顺序,对于任一结点,先访问其左孩子。而左孩子又可以看做一个根结点,然后继续访问左孩子,直到遇到的左孩子结点为空,则停止访问。然后访问右孩子。
处理过程如下:
对于任一结点p:
step 1:若其左孩子不为空,则将p入栈,并将p的左孩子置为当前的p。然后对当前结点p再进行相同的处理。
step 2:若其左孩子为空,则取栈顶元素并进行出栈操作,访问该栈顶结点,然后将栈顶结点的右孩子置为当前的P结点。
step 3:直到p为NULL并且栈为空则遍历结束。

//中序遍历的非递归法  
void Inorder_travel2(BinaryTreeNode* pRoot) {  
    stack<BinaryTreeNode*> s;  
    BinaryTreeNode *p = pRoot;  
    while(p != NULL || !s.empty()) {  
        while(p!=NULL) {  
            s.push(p);  
            p=p->left;  
        }  
        if(!s.empty()) {  
            p=s.top();  
            cout << p->value <<endl;  
            s.pop();  
            p=p->right;  
        }  
    }  
}  

##三、后序遍历
遍历的次序为:左结点——右结点——根结点。
###递归

//后序遍历的递归实现  
void Postorder_travel1(BinaryTreeNode* pRoot) {  
    if(pRoot == NULL)
        return;
    if(pRoot->left != NULL)  
       Postorder_travel1(pRoot->left);  
    if(pRoot->right != NULL)  
       Postorder_travel1(pRoot->right);  
    cout<< pRoot->val << endl;       
}  

###非递归
非递归遍历:要保证根结点在左孩子和右孩子访问之后才能访问。因此对于任一结点p,先将其入栈。
若p不存在左孩子和右孩子,则可以直接访问它。或者p存在左孩子或者右孩子,但是左孩子和右孩子都已经被访问过了,则可以直接访问该结点。
若非上述两种情况,则将右孩子和左孩子依次入栈。这样可以保证每次取栈顶元素时,左孩子在右孩子前面被访问,根结点在左孩子和右孩子访问之后被访问。

//后序遍历的非递归法  
void Postorder_travel2(BinaryTreeNode* pRoot) {  
    stack<BinaryTreeNode*> s;  
    BinaryTreeNode *cur;  
    BinaryTreeNode *pre=NULL;  
    s.push(pRoot);//根结点入栈  
    while(!s.empty()) {  
        cur=s.top();  
        if((cur->left==NULL&&cur->right==NULL)||(pre!=NULL&&(pre==cur->left||pre==cur->right))) {  
            //左孩子和右孩子同时为空,或者当前结点的左孩子或右孩子已经遍历过了  
            cout << cur->value << endl;  
            s.pop();  
            pre=cur;  
        }  
        else {  
            if(cur->right!=NULL)  
                s.push(cur->right);  
            if(cur->left!=NULL)  
                s.push(cur->left);  
        }  
    }  
}  

关于层次遍历参考链接:剑指offer——面试题60:把二叉树打印成多行
https://blog.csdn.net/allenlzcoder/article/details/79785180

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值