美文网首页
树的遍历

树的遍历

作者: CokeCode | 来源:发表于2021-06-17 00:43 被阅读0次

节点结构:

public class TreeNode {
    public int val;
    public TreeNode left;
    public TreeNode right;
    
    public TreeNode() {
    }
    
    public TreeNode(int x) {
        val = x;
    }
}

先序遍历

递归

public void preOrder(TreeNode tree) {
    if (tree == null) 
        return;
    processNode(tree); // 处理节点的逻辑抽象
    preOrder(tree.left);
    preOrder(tree.right);
}

非递归

public void preOrder(TreeNode tree) {
    if (tree == null)
        return;
    Stack<TreeNode> s = new Stack<>();
    s.push(tree); 
    while (!s.isEmpty()) {
        TreeNode node = s.pop();
        processNode(node); // 处理节点的逻辑抽象
        if (node.right != null) { // 先入栈右子节点
            s.push(node.right);
        }
        if (node.left != null) {
            s.push(node.left);
        }
    }
}

后序遍历

递归

public void postOrder(TreeNode tree) {
    if (tree == null) 
        return;
    postOrder(tree.left);
    postOrder(tree.right);
    processNode(tree); // 处理节点的逻辑抽象
}

非递归

public void postOrder(TreeNode tree) {
    if (tree == null)
        return;
    Stack<TreeNode> s1 = new Stack<>();
    Stack<TreeNode> s2 = new Stack<>();
    s1.push(tree); 
    while (!s1.isEmpty()) {
        tree = s1.pop();
        s2.push(tree);
        if (tree.left != null) {
            s1.push(tree.left); // 先入栈左子节点
        }
        if (tree.right != null) { 
            s1.push(tree.right);
        }
    }
    while (!s2.isEmpty()) {
        processNode(s2.pop()); // 处理节点的逻辑抽象
    }
}

中序遍历

递归

public void inOrder(TreeNode tree) {
    if (tree == null) 
        return;
    inOrder(tree.left);
    processNode(tree); // 处理节点的逻辑抽象
    inOrder(tree.right);
}

非递归

public void inOrder(TreeNode tree) {
    Stack<TreeNode> s = new Stack<>();
    while (tree != null || !s.isEmpty()) {
        while (tree != null) {
            s.push(tree);
            tree = tree.left;
        }
        if (!s.isEmpty()) {
            tree = s.pop();
            processNode(tree); // 处理节点的逻辑抽象
            tree = tree.right;
        }
    }
}

层序遍历

public void levelOrder(TreeNode tree) {
    if (tree == null)
        return;
    Queue<TreeNode> q = new LinkedList<>();
    q.add(tree);
    while (!q.isEmpty()) {
        tree = q.poll();
        processNode(tree); // 处理节点的逻辑抽象
        if (tree.left != null)
            q.add(tree.left);
        if (tree.right != null)
            q.add(tree.right);
    }
}

类库

有了上述遍历算法实现后,我们建立类库,主要是:(1)通过泛型增加程序的通用性,(2)面向接口编程,(3)能够被实际开发生产使用。

@FunctionalInterface
public interface Node<T> {
    T getValue();
}
import lombok.*;

@Data
@NoArgsConstructor
@AllArgsConstructor
@RequiredArgsConstructor
public class TreeNode<T> implements Node<T> {
    @NonNull protected T value;
    protected TreeNode left;
    protected TreeNode right;
}
@FunctionalInterface
public interface Visitor<T> {
    void process(Node<T> node);
}
import java.util.LinkedList;
import java.util.Queue;
import java.util.Stack;

@FunctionalInterface
public interface TreeVisitor<T> extends Visitor<T> {

    default void preOrder(TreeNode<T> tree) {
        preOrder(tree, false);
    }

    default void preOrder(TreeNode<T> tree, boolean recursive) {
        if (recursive)
            preOrderRecursive(tree);
        else
            preOrderNonRecursive(tree);
    }

    default void preOrderRecursive(TreeNode<T> tree) {
        if (tree == null)
            return;
        process(tree);
        preOrderRecursive(tree.getLeft());
        preOrderRecursive(tree.right);
    }

    default void preOrderNonRecursive(TreeNode<T> tree) {
        if (tree == null)
            return;
        Stack<TreeNode<T>> s = new Stack<>();
        s.push(tree);
        while (!s.isEmpty()) {
            TreeNode<T> node = s.pop();
            process(node);
            if (node.right != null) { // 先入栈右子节点
                s.push(node.right);
            }
            if (node.left != null) {
                s.push(node.left);
            }
        }
    }

    default void postOrder(TreeNode<T> tree) {
        postOrder(tree, false);
    }

    default void postOrder(TreeNode<T> tree, boolean recursive) {
        if (recursive) 
            postOrderRecursive(tree);
        else
            postOrderNonRecursive(tree);
    }

    default void postOrderRecursive(TreeNode<T> tree) {
        if (tree == null)
            return;
        postOrderRecursive(tree.left);
        postOrderRecursive(tree.right);
        process(tree);
    }

