二叉树的四种遍历方式

二叉树的四种遍历方式:

  • 二叉树的遍历(traversing binary tree)是指从根结点出发,按照某种次序依次访问二叉树中所有的结点,使得每个结点被访问依次且仅被访问一次。
    四种遍历方式分别为:先序遍历、中序遍历、后序遍历、层序遍历。

遍历之前,我们首先介绍一下,如何创建一个二叉树,在这里博主宝宝用的是先建左树在建右树的方法,

首先要声明结点TreeNode类,代码如下:

public class TreeNode {
    public int data;
    public TreeNode leftChild;
    public TreeNode rightChild;

    public TreeNode(int data){
        this.data = data;
    }

}

再来创建一颗二叉树:

/**
     * 构建二叉树
     * @param list   输入序列
     * @return
     */
    public static TreeNode createBinaryTree(LinkedList<Integer> list){
        TreeNode node = null;
        if(list == null || list.isEmpty()){
            return null;
        }
        Integer data = list.removeFirst();
        if(data!=null){
            node = new TreeNode(data);
            node.leftChild = createBinaryTree(list);
            node.rightChild = createBinaryTree(list);
        }
        return node;
    }

接下来博主宝宝按照上面列的顺序一一讲解,

首先来看先序遍历,所谓的先序遍历就是先访问根节点,在访问左节点,最后访问右节点,

如上图所示,前序遍历结果为:ABDFECGHI

实现代码如下:

/**
     * 二叉树前序遍历   根-> 左-> 右
     * @param node    二叉树节点
     */
    public static void preOrderTraveral(TreeNode node){
        if(node == null){
            return;
        }
        System.out.print(node.data+" ");
        preOrderTraveral(node.leftChild);
        preOrderTraveral(node.rightChild);
    }

再者就是中序遍历,所谓的中序遍历就是先访问左节点,再访问根节点,最后访问右节点,

如上图所示,前序遍历结果为:DBEFAGHCI

实现代码如下:

/**
     * 二叉树中序遍历   左-> 根-> 右
     * @param node   二叉树节点
     */
    public static void inOrderTraveral(TreeNode node){
        if(node == null){
            return;
        }
        inOrderTraveral(node.leftChild);
        System.out.print(node.data+" ");
        inOrderTraveral(node.rightChild);
    }

最后就是中序遍历,所谓的中序遍历就是先访问左节点,再访问右节点,最后访问根节点。

如上图所示,前序遍历结果为:DEFBHGICA

实现代码如下:

/**
     * 二叉树后序遍历   左-> 右-> 根
     * @param node    二叉树节点
     */
    public static void postOrderTraveral(TreeNode node){
        if(node == null){
            return;
        }
        postOrderTraveral(node.leftChild);
        postOrderTraveral(node.rightChild);
        System.out.print(node.data+" ");
    }

讲完上面三种非递归的方法,下面博主宝宝再给大家讲讲非递归是如何实现前中后序遍历的

还是一样,先看非递归前序遍历

  1. 首先申请一个新的栈,记为stack;
  2. 声明一个结点treeNode,让其指向node结点;
  3. 如果treeNode的不为空,将treeNode的值打印,并将treeNode入栈,然后让treeNode指向treeNode的右结点,
  4. 重复步骤3,直到treenode为空;
  5. 然后出栈,让treeNode指向treeNode的右孩子
  6. 重复步骤3,直到stack为空.

实现代码如下:

public static void preOrderTraveralWithStack(TreeNode node){
        Stack<TreeNode> stack = new Stack<TreeNode>();
        TreeNode treeNode = node;
        while(treeNode!=null || !stack.isEmpty()){
            //迭代访问节点的左孩子,并入栈
            while(treeNode != null){
                System.out.print(treeNode.data+" ");
                stack.push(treeNode);
                treeNode = treeNode.leftChild;
            }
            //如果节点没有左孩子,则弹出栈顶节点,访问节点右孩子
            if(!stack.isEmpty()){
                treeNode = stack.pop();
                treeNode = treeNode.rightChild;
            }
        }
    }

中序遍历非递归,博主宝宝在此不过多叙述具体步骤了,

具体过程:

  1. 申请一个新栈,记为stack,申请一个变量cur,初始时令treeNode为头节点;
  2. 先把treeNode节点压入栈中,对以treeNode节点为头的整棵子树来说,依次把整棵树的左子树压入栈中,即不断令treeNode=treeNode.leftChild,然后重复步骤2;
  3. 不断重复步骤2,直到发现cur为空,此时从stack中弹出一个节点记为treeNode,打印node的值,并让treeNode= treeNode.right,然后继续重复步骤2;
  4. 当stack为空并且cur为空时结束。
public static void inOrderTraveralWithStack(TreeNode node){
        Stack<TreeNode> stack = new Stack<TreeNode>();
        TreeNode treeNode = node;
        while(treeNode!=null || !stack.isEmpty()){
            while(treeNode != null){
                stack.push(treeNode);
                treeNode = treeNode.leftChild;
            }
            if(!stack.isEmpty()){
                treeNode = stack.pop();
                System.out.print(treeNode.data+" ");
                treeNode = treeNode.rightChild;
            }

        }
    }

后序遍历非递归实现,后序遍历这里较前两者实现复杂一点,我们需要一个标记为来记忆我们此时节点上一个节点,具体看代码注释

