算法複習之二叉樹的遍歷

節點類:

public class Node <T>{
    public T data;
    public Node<T> left = null;
    public Node<T> right = null;
    public Node(T data) {
        super();
        this.data = data;
    }
}

先根遍歷:先訪問根節點元素,然再訪問左右子樹節點

    /**
     * 遞歸方法
     * @param root
     */
    public <T> void  traverse(Node<T> root){
        if(root == null){
            return ;
        }
        out.println(root.data);
        traverse(root.left);
        traverse(root.right);
    }
    /**
     * 非遞歸方法,利用LinkedList模擬函數棧
     * @param root
     */
    public <T> void  traverse2(Node<T> root){
        LinkedList<Node<T>> list = new LinkedList<>();
        list.push(root);
        while(list.size()>0){
            Node<T> now = list.pop();
            if(now==null){
                continue;
            }
            out.println(now.data);
            list.push(now.right);//先添加右節點再添加左節點確保左節點先被訪問
            list.push(now.left);
        }
    }
}

中根遍歷

package binaryTree;

import java.io.PrintStream;
import java.util.LinkedList;

import org.junit.Test;

public class InorderTraversal {
    protected PrintStream out =null;
    public void setOut(PrintStream out) {
        this.out = out;
    }
    /**
     * 遞歸方法
     * @param root
     */
    public <T> void  traverse(Node<T> root){
        if(root == null){
            return ;
        }
        traverse(root.left);
        out.println(root.data);
        traverse(root.right);
    }
    /**
     * 非遞歸方法,利用2個LinkedList模擬遍歷過程,第一個棧中存放第二個棧頂元素的左節點,第一個棧空,說明第二個棧頂元素左節點訪問完畢
     * @param root
     */
    public <T> void  traverse2(Node<T> root){
        LinkedList<Node<T>> first = new LinkedList<>();
        LinkedList<Node<T>> secend = new LinkedList<>();
        first.push(root);
        while(first.size()>0||secend.size()>0){
            if(first.size()==0){
                Node<T> now = secend.removeLast();
                out.println(now.data);
                if(now.right!=null){
                    first.push(now.right);
                }
                continue;
            }
            Node<T> now = first.pop();
            secend.add(now);
            if(now.left!=null){
                first.add(now.left);
            }
        }
    }
    /**
     * 非遞歸方法,利用LinkedList模擬棧,now指向stack棧頂元素的左子樹,now指向空,說明棧頂元素左子樹訪問完畢
     * @param root
     */
    public <T> void  traverse3(Node<T> root){
        LinkedList<Node<T>> stack = new LinkedList<>();
        Node<T> now  = root;
        while(now!=null||stack.size()>0){
            if(now==null){
                now = stack.pop();
                out.println(now.data);
                now=now.right;
            }else{
                stack.push(now);
                now = now.left;
            }
        }
    }
}

後根遍歷:

package binaryTree;

import java.io.PrintStream;
import java.util.LinkedList;

import org.junit.Test;

public class PostorderTraversal {
    protected PrintStream out =null;
    public void setOut(PrintStream out) {
        this.out = out;
    }
    /**
     * 遞歸方法
     * @param root
     */
    public <T> void  traverse(Node<T> root){
        if(root == null){
            return ;
        }
        traverse(root.left);
        traverse(root.right);
        out.println(root.data);
    }
    /**
     * 非遞歸方法,利用兩個指針,stack中記錄訪問過的節點
     * @param root
     */
    public <T> void  traverse2(Node<T> root){
        LinkedList<Node<T>> stack = new LinkedList<>();
        Node<T> now ;
        Node<T> pre = null;
        stack.push(root);
        while(stack.size()>0){
            now = stack.peek();
            if((now.left==null&&now.right==null)||
                ( pre!=null&&(pre==now.left||pre==now.right)) ){//now沒有子節點或者上次訪問的節點是now的子節點
                out.println(now.data);
                stack.pop();
                pre = now;
            }else{
                if(now.right!=null){
                    stack.push(now.right);
                }
                if(now.left!=null){
                    stack.push(now.left);
                }
            }
        }
    }
}

層次遍歷:

package binaryTree;

import java.io.PrintStream;
import java.util.LinkedList;

import org.junit.Test;

public class LevelTraversal {
    protected PrintStream out =null;
    public void setOut(PrintStream out) {
        this.out = out;
    }
    /**
     * 非遞歸方法,利用LinkedList模擬隊列,很簡單
     * @param root
     */
    public <T> void  traverse(Node<T> root){
        LinkedList<Node<T>> queue = new LinkedList<>();
        Node<T> now ;
        queue.offer(root);
        while(queue.size()>0){
            now = queue.poll();
            out.println(now.data);
            if(now.left!=null) queue.add(now.left);
            if(now.right!=null) queue.add(now.right);
        }
    }
}

測試函數:

@Test
    public void test(){
        Node<Integer> root1 = new Node<Integer>(1);
        Node<Integer> root2 = new Node<Integer>(2);
        Node<Integer> root3 = new Node<Integer>(3);
        Node<Integer> root4 = new Node<Integer>(4);
        Node<Integer> root5 = new Node<Integer>(5);
        Node<Integer> root6 = new Node<Integer>(6);
        Node<Integer> root7 = new Node<Integer>(7);
        this.out = System.out;
        root1.left = root2;
        root1.right = root5;
        root2.left = root3;
        root2.right = root4;
        root5.left = root6;
        root5.right = root7;
        traverse(root1);
    }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章