ningendo

递归遍历各种数据结构,深入理解前序遍历,后续遍历,深度优先dfs。

一.递归遍历数组

public class Graph4Test {
    public static void main(String[] args) {
        int[] a1 = new int[]{1,2,3,4,5,6};
        preOrder(a1,0);
        System.out.println();
        postOrder(a1,0);
    }
  //前序遍历
    private static void preOrder(int[] a,int pos) {
    //递归退出条件 ,即当前索引下标值 > 数组的length
if(a.length-1<pos){ return; } System.out.print(a[pos]+","); preOrder(a,pos+1); }   //后续遍历 private static void postOrder(int[] a,int pos) { if(a.length-1<pos){ return; } postOrder(a,pos+1); System.out.print(a[pos]+","); } }

输出:

1,2,3,4,5,6,
6,5,4,3,2,1,

 

前序遍历调用

 

 

 后序遍历调用,后序遍历的话,是先一直递归查找到最后一个元素,才开始调用打印,所以是从后往前打印

 

 

 .递归遍历链表

链表的递归遍历同数组的一样

 

public class ListTest1 {
    public static void main(String[] args) {
        ListNode l1 = LinkListUtil.geneLinkList(new int[]{1,2,3,4,5,6});
        preOrder(l1);
        System.out.println();
        postOrder(l1);
    }
//前序遍历
    private static void preOrder(ListNode l){
//递归的退出条件,指向链表的当前指针为空
if(l==null){ return; } System.out.print(l.getVal()+","); preOrder(l.getNext()); } //后序遍历 private static void postOrder(ListNode l){ if(l==null){ return; } postOrder(l.getNext()); System.out.print(l.getVal()+","); } }

 

输出:

1,2,3,4,5,6,
6,5,4,3,2,1,

 

三.递归遍历二叉树

 

 

 

public class BTTest2 {
    public static void main(String[] args) {
        TreeNode n1 = BTUtils.generateTreeNode(new Integer[]{1,2,3,4,null,5,6});
        preOrder(n1);
        System.out.println();
        postOrder(n1);
    }
//前序遍历
    private static void preOrder(TreeNode root){
        if(root==null){
            return;
        }
        System.out.print(root.getVal()+",");
        preOrder(root.getLeft());
        preOrder(root.getRight());
    }
//后序遍历
    private static void postOrder(TreeNode root){
        if(root==null){
            return;
        }
        preOrder(root.getLeft());
        preOrder(root.getRight());
        System.out.print(root.getVal()+",");
    }
}

输出:

1,2,4,3,5,6,
4,2,5,6,3,1,

 

前序遍历调用过程

 

 

 后序遍历调用过程

 

 

 

 

四.递归遍历多叉树,森林

 

 

 前序遍历

public class NTreeTest1{
    public static void main(String[] args) {
        Node r1 = new Node(1);
        Node r21 = new Node(3);
        Node r22 = new Node(2);
        Node r23 = new Node(4);
        Node r31 = new Node(5);
        Node r32 = new Node(6);
        r21.children.add(r31);
        r21.children.add(r32);
        r1.children.add(r21);
        r1.children.add(r22);
        r1.children.add(r23);

        List<Integer> preorder = preorder(r1);
        ArrayUtils.displayArray(preorder);
    }

    public static List<Integer> preorder(Node root) {
        List<Integer> list = new ArrayList<>();
        preorder(root,list);
        return list;
    }

    private static void preorder(Node root,List<Integer> list){
        if(root==null){
            return;
        }
        list.add(root.val);
        for (int i = 0; i < root.children.size(); i++) {
            preorder(root.children.get(i),list);
        }
    }
}

输出: [1,3,5,6,2,4]

 

后序遍历

public class NTreeTest2{
    public static void main(String[] args) {
        Node r1 = new Node(1);
        Node r21 = new Node(3);
        Node r22 = new Node(2);
        Node r23 = new Node(4);
        Node r31 = new Node(5);
        Node r32 = new Node(6);
        r21.children.add(r31);
        r21.children.add(r32);
        r1.children.add(r21);
        r1.children.add(r22);
        r1.children.add(r23);

        List<Integer> preorder = postorder(r1);
        ArrayUtils.displayArray(preorder);
    }