public static void postOrderTraveralWithStack(TreeNode node){
        Stack<TreeNode> stack = new Stack<TreeNode>();
        TreeNode treeNode = node;
        TreeNode lastVisit = null;   //标记每次遍历最后一次访问的节点
        while(treeNode!=null || !stack.isEmpty()){//节点不为空,结点入栈,并且指向下一个左孩子
            while(treeNode!=null){
                stack.push(treeNode);
                treeNode = treeNode.leftChild;
            }
            //栈不为空
            if(!stack.isEmpty()){
                //出栈
                treeNode = stack.pop();
                /**
                 * 这块就是判断treeNode是否有右孩子,
                 * 如果没有输出treeNode.data,让lastVisit指向treeNode,并让treeNode为空
                 * 如果有右孩子,将当前节点继续入栈,treeNode指向它的右孩子,继续重复循环
                 */
                if(treeNode.rightChild == null || treeNode.rightChild == lastVisit) {
                    System.out.print(treeNode.data + " ");
                    lastVisit = treeNode;
                    treeNode  = null;
                }else{
                    stack.push(treeNode);
                    treeNode = treeNode.rightChild;
                }

            }

        }
    }

最后博主宝宝再给大家介绍一下层序遍历

具体步骤如下:

  1. 首先申请一个新的队列,记为queue;
  2. 将头结点head压入queue中;
  3. 每次从queue中出队,记为node,然后打印node值,如果node左孩子不为空,则将左孩子入队;如果node的右孩子不为空,则将右孩子入队;
  4. 重复步骤3,直到queue为空。

实现代码如下:

public static void levelOrder(TreeNode root){
        LinkedList<TreeNode> queue = new LinkedList<>();
        queue.add(root);
        while(!queue.isEmpty()){
            root = queue.pop();
            System.out.print(root.data+" ");
            if(root.leftChild!=null) queue.add(root.leftChild);
            if(root.rightChild!=null) queue.add(root.rightChild);
        }
    }

原文地址:https://www.cnblogs.com/du001011/p/11229170.html

时间: 2024-11-09 01:02:57

二叉树的四种遍历方式的相关文章

java集合四种遍历方式

package conection; import java.util.Iterator;import java.util.LinkedList;import java.util.List; public class Ergodic { public static void main(String[] args) {     // TODO Auto-generated method stub    /*    * java集合类的四种遍历方式    *     */    List<Integ

lua中for循环的四种遍历方式

lua中for的四种遍历方式区别 table.maxn 取最大的整数key #table 从1开始的顺序整数最大值,如1,2,3,6 #table == 3 key,value pairs 取每一个键值对 ipairs 取从key==1开始的顺序整数最大值,每个键值对 参考http://rangercyh.blog.51cto.com/1444712/1032925 不过有一个问题, tbtest = { [1] = 1, [2] = 2, [4] = 4, } print(#(tbtest))

二叉树的三种遍历方式的循环和递归的实现方式

///////////////////头文件:BST.h//////////////////////// #ifndef BST_H #define BST_H #include "StdAfx.h" #include<iostream> #include<stack> template<typename DataType> class BST { public: class Node { public: Node(int data=0):m_dat

list的四种遍历方式

1.手先增强for循环和iterator遍历的效果是一样的,也就说 增强for循环的内部也就是调用iteratoer实现的,但是增强for循环 有些缺点,例如不能在增强循环里动态的删除集合内容.不能获取下标等. 2.ArrayList由于使用数组实现,因此下标明确,最好使用普通循环. 3.而对于 LinkedList 由于获取一个元素,要从头开始向后找,因此建议使用 增强for循环,也就是iterator. list,map,set的区别  list,map,set的区别 (首先假定小猪都是同一

折半查找/二分查找 以及二叉树的 三种遍历方式

二分查找   线性查找 1.二分查找 public class BinarySearch { /** * 二分查找 * @param data * @return */ public int binarySearch(long[] data,long n) { //左右 端点 int left =0; int right =data.length-1; //中间元素 int mid=-1; while(left<right){ // 有两种情况 1.left = right 2. left>r

Map集合的四种遍历方式

很久以前写的代码,和上一个做比较吧!便于以后查看 1 import java.util.HashMap; 2 import java.util.Iterator; 3 import java.util.Map; 4 5 public class TestMap { 6 public static void main(String[] args) { 7 Map<Integer, String> map = new HashMap<Integer, String>(); 8 map.

map的四种遍历方式

import java.util.HashMap;import java.util.Iterator;import java.util.Map; public class TestMap { public static void main(String[] args) { Map<Integer, String> map = new HashMap<Integer, String>(); map.put(1, "a"); map.put(2, "b&q

java list 的 四种遍历方式

在java中遍历一个list对象的方法主要有以下四种: 1. For Loop —— 普通for循环 2. Advanced For Loop —— 高级for循环 3. Iterator Loop —— 迭代器遍历 4. While Loop —— while循环 具体可以参考以下代码: import java.util.ArrayList; import java.util.Iterator; import java.util.List; public class Main { public

Map集合的四种遍历方式,自己记录,方便以后查询参考!

1 import java.util.HashMap; 2 import java.util.Iterator; 3 import java.util.Map; 4 5 public class TestMap { 6 public static void main(String[] args) { 7 Map<Integer, String> map = new HashMap<Integer, String>(); 8 map.put(1, "a"); 9