二叉树遍历方法总结

一、递归方法

1、前序遍历    :   根——左——右

Preorder_tree_walk(x){   //x为根节点

      if x != nil

          print x.key;

     preorder_tree_walk(x.left);

     Preorder_tree_walk(x.right);

}

2、中序遍历     :  左——根——右

Inorder_tree_walk(x){

    if x!=nil

       Inorder_tree_walk(x.left);

       print x.key;

       Inorder_tree_walk(x.right);

}

3、后序遍历    :  左——右——根

Postorder_tree_walk(x){

     if x!=nil

        Postorder_tree_walk(x.left);

        Postorder_tree_walk(x.right);

        print x.key;

}

二、非递归方法

比较难的是非递归方法,可以有多种方法实现。

1、前序遍历

a、第一种方法,这也是我未参考别人而写出来的,把根节点压入栈,然后若栈不为空则循环,弹出并打印出栈顶元素,压入两个孩子节点(如果有的话),再继续循环,直到栈为空

Preorder_tree_walk(x){

      stack S;

      push(S,x);

      while(S.top != null){

                x=pop(S);

                print x.key;

                if  x.left != null

                     push(S,x.left);

                if  x.right != null

                     push(S.x.right);

      }


}

b、第二种,也是标准的算法,

     处理过程如下:

     1>内层while循环:对任一节点x,如果x不为null,访问x,并把x压入栈,再令x等于x的左孩子节点,循环1,直到x为null;

     2>如果栈顶不为空,弹出栈顶元素x,并令x为x的有孩子节点,返回1>,继续执行,直到栈为空且x为Null.

Preorder_tree_walk(x){

      stack S;

      while(x!=null || S.top != null){

               while(x!=null){

                         print x.key;

                         push(S,x);

                         x=x.left;

               }

               if(S.top!=null){

                         x=pop(S);

                         x=x.right;

               }

      }

}

2、中序遍历:据中序遍历的顺序,先左孩子,再根节点,再右孩子。

     1>如图第一个红色箭头所示,依次将当前节点及其所有左后代元素压入栈(图中1,2,3),直到左孩子为空,

     2>将栈顶元素x弹出并打印,把x的右孩子作为当前节点,返回1>执行;



Inorder_tree_walk(x){

    stack S;

    while(x!=null || S.top!=null){

            while(x!=null){

                     push(S,x);

                     x=x.left;

            }

            if(S.top!=null){

                     x=pop(S);

                     print x.key;

                     x=x.right;

            }

    }

}

3、后序遍历:次序为左——右——根

a、第一种方法:

     1>沿左子树一直往下走,并依次压入栈,直到左孩子节点为空,此时不能将栈顶元素出栈,因为右子树还没有遍历,

      2>如果栈顶元素curr右孩子为空或者右孩子已访问,则输出栈顶元素,并置栈顶元素为prev上一个访问节点,

否则,置当前元素curr为栈顶元素右孩子,返回1>执行,当其右孩子访问完时,该节点又出现在栈顶,此时该节点可以出栈。

     可以看出,在这个过程中,每个结点都两次出现在栈顶,只有在第二次出现在栈顶时,才能访问它。因此需要多设置一个变量标识该结点是否是第一次出现在栈顶。

Postorder_tree_walk(curr){

      stack S;

      prev=null;//上一次访问节点

      while(curr!=null || S.top!=null){

              while(curr!=null){              //一直向左走,并压入栈,直到左孩子为空

                        push(S,curr);

                        curr=curr.left;

              }

              curr=S.top;

              if(curr.right==null || curr.right==prev){            //如果当前元素右孩子为空或者右孩子已访问,则访问当前节点

                        print curr.key;

                        prev = curr;

                        pop(S);

                        curr=null;

              }

              else   curr=curr.right;//否则访问右孩子

      }

}

b、第二种方法

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

Postorder_tree_walk(x){

      stack S;

      curr;    //当前节点

      prev=null;//上一个访问节点

      push(S,x);

      while(S.top!=null){

                curr=S.top;

                if((curr.left==null &&curr.right==null) ||

                   (prev!=null && (prev==curr.left||prev==curr.right))){

                           print curr.key;

                           pop(S);

                           prev=curr;

                }

                else {

                           if(curr.left!=null)

                               push(S,curr.left);

                           if(curr.right!=null)

                               push(S,curr.right);

                }

      }

}

参考资料:

1>http://blog.csdn.net/hackbuteer1/article/details/6583988

2>http://www.cnblogs.com/dolphin0520/archive/2011/08/25/2153720.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
本火锅店点餐系统采用Java语言和Vue技术,框架采用SSM,搭配Mysql数据库,运行在Idea里,采用小程序模式。本火锅店点餐系统提供管理员、用户两种角色的服务。总的功能包括菜品的查询、菜品的购买、餐桌预定和订单管理。本系统可以帮助管理员更新菜品信息和管理订单信息,帮助用户实现在线的点餐方式,并可以实现餐桌预定。本系统采用成熟技术开发可以完成点餐管理的相关工作。 本系统的功能围绕用户、管理员两种权限设计。根据不同权限的不同需求设计出更符合用户要求的功能。本系统中管理员主要负责审核管理用户,发布分享新的菜品,审核用户的订餐信息和餐桌预定信息等,用户可以对需要的菜品进行购买、预定餐桌等。用户可以管理个人资料、查询菜品、在线点餐和预定餐桌、管理订单等,用户的个人资料是由管理员添加用户资料时产生,用户的订单内容由用户在购买菜品时产生,用户预定信息由用户在预定餐桌操作时产生。 本系统的功能设计为管理员、用户两部分。管理员为菜品管理、菜品分类管理、用户管理、订单管理等,用户的功能为查询菜品,在线点餐、预定餐桌、管理个人信息等。 管理员负责用户信息的删除和管理,用户的姓名和手机号都可以由管理员在此功能里看到。管理员可以对菜品的信息进行管理、审核。本功能可以实现菜品的定时更新和审核管理。本功能包括查询餐桌,也可以发布新的餐桌信息。管理员可以查询已预定的餐桌,并进行审核。管理员可以管理公告和系统的轮播图,可以安排活动。管理员可以对个人的资料进行修改和管理,管理员还可以在本功能里修改密码。管理员可以查询用户的订单,并完成菜品的安排。 当用户登录进系统后可以修改自己的资料,可以使自己信息的保持正确性。还可以修改密码。用户可以浏览所有的菜品,可以查看详细的菜品内容,也可以进行菜品的点餐。在本功能里用户可以进行点餐。用户可以浏览没有预定出去的餐桌,选择合适的餐桌可以进行预定。用户可以管理购物车里的菜品。用户可以管理自己的订单,在订单管理界面里也可以进行查询操作。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值