    public static List<Integer> postorder(Node root) {
        List<Integer> list = new ArrayList<>();
        postorder(root,list);
        return list;
    }

    private static void postorder(Node root,List<Integer> list){
        if(root==null){
            return;
        }
        for (int i = 0; i < root.children.size(); i++) {
            postorder(root.children.get(i),list);
        }
        list.add(root.val);
    }
}

输出 : [5,6,3,2,4,1]

思路和二叉树一样 ,只是把二叉树的 root.left 和root.right  改成  for循环遍历 root.children罢了.

 

五.递归遍历图,深度优先遍历 dfs

test1方法的图 ,和多叉树一样                      邻接表

 

 

 

 

 

 

test2方法的图                                                     邻接表

 

 

 

 

 

 

graph.java

因为图可能带环,所以用一个 Set<T> visited  来保存遍历过的图节点

 

public class Graph<T> {
//邻接表,这里用一个hashMap 来实现
private Map<T,LinkedList<T>> adj = new HashMap<>(); public void addEdge(T begin, T end) { if(!adj.containsKey(begin)){ adj.put(begin,new LinkedList<T>()); } if(!adj.containsKey(end)){ adj.put(end,new LinkedList<T>()); } adj.get(begin).addLast(end); adj.get(end).addLast(begin); } private void dfs(T v, Set<T> visited) {
//或者在这里加上递归退出条件,该节点遍历过就退出
    //if(visited.contains(v){
    //return;
//}
visited.add(v); System.out.print(v
+ " "); LinkedList<T> linkedList = adj.get(v);
//找邻接表的元素,从第一个元素开始找,一直找节点的邻接表的第一个,找到没有位置,或者遍历过位置
for (T t : linkedList) { if (!visited.contains(t)){ dfs(t, visited); } } } public void dfs(T v) { Set<T> visited = new HashSet<>(); dfs(v, visited); } }
GraphNode.java
public class GraphNode {
    private int val;

    public GraphNode(int val) {
        this.val = val;
    }

    public int getVal() {
        return val;
    }

    public void setVal(int val) {
        this.val = val;
    }

    @Override
    public String toString() {
        return "GraphNode{" +
                "val=" + val +
                '}';
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        GraphNode graphNode = (GraphNode) o;
        return val == graphNode.val;
    }

    @Override
    public int hashCode() {
        return Objects.hash(val);
    }
}
Graph3Test.java
public class Graph3Test {
    public static void main(String[] args) {
        test1();
        System.out.println();
        test2();
    }

    private static void test1(){
        Graph<GraphNode> graph = new Graph<>();
        GraphNode n1 = new GraphNode(1);
        GraphNode n2 = new GraphNode(2);
        GraphNode n3 = new GraphNode(3);
        GraphNode n4 = new GraphNode(4);
        graph.addEdge(n1,n2);
        graph.addEdge(n1,n3);
        graph.addEdge(n1,n4);

        graph.dfs(n1);
    }

    private static void test2(){
        Graph<GraphNode> graph = new Graph<>();
        GraphNode n1 = new GraphNode(1);
        GraphNode n2 = new GraphNode(2);
        GraphNode n3 = new GraphNode(3);
        GraphNode n4 = new GraphNode(4);
        GraphNode n5 = new GraphNode(5);
        graph.addEdge(n1,n2);
        graph.addEdge(n1,n3);
        graph.addEdge(n1,n4);
        graph.addEdge(n2,n5);
        graph.addEdge(n2,n4);

        graph.dfs(n1);
    }
}

输出:

GraphNode{val=1} GraphNode{val=2} GraphNode{val=3} GraphNode{val=4}
GraphNode{val=1} GraphNode{val=2} GraphNode{val=5} GraphNode{val=4} GraphNode{val=3}

 

test1 的调用过程

 

