二叉树的遍历

一、概述

二叉树的遍历分为两种,第一种是层序遍历,从根节点开始,依次向下,对于每一层从左向右遍历。第二种是先、中、后序遍历,遍历顺序都是相对于父节点,也就是先遍历父节点、中间遍历父节点、最后遍历父节点

二、层序遍历

层序遍历用到了队列

算法步骤

初始时,根节点入队列

然后,while循环判断队列不为空时,弹出一个节点,访问它,并把它的所有孩子节点入队列

代码实现

public void levelTraverse(BinarySearchTree<T> tree){
    levelTraverse(tree.root);
}
private void levelTraverse(BinaryNode<T> root){
    if(root == null)
        return;
    
    Queue<BinaryNode<T>> queue = new LinkedList<>();//层序遍历时保存结点的队列
    queue.offer(root);//初始化
    while(!queue.isEmpty()){
        BinaryNode<T> node = queue.poll();
        System.out.print(node.element + " ");//访问节点
        if(node.left != null)
            queue.offer(node.left);
        if(node.right != null)
            queue.offer(node.right);
    }
}

queue的offer方法是将数据添加到队列尾部

queue的poll方法是删除队列的头节点

三、先、中、后序遍历

有两种方式,一种是递归实现,另一种是用堆栈实现

先创建一颗树

public class Node {  
private int data;  
private Node leftNode;  
private Node rightNode;  
public Node(int data, Node leftNode, Node rightNode){  
    this.data = data;  
    this.leftNode = leftNode;  
    this.rightNode = rightNode;  
}  

public int getData() {  
    return data;  
}  
public void setData(int data) {  
    this.data = data;  
}  
public Node getLeftNode() {  
    return leftNode;  
}  
public void setLeftNode(Node leftNode) {  
    this.leftNode = leftNode;  
}  
public Node getRightNode() {  
    return rightNode;  
}  
public void setRightNode(Node rightNode) {  
    this.rightNode = rightNode;  
}  
}

递归实现

public class BinaryTree {  
/** 
 * @author yaobo
 * 二叉树的先序中序后序排序 
 */  
public Node init() {//注意必须逆序建立,先建立子节点,再逆序往上建立,因为非叶子结点会使用到下面的节点,而初始化是按顺序初始化的,不逆序建立会报错  
    Node J = new Node(8, null, null);  
    Node H = new Node(4, null, null);  
    Node G = new Node(2, null, null);  
    Node F = new Node(7, null, J);  
    Node E = new Node(5, H, null);  
    Node D = new Node(1, null, G);  
    Node C = new Node(9, F, null);  
    Node B = new Node(3, D, E);  
    Node A = new Node(6, B, C);  
    return A;   //返回根节点  
}

public void printNode(Node node){  
    System.out.print(node.getData());  
}  
public void theFirstTraversal(Node root) {  //先序遍历  
    printNode(root);  
    if (root.getLeftNode() != null) {  //使用递归进行遍历左孩子  
        theFirstTraversal(root.getLeftNode());  
    }  
    if (root.getRightNode() != null) {  //递归遍历右孩子  
        theFirstTraversal(root.getRightNode());  
    }  
}  
public void theInOrderTraversal(Node root) {  //中序遍历  
    if (root.getLeftNode() != null) {  
        theInOrderTraversal(root.getLeftNode());  
    }  
    printNode(root);  
    if (root.getRightNode() != null) {  
        theInOrderTraversal(root.getRightNode());  
    }  
}


public void thePostOrderTraversal(Node root) {  //后序遍历  
    if (root.getLeftNode() != null) {  
        thePostOrderTraversal(root.getLeftNode());  
    }  
    if(root.getRightNode() != null) {  
        thePostOrderTraversal(root.getRightNode());  
    }  
    printNode(root);  
}  
  
public static void main(String[] args) {  
    BinaryTree tree = new BinaryTree();  
    Node root = tree.init();  
    System.out.println("先序遍历");  
    tree.theFirstTraversal(root);  
    System.out.println("");  
    System.out.println("中序遍历");  
    tree.theInOrderTraversal(root);  
    System.out.println("");  
    System.out.println("后序遍历");  
    tree.thePostOrderTraversal(root);  
    System.out.println("");  
}  
}

堆栈实现

public class BinaryTree1 { 
 public Node init() {//注意必须逆序建立,先建立子节点,再逆序往上建立,因为非叶子结点会使用到下面的节点,而初始化是按顺序初始化的,不逆序建立会报错  
        Node J = new Node(8, null, null);  
        Node H = new Node(4, null, null);  
        Node G = new Node(2, null, null);  
        Node F = new Node(7, null, J);  
        Node E = new Node(5, H, null);  
        Node D = new Node(1, null, G);  
        Node C = new Node(9, F, null);  
        Node B = new Node(3, D, E);  
        Node A = new Node(6, B, C);  
        return A;   //返回根节点  
    } 

public void printNode(Node node){  
    System.out.print(node.getData());  
}


public void theFirstTraversal_Stack(Node root) {  //先序遍历  
    Stack<Node> stack = new Stack<Node>();  
    Node node = root;  
    while (node != null || stack.size() > 0) {  //将所有左孩子压栈  
        if (node != null) {   //压栈之前先访问  
            printNode(node);  
            stack.push(node);  
            node = node.getLeftNode();  
        } else {  
            node = stack.pop();  //为了获取父节点
            node = node.getRightNode();  
        }  
    }  
}  
  
public void theInOrderTraversal_Stack(Node root) {  //中序遍历  
    Stack<Node> stack = new Stack<Node>();  
    Node node = root;  
    while (node != null || stack.size() > 0) {  
        if (node != null) {  
            stack.push(node);   //直接压栈  
            node = node.getLeftNode();  
        } else {  
            node = stack.pop(); //出栈并访问  
            printNode(node);  
            node = node.getRightNode(); 
        }  
    }  
}  
  
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();
        }  
    }  
    System.out.println(output.size());
    while (output.size() > 0) {
        
        printNode(output.pop());  
    }  
}

public static void main(String[] args) {  
    BinaryTree1 tree = new BinaryTree1();  
    Node root = tree.init();  
    System.out.println("先序遍历");  
    tree.theFirstTraversal_Stack(root);  
    System.out.println("");  
    System.out.println("中序遍历");  
    tree.theInOrderTraversal_Stack(root);  
    System.out.println("");  
    System.out.println("后序遍历");  
    tree.thePostOrderTraversal_Stack(root);  
    System.out.println("");  
}
}

pop方法是删除头节点元素

push方法是将元素添加到链表头部

posted @ 2018-09-03 10:24  StoneGeek  阅读(185)  评论(0编辑  收藏  举报