深入理解栈和队列, BFS & DFS

文章目录

    • 背景
    • 队列的基本概念
      • 入队
      • 出队
    • 栈的基本概念
      • 入栈
      • 出栈
    • BFS的基本概念
    • DFS的基本概念
    • 实际应用
      • 二叉树广度优先遍历
      • 验证括号
      • 拓展题目

若文章对你有帮助请点个, 表示对我的鼓励, 非常感谢 ❤️❤️❤️

背景

为了让程序有自己的灵魂, 以及锻炼自己的思维逻辑能力. 特此学习了下Leetcode的栈和队列, 受益良多, 因此写下感受来使更多人看见, 方便他人. 欢迎大家提意见.

面向刚刷leetcode的新人和对数据结构不了解的人.

队列的基本概念

队列的基本思想就是先入队的最先出队(FIFO).

深入理解栈和队列, BFS & DFS_第1张图片

入队

基于上图中, 往队列中加入一个元素.
深入理解栈和队列, BFS & DFS_第2张图片

出队

从队列中移除一个元素.
深入理解栈和队列, BFS & DFS_第3张图片

深入理解栈和队列, BFS & DFS_第4张图片

栈的基本概念

栈与队列相反, 栈是先入后入的数据结构(FILO).

深入理解栈和队列, BFS & DFS_第5张图片

入栈

栈的元素入栈之后, 落入栈的顶端.
深入理解栈和队列, BFS & DFS_第6张图片

出栈

出栈的元素从栈顶进行移出.
深入理解栈和队列, BFS & DFS_第7张图片

深入理解栈和队列, BFS & DFS_第8张图片

BFS的基本概念

BFS是广度优先搜索, 该算法主要是用来遍历树和图. 它的基本思想是从根节点开始, 依次遍历距离根节点最近的节点.

深入理解栈和队列, BFS & DFS_第9张图片

所以上图的广度优先遍历顺序为: 1, 2, 3, 4, 5, 6, 7

DFS的基本概念

DFS是深度优先搜索, 也是用来遍历树和图. 它的基本思想是从根节点开始访问, 然后尽可能地往深处访问. 如果发现已经访问到叶子节点或者该节点的分支已经全部访问, 则回溯到父节点.

假设有一树如下图所示, 现在要用DFS访问该树的所有节点.
深入理解栈和队列, BFS & DFS_第10张图片

以下是深度优先访问的节点的顺序:
深入理解栈和队列, BFS & DFS_第11张图片
深入理解栈和队列, BFS & DFS_第12张图片

实际应用

基于以上的说明, 来实际编写两道

二叉树广度优先遍历

Leetcode 102 题

public List<List<Integer>> levelOrder(TreeNode root) {
    if(root == null) return new ArrayList<>();
    List<List<Integer>> result = new ArrayList<>();
    LinkedList<TreeNode> queue = new LinkedList<TreeNode>();
    queue.offer(root);
    while(!queue.isEmpty()) {
        List<Integer> levelNodes = new ArrayList<>();
        int curLength = queue.size();
        // 开始遍历每一层
        for(int i = 0; i < curLength; i++) {
            TreeNode curNode = queue.poll();
            levelNodes.add(curNode.val);
            // 如果有孩子节点则加入队列中.
            if(curNode.left != null) queue.offer(curNode.left);
            if(curNode.right != null) queue.offer(curNode.right);
        }
        // 将该层添加到结果集
        result.add(levelNodes);
    }
    return result;
}

验证括号

Leetcode 第20题 Valid Parentheses

public boolean isValid(String s) {
    if(s == null || s.length() == 0) return true;
    Stack<Character> stack = new Stack<>();
    for(char c : s.toCharArray()) {
        // 如果匹配到左边的符号, 则将右边的符号放入进去.
        if( c == '(') {
            stack.push(')');
        } else if( c == '{') {
            stack.push('}');
        } else if( c == '['){
            stack.push(']');
        } else if(!stack.isEmpty()) {
            // 现在遍历到右边的符号,这是栈顶的元素一定和右边符号相等才行.
            if(stack.peek() == c) {
                stack.pop();
            } else {
                return false;
            }
        } else {
            return false;
        }
    }
    return stack.isEmpty();
}

拓展题目

二叉树的广度和深度优先遍历只是为了解释栈, 队列在BFS和DFS扮演的作用. 在真实的应用中, 要比两个复杂许多.

  1. Leetcode 第94题 Binary Tree Inorder Traversal
  2. Leetcode 第200题 Number of Islands
  3. Leetcode 第279题 Perfect Squares

你可能感兴趣的:(算法,leetcode,栈,队列,bfs,dfs)