二叉树的各种遍历算法的递归和非递归实现

来源:互联网 发布:mac新浪微博客户端 编辑:程序博客网 时间:2024/06/08 13:55

二叉树在数据结构中是非常常用的,尤其是关于它的各种遍历算法,经常有关于递归和非递归的实现。下面来一一介绍各种遍历方式。

下面是先序遍历:

先序遍历:首先遍历根节点,然后再遍历左子树,再遍历右子树,那么如果采用递归来遍历,就是首先每一次先输出那个根节点的值,然后接着采用递归方式来遍历。代码如下:

class TreeNode{        int val;        TreeNode left;        TreeNode right;        TreeNode(int x)        {              val = x;        }}public void preOrder(TreeNode root){         if(root != null)         {                System.out.println(root.val);
                if(root.left != null)                   preOrder(root.left);
                if(root.right != null)                   preOrder(root.right);         }}

如果考虑不采用递归来做,那么就是用Stack来实现。

因为栈有个先进后出的特点,所以在将节点入栈的时候,首先要考虑是先将右子树先入栈,然后再将左子树入栈,因为是出栈的顺序是先进后出,所以这里要特别当心。然后每一次栈顶的元素先出栈,然后顺带着将这个栈顶元素的右子树先入栈,然后是左子树再入栈,一定是这样的顺序。注意,栈底元素在还没出栈之前一定是右子树的根节点。直到第一次它出栈。

public class Solution 
{    public ArrayList<Integer> preorderTraversal(TreeNode root) 
<span style="font-family: Arial, Helvetica, sans-serif;">        {</span>
        ArrayList<Integer> returnList = new ArrayList<Integer>();         if(root == null)            return returnList;         Stack<TreeNode> stack = new Stack<TreeNode>();        stack.push(root);         while(!stack.empty()){            TreeNode n = stack.pop();          //每次先让它出栈            returnList.add(n.val);             if(n.right != null){                stack.push(n.right);            }            if(n.left != null){                stack.push(n.left);            }         }        return returnList;    }}

其次是中序遍历:

首先也是采用递归的方式,就是先遍历左子树,然后遍历根节点,接着遍历右子树。所以代码可以这样写:

class TreeNode {          int val;          TreeNode left;          TreeNode right;          TreeNode(int x)          {                   val = x;          }}public void inOrder(TreeNode root){        if(root == null)              return;        else if(root != null)        {
                if(root.left != null)                   inOrder(root.left);                System.out.println(root.val);
                if(root.right != null)                   inOrder(root.right);         }}
接下来就是采用非递归的方式来进行中序遍历。非递归来中序遍历一棵二叉树,采用的数据结构还是栈,首先,一直循环将左子树压入栈中,直到那个左子树节点为空,那么现在在栈中的所有节点都是关于左子树的,然后开始将栈中的头结点压出栈。然后看它有木有右子树,因为刚才的头结点肯定是没有左子树的节点,但是根据中序遍历的情况,有可能还有右子树,所以得考虑。然后如果有右子树,那么就将这个人右子树节点压入栈中,然后再次循环,看这个右子树节点是否有左子树,如果有,那么继续循环地压入,直到碰到没有左子树的情况,然后将头结点压出栈,接下来就是重复这样循环实现。其实和递归实现的原理差不多。

class TreeNode{          int val;          TreeNode left;          TreeNode right;          TreeNode(int x)          {                 val = x;          }}public List<Integer> inOrder(TreeNode root){          List<Integer> list = new ArrayList<Integer>();          if(root == null)                return;          else          {                  Stack<Integer> stack = new Stack<Integer>();                  NodeTree Current = root;                  while(Current != null || !stack.isEmpty())                  {                         while(Current != null)                         {                                stack.push(Current.val);                                Current = Current.left;                         }                         if(!stack.isEmpty())                         {                                Current = stack.pop();                                list.add(Current.val);                                if(Current.right != null)        //考虑左子树的右子树是否存在,如果存在,那么就将其压入栈中                                       Current = Current.right;                          }                    }              }              return list;}

还有一种非递归的方式来中序遍历二叉树,因为上面那种方法来leetcode中发现超时了,所以得换一种方式:

public List<Integer> inOrder(TreeNode root){        List<Integer> list = new ArrayList<Integer>();        if(root == null)              return list;        else        {                 Stack<TreeNode> stack = new Stack<TreeNode>();                 TreeNode Current = root;                 while(Current != null || !stack.isEmpty())                 {                         if(Current != null)                         {                                  stack.push(Current);                                  Current = Current.left;                          }                          else                          {                                    TreeNode t = stack.pop();                                    list.add(t.val);                                    Current = t.right;                          }                   }           }           return list;}

接下来是后续遍历:

首先采用递归的方式来实现后续遍历,与先序和中序遍历类似。

public void postOrder(TreeNode root){          if(root == null)                return;          else          {                 if(root.left != null)                      postOrder(root.left);                 if(root.right != null)                      postOrder(root.right);                 System.out.println(root.val);          }}

然后是非递归实现后续遍历,也是采用栈来实现,就是入栈和出栈顺序上得注意

public void thePostOrderTraversal_Stack(Node root) {   //后序遍历    Stack<Node> stack = new Stack<Node>();    Stack<Node> output = new Stack<Node>();//构造一个中间栈来存储逆后序遍历的结果    Node node = root;    while (node != null || stack.size() > 0) {      if (node != null) {        output.push(node);        stack.push(node);        node = node.getRightNode();      } else {        node = stack.pop();        node = node.getLeftNode();              }    }    while (output.size() > 0) {      printNode(output.pop());    }  }

0 0
原创粉丝点击