二叉树前中后序遍历(递归加非递归)

二叉树个各种遍历(递归加非递归)

先中后序遍历的操作定义

首先明确前中后序遍历二叉树时,结点、左子树、右子树的先后次序。
+ 先序遍历,遍历顺序是:父结点、左子树(先序遍历左子树,顺序同理,左子树父节点、该父节点的左子树,该父节点的右子树)、右子树(同左子树)。

  • 中序遍历,遍历顺序是:左子树(中序遍历左子树,顺序同理,左子树父节点、该父节点的左子树,该父节点的右子树)、父结点、右子树(同左子树)。

  • 后序遍历,遍历顺序是:左子树(后序遍历左子树,顺序同理,左子树父节点、该父节点的左子树,该父节点的右子树)、右子树(同左子树)、父节点。

递归遍历方法

按照上面的遍历顺序,可以很轻松的用递归实现二叉树的遍历。

//是哪个顺序,就把其他顺序的visit方法调用注释掉即可
void BTreeTraverse(TreeNode node){
    if(nede == null)
        return;
    //先序遍历
    visit(node);
    BTreeTraverse(node.leftChild);
    //中序遍历
    visit(node);
    BTreeTraverse(node.rightChild);
    //后序遍历
    visit(node);

    return;
}

非递归遍历方法

前序非递归遍历
void preOrderTraverse(BTreeNode node){
    Stack<BTreeNode> stack = new Stack<BTreeNode>();
    BTreeNode temp;
    if(node == null)
        return;
    //根结点入栈
    stack.push(node);

    while(!stack.empty()){
        //向左走到尽头,压入结点前访问结点元素
        while( (temp =stack.peek()) != null ){
            //访问结点元素
            visit(temp);
            //压入左孩子
            stack.push(temp.leftChild);
        }
        //最左叶子结点的左孩子为null,需要将null弹出
        stack.pop();
        //判断当前栈是否为空,不为空则弹出栈顶元素,压入该元素的右孩子
        if(!stack.empty()){
            temp = stack.pop();
            stack.push(temp.rightChild);
        }//接下来的循环会继续从这个右孩子开始向左走
    }
}
中序非递归遍历
void inOrderTraverse(BTreeNode node){
    Stack<BTreeNode> stack = new Stack<BTreeNode>();
    BTreeNode temp;
    if(node == null)
        return;
    //根结点入栈
    stack.push(node);

    while(!stack.empty()){
        //向左走到尽头
        while( (temp =stack.peek()) != null ){
            //压入左孩子
            stack.push(temp.leftChild);
        }
        //最左叶子结点的左孩子为null,需要将null弹出
        stack.pop();
        //判断当前栈是否为空,不为空则弹出栈顶元素,访问元素并压入该元素的右孩子
        if(!stack.empty()){
            temp = stack.pop();
            visit(temp);
            stack.push(temp.rightChild);
        }//接下来的循环会继续从这个右孩子开始向左走
    }
}

前序和中序非递归遍历的区别仅仅在于visit()函数被调用的时间不同。

后序非递归遍历

在进行后序非递归遍历时,如果再像考虑前中序非递归遍历一样,只想移动visit()方法的调用位置,就会陷入一个误区——在后序中,后序遍历是有条件的,即父节点是在子结点全部被遍历完后才被遍历。这样就需要判断一下当前最后一次访问的结点是否是当前节点的右子树,如果是,则遍历当前节点,否则,将该结点的右子树压入栈中。

这里有两种实现

void postOrderTraverse(BTreeNode node){
    Stack<BTreeNode> stack = new Stack<BTreeNode>();
    BTreeNode temp = node;
    BTreeNode preNode = null;//该变量存储上一次访问的结点

    while(temp != null || !stack.empty()){
        //寻找temp的最左叶子结点
        while(temp != null){
            stack.push(temp);
            temp = temp.leftChild;
        }
        //获取当前栈顶元素
        temp = stack.peek();
        //如果当前节点没有右子树或者右子树是上一次遍历的结点,访问当前节点
        if(temp.rightChild == null || temp.rightChild == preNode){
            visit(temp);
            temp = stack.pop();
            preNode = temp;
            temp = null;//遍历完当前节点后,就应该再从栈中pop了
        }else{
            //否则说明这个右子树没有被遍历过,将这个右子树压入栈中
            temp = temp.rightChild;
        }
    }
}

我比较喜欢双栈法,比较巧妙

void postOrderTraverse(BTreeNode node){
    Stack<BTreeNode> stack_temp = new Stack<BTreeNode>();
    Stack<BTreeNode> stack_result = new Stack<BTreeNode>();
    BTreeNode temp = node;
    stack_temp.push(temp);

    //先将树中的结点按照下面的方式从一个栈里拿出来放到结果栈里
    while(!stack_temp.empty()){
        temp = stack_temp.push();
        stack_result.push(temp);
        //把非空在孩子结点放到temp栈中
        if(temp.leftChild != null)
            stack_temp.push(temp.leftChild);
        if(temp.rightChild != null)
            stack_temp.push(temp.rightChild); 
        temp = temp.leftChild;
    }
    //访问结果栈中的结点
    while(!stack_result.empty()){
        temp = stack_result.pop();
        visit(temp);
    }
}
Python网络爬虫与推荐算法新闻推荐平台:网络爬虫:通过Python实现新浪新闻的爬取,可爬取新闻页面上的标题、文本、图片、视频链接(保留排版) 推荐算法:权重衰减+标签推荐+区域推荐+热点推荐.zip项目工程资源经过严格测试可直接运行成功且功能正常的情况才上传,可轻松复刻,拿到资料包后可轻松复现出一样的项目,本人系统开发经验充足(全领域),有任何使用问题欢迎随时与我联系,我会及时为您解惑,提供帮助。 【资源内容】:包含完整源码+工程文件+说明(如有)等。答辩评审平均分达到96分,放心下载使用!可轻松复现,设计报告也可借鉴此项目,该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的。 【提供帮助】:有任何使用问题欢迎随时与我联系,我会及时解答解惑,提供帮助 【附带帮助】:若还需要相关开发工具、学习资料等,我会提供帮助,提供资料,鼓励学习进步 【项目价值】:可用在相关项目设计,皆可应用在项目、毕业设计、课程设计、期末/期/大作业、工程实训、大创等学科竞赛比赛、初期项目立项、学习/练手等方面,可借鉴此优质项目实现复刻,设计报告也可借鉴此项目,也可基于此项目来扩展开发出更多功能 下载后请首先打开README文件(如有),项目工程可直接复现复刻,如果基础还行,也可在此程序基础上进行修改,以实现其它功能。供开源学习/技术交流/学习参考,勿用于商业用途。质量优质,放心下载使用。
1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值