    default void postOrderNonRecursive(TreeNode<T> tree) {
        if (tree == null)
            return;
        Stack<TreeNode<T>> s1 = new Stack<>();
        Stack<TreeNode<T>> s2 = new Stack<>();
        s1.push(tree);
        while (!s1.isEmpty()) {
            tree = s1.pop();
            s2.push(tree);
            if (tree.left != null) {
                s1.push(tree.left); // 先入栈左子节点
            }
            if (tree.right != null) {
                s1.push(tree.right);
            }
        }
        while (!s2.isEmpty()) {
            process(s2.pop());
        }
    }
    
    default void inOrder(TreeNode<T> tree) {
        inOrder(tree, false);
    }

    default void inOrder(TreeNode<T> tree, boolean recursive) {
        if (recursive)
            inOrderRecursive(tree);
        else
            inOrderNonRecursive(tree);
    }
    
    default void inOrderRecursive(TreeNode<T> tree) {
        if (tree == null)
            return;
        inOrderRecursive(tree.left);
        process(tree);
        inOrderRecursive(tree.right);
    }

    default void inOrderNonRecursive(TreeNode<T> tree) {
        Stack<TreeNode<T>> s = new Stack<>();
        while (tree != null || !s.isEmpty()) {
            while (tree != null) {
                s.push(tree);
                tree = tree.left;
            }
            if (!s.isEmpty()) {
                tree = s.pop();
                process(tree);
                tree = tree.right;
            }
        }
    }

    default void levelOrder(TreeNode<T> tree) {
        if (tree == null)
            return;
        Queue<TreeNode<T>> q = new LinkedList<>();
        q.add(tree);
        while (!q.isEmpty()) {
            tree = q.poll();
            process(tree);
            if (tree.left != null)
                q.add(tree.left);
            if (tree.right != null)
                q.add(tree.right);
        }
    }
}

在测试中使用上面的类库:

import org.junit.jupiter.api.Test;

public class TestClass {
    @Test
    void test1() {
        TreeVisitor<Integer> visitor = (n) -> System.out.println(n.getValue());
        TreeNode<Integer> left = new TreeNode<>(2);
        TreeNode<Integer> right = new TreeNode<>(3);
        TreeNode<Integer> root = new TreeNode<>(1, left, right);

        visitor.inOrder(root);
    }

    @Test
    void test2() {
        TreeVisitor<Integer> visitor = node -> {
            TreeNode<Integer> tn = (TreeNode<Integer>) node;
            System.out.println(tn.getLeft());
        };
        TreeNode<Integer> left = new TreeNode<>(2);
        TreeNode<Integer> right = new TreeNode<>(3);
        TreeNode<Integer> root = new TreeNode<>(1, left, right);

        visitor.inOrder(root);
    }
}

相关文章

  • 树的遍历算法

    树的递归遍历 树的层次遍历 树的非递归前序遍历 树的非递归中序遍历

  • 图的深度优先遍历

    数据结构遍历的意义 树的遍历 图的遍历 树的前序遍历 图遍历和树遍历区别 知识回顾 树的深度优先遍历 普通函数和递...

  • 树的遍历

    N叉树的遍历 N叉树的前序遍历 N叉树的后序遍历 N叉树的层序遍历 二叉树 鉴于递归法遍历比较简单,就不重复写了 ...

  • 数据结构与算法之二叉树遍历(七)

    目录 前序遍历中序遍历后序遍历层序遍历遍历方式的选择条件根据遍历结果重构二叉树翻转二叉树计算二叉树的高度判断一棵树...

  • 数据结构——树和森林的遍历方法

    树的遍历 1、树的遍历的定义:以某种方式访问树中的每一个结点,且仅访问一次。 树的遍历主要有先根遍历和后根遍历。2...

  • 二叉树的遍历

    二叉树的遍历 二叉树遍历 分为前序遍历、中序遍历和后序遍历。 前序遍历 (DLR) 先访问根节点,然后前序遍历左子...

  • 数据结构:树的实现和遍历(c++)

    (一)二叉树的遍历——递归实现 二叉树常见的遍历方式分为前序遍历、中序遍历和后序遍历。 1 前序遍历 前序遍历也叫...

  • js二叉树(前中后序遍历)+多叉树(深度优先遍历和广度优先遍历)

    ?二叉树三种遍历 和 多叉树 深度优先遍历和广度优先遍历 二叉树遍历 先序遍历(根左右) 中序遍历(左根右) 后序...

  • 2021-04-14(冒泡递归)

    树的遍历之先序遍历二叉树 1. 遍历简介: 树作为非线性数据结构,在我们取出数据时就需要设计遍历,所谓遍历,就是按...

  • 树和森林的遍历

    树的遍历 先根遍历若树非空,则先访问根结点,再按从左到右的顺序遍历根结点的每棵子树树先根遍历:RADEBCFGHK...

网友评论

      本文标题:树的遍历

      本文链接:https://www.haomeiwen.com/subject/lbofyltx.html