• 数据结构之栈和队列


    栈和队列是计算机中基本的两个数据结构,栈可以达到后进先出,队列可以先进先出。在实际应用上,我们可以使用栈进行逆序遍历链表,非递归中序遍历二叉树,括号匹配,函数调用等等;可以使用队列对二叉树进行层次遍历,打印机的打印服务,通信中的消息队列等等。

    下面贴几道关于栈和队列较常考的笔试/面试题。

    链表逆序遍历:思想很简单,当链表节点不为null就进行压栈,直到为null。

    class Node2{
        int value;
        Node2 next;
    }
        
    public void reservePrintList(Node2 root) {
            
        if (root == null) {
            return;
        }
            
        Stack<Node2> stack = new Stack<>();
        while (root !=null) {
            stack.push(root);
            root = root.next;
        }
            
        while (!stack.isEmpty()) {
            System.out.println(stack.pop().value);
        }
    }

    非递归中序遍历二叉树:中序遍历二叉树第一个被遍历的节点肯定位于二叉树的最左边,在未到最左边之前一直压栈,到了就出栈。

    class Node{
        int value;
        Node left;
        Node right;
    }
    /**
     * 非递归中序遍历二叉树,利用栈可以很方便的实现
     * @param root
     */
    public void printTree1(Node root) {
            
        if (root == null) {
            return;
        }
            
        Stack<Node> stack = new Stack<>();
        while (root != null) {
            stack.push(root);  // 根节点压栈
            if (root.left != null) { // 左子树不为空,将左子树压入栈
                stack.push(root.left);
            }else {
                // root的左子树为空,说明root要么是叶子,要么是还有右子树,不管是叶子还是有右子树的节点,它都将进行输出
                // 因为中序遍历的的顺序是从左到右
                Node node = stack.pop(); 
                System.out.println(node.value);
                if (node.right != null) {
                    // 存在右子树,将右子节点压栈,因为不清楚右子节点是否为叶子,所以是压栈进行下一轮循环进行处理
                    stack.push(node.right);
                }
                    
                root = stack.peek(); // 取栈顶元素,但不移除,因为不清楚目前栈顶节点是否为叶子
            }
        }
            
    }

    二叉树层次遍历:层次遍历值对二叉树从上到下进行一层层的遍历,每层的遍历顺序为从左到右,借助队列可以很容易实现

    class Node{
            int value;
            Node left;
            Node right;
    }
    /**
    * 层次遍历二叉树(从上到下),借助队列这一数据结构可以很好的实现
    * @param root
    */
    public void printTree2(Node root) {
            
        if (root == null) {
            return;
        }
            
        Queue<Node> queue = new LinkedList<>();
        queue.add(root); // 将根节点加入队列
        while (root != null) {
            Node node = queue.poll(); // 取出队头root
            if (node.left != null) { // 左子节点不为空,入队
                queue.offer(root.left);
            }
            if (node.right != null) { // 右子节点不为空 ,入队
                queue.offer(root.right);
            }
            System.out.println(node.value); // 打印队头元素
            root = queue.peek();    // 获取新的队头元素,但不移除,更新为root
        }
    }

    看师弟师妹们数据机构第三章的总结,都是自行实现栈和队列这两个数据结构,我上面贴出的代码没有进行栈或队列满的判断,这是因为我偷懒直接使用java类库,java类库里的栈或队列都是在超过初始容量后自动扩容的(最大容量好像int类型最大的整数)。C++也是直接把栈和队列封装好可以直接使用,但是在学习的时候建议还是先理解底层原理,自己实现,等底层原理熟练就直接用封装好的类,还有就是建议师弟师妹们要多去敲代码,不能说基本理论原理了解了,就不去使用代码进行实现,理论和代码实现还是有一定差别的,在代码实现过程中,可能会出现一些bug,不要怕bug,虽然bug的确很烦,一个引用出错就找了几小时(我的惨痛经历),但是解决bug后下次我们就可以更好的避免同类型的bug了。

      

  • 相关阅读:
    C#网络编程之Http请求
    使用 pdf.js 在网页中加载 pdf 文件
    程序员转型技术管理,这几本书不能错过
    HTTPS小结 、TSL、SSL
    clipboard 在 vue 项目中,on 事件监听回调多次执行
    Vue 引入 .md 文件,解析markdown语法
    Vue cli4.0 代理配置
    npm publish 一直报错 404
    JSON 多层对象获取键值
    Tomcat8配置Https协议,Tomcat配置Https安全访问,Tomcat Https配置
  • 原文地址:https://www.cnblogs.com/X-huang/p/10679408.html
Copyright © 2020-2023  润新知