 test2 的调用过程

 

 

 

%3CmxGraphModel%3E%3Croot%3E%3CmxCell%20id%3D%220%22%2F%3E%3CmxCell%20id%3D%221%22%20parent%3D%220%22%2F%3E%3CmxCell%20id%3D%222%22%20style%3D%22edgeStyle%3Dnone%3Brounded%3D0%3BorthogonalLoop%3D1%3BjettySize%3Dauto%3Bhtml%3D1%3BentryX%3D0.867%3BentryY%3D0.086%3BentryDx%3D0%3BentryDy%3D0%3BentryPerimeter%3D0%3BstrokeColor%3D%23000000%3Bshape%3Dlink%3B%22%20edge%3D%221%22%20source%3D%225%22%20target%3D%226%22%20parent%3D%221%22%3E%3CmxGeometry%20relative%3D%221%22%20as%3D%22geometry%22%2F%3E%3C%2FmxCell%3E%3CmxCell%20id%3D%223%22%20style%3D%22edgeStyle%3Dnone%3Brounded%3D0%3BorthogonalLoop%3D1%3BjettySize%3Dauto%3Bhtml%3D1%3Bshape%3Dlink%3B%22%20edge%3D%221%22%20source%3D%225%22%20target%3D%227%22%20parent%3D%221%22%3E%3CmxGeometry%20relative%3D%221%22%20as%3D%22geometry%22%2F%3E%3C%2FmxCell%3E%3CmxCell%20id%3D%224%22%20style%3D%22edgeStyle%3Dnone%3Brounded%3D0%3BorthogonalLoop%3D1%3BjettySize%3Dauto%3Bhtml%3D1%3BentryX%3D0.083%3BentryY%3D0.214%3BentryDx%3D0%3BentryDy%3D0%3BentryPerimeter%3D0%3Bshape%3Dlink%3B%22%20edge%3D%221%22%20source%3D%225%22%20target%3D%228%22%20parent%3D%221%22%3E%3CmxGeometry%20relative%3D%221%22%20as%3D%22geometry%22%2F%3E%3C%2FmxCell%3E%3CmxCell%20id%3D%225%22%20value%3D%221%22%20style%3D%22shape%3Dmxgraph.flowchart.on-page_reference%3B%22%20vertex%3D%221%22%20parent%3D%221%22%3E%3CmxGeometry%20x%3D%22140%22%20y%3D%221998%22%20width%3D%2230%22%20height%3D%2235%22%20as%3D%22geometry%22%2F%3E%3C%2FmxCell%3E%3CmxCell%20id%3D%226%22%20value%3D%222%22%20style%3D%22shape%3Dmxgraph.flowchart.on-page_reference%3B%22%20vertex%3D%221%22%20parent%3D%221%22%3E%3CmxGeometry%20x%3D%2295%22%20y%3D%222062%22%20width%3D%2230%22%20height%3D%2235%22%20as%3D%22geometry%22%2F%3E%3C%2FmxCell%3E%3CmxCell%20id%3D%227%22%20value%3D%223%22%20style%3D%22shape%3Dmxgraph.flowchart.on-page_reference%3B%22%20vertex%3D%221%22%20parent%3D%221%22%3E%3CmxGeometry%20x%3D%22175%22%20y%3D%222072%22%20width%3D%2230%22%20height%3D%2235%22%20as%3D%22geometry%22%2F%3E%3C%2FmxCell%3E%3CmxCell%20id%3D%228%22%20value%3D%224%22%20style%3D%22shape%3Dmxgraph.flowchart.on-page_reference%3B%22%20vertex%3D%221%22%20parent%3D%221%22%3E%3CmxGeometry%20x%3D%22245.5%22%20y%3D%222054.5%22%20width%3D%2230%22%20height%3D%2235%22%20as%3D%22geometry%22%2F%3E%3C%2FmxCell%3E%3C%2Froot%3E%3C%2FmxGraphModel%3E

posted on 2021-01-16 02:35  Lunamonna  阅读(78)  评论(0编辑  收藏  举报

导航