JS中队列和双端队列实现及应用详解

JS中队列和双端队列实现及应用详解

什么是队列?

队列是指一种线性数据结构,它按照先进先出(FIFO)的原则进行排序。队列只允许在后端(称为tail)进行插入操作,在前端(称为head)进行删除操作。例如,当你在一家银行排队等待服务时,由于先来的人先获得服务的原则,所以你必须在队列中等待,直到你到达前面。当有人从银行窗口出来时,他们排在你的前面的所有人都必须离开,直到你才能接受服务。

在编程中,队列常见的应用场景包括:任务调度,缓存管理以及消息队列等。

队列的实现

使用数组实现队列

最简单的实现方式就是使用数组来模拟队列。我们可以使用push方法往数组的尾部插入元素,使用shift方法从数组的头部删除元素。这样就能够满足队列的先进先出原则。

class Queue {
  constructor() {
    this.elements = [];
  }

  enqueue(element) {
    this.elements.push(element);
  }

  dequeue() {
    return this.elements.shift();
  }

  isEmpty() {
    return this.elements.length == 0;
  }

  size() {
    return this.elements.length;
  }
}

双端队列的实现

双端队列是队列的一种扩展,它允许我们在头部和尾部同时进行插入和删除操作。这种特性使得双端队列非常适合用来实现某些算法和数据结构,如双端搜索、滑动窗口等。

在JavaScript中,我们可以使用数组来模拟双端队列。我们可以使用push方法往数组的尾部插入元素,使用shift方法从数组的头部删除元素,使用unshift方法从数组的头部插入元素,使用pop方法从数组的尾部删除元素。

class Deque {
  constructor() {
    this.elements = [];
  }

  addFront(element) {
    this.elements.unshift(element);
  }

  addBack(element) {
    this.elements.push(element);
  }

  removeFront() {
    return this.elements.shift();
  }

  removeBack() {
    return this.elements.pop();
  }

  isEmpty() {
    return this.elements.length == 0;
  }

  size() {
    return this.elements.length;
  }
}

应用场景

任务调度

在任务调度中,队列被用于维护待执行任务的队列。每个任务都被封装为一个函数,当任务执行完毕时,我们将其从队列中删除。任务调度器不断地从队列中取出任务并执行,直到队列为空。

function taskA() {
  console.log("Task A");
}

function taskB() {
  console.log("Task B");
}

function taskC() {
  console.log("Task C");
}

class Scheduler {
  constructor() {
    this.queue = new Queue();
    this.maxConcurrent = 2;
    this.running = 0;
  }

  addTask(task) {
    this.queue.enqueue(task);
    this.schedule();
  }

  schedule() {
    while (!this.queue.isEmpty() && this.running < this.maxConcurrent) {
      const task = this.queue.dequeue();
      task();
      this.running++;
      setTimeout(() => {
        this.running--;
        this.schedule();
      }, 1000);
    }
  }
}

const scheduler = new Scheduler();
scheduler.addTask(taskA);
scheduler.addTask(taskB);
scheduler.addTask(taskC);

上面的代码中,我们定义了三个任务taskA、taskB和taskC,并将它们添加到任务调度队列中。我们使用Scheduler类来管理任务调度,它的addTask方法用于添加任务。我们使用了一个while循环来检查队列中是否有任务可供执行,同时也保证了我们的任务调度器最多会同时执行两个任务。

滑动窗口

滑动窗口算法是一种用于解决字符串和数组问题的常用算法,它可以用队列来实现。滑动窗口算法用来在一个大字符串中寻找一个长度固定的子串,满足一些限定条件。

function findSubstring(s, t) {
  const n = s.length, m = t.length;
  const ans = [];

  if (n < m) return ans;

  const cntS = new Array(128).fill(0);
  const cntT = new Array(128).fill(0);

  for (let i = 0; i < m; i++) {
    cntT[t.charCodeAt(i)]++;
  }

  const check = () => {
    for (let i = 0; i < 128; i++) {
      if (cntT[i] > cntS[i]) return false;
    }
    return true;
  }

  for (let i = 0; i < m; i++) {
    cntS[s.charCodeAt(i)]++;
  }

  if (check()) ans.push(0);

  for (let i = m; i < n; i++) {
    cntS[s.charCodeAt(i - m)]--;
    cntS[s.charCodeAt(i)]++;
    if (check()) ans.push(i - m + 1);
  }

  return ans;
}

上面的代码中,我们定义了一个findSubstring方法,用于在字符串s中寻找子串t。我们首先统计了子串t中每个字符的出现次数,并存储在cntT数组中。然后,我们设定一个长度为m的窗口,从字符串s的开头向右滑动。每次滑动窗口,我们都会更新cntS数组,它存储了当前窗口中每个字符的出现次数。如果当前窗口中的字符出现次数满足要求,那么我们就将窗口的起始位置加入到答案列表中。

总结

队列和双端队列是非常常见的数据结构,它们具有广泛的应用场景。JavaScript提供了很多实现队列和双端队列的方法,包括使用数组实现,使用链表实现等等。在实际开发中,我们通常会选择最简单、最直接的实现方式,以便能够满足我们的需求。在设计算法和数据结构时,我们需要根据具体情况灵活地选择合适的数据结构以及相应的实现方式。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:JS中队列和双端队列实现及应用详解 - Python技术站

(0)
上一篇 2023年6月8日
下一篇 2023年6月8日

相关文章

  • 教你用Node.js与Express建立一个GraphQL服务器

    使用Node.js与Express建立GraphQL服务器的完整攻略 什么是GraphQL? GraphQL是一个用于API开发的查询语言和运行时。与REST API不同,GraphQL由客户端定义查询,使得客户端不必多次请求服务器,从而节省了带宽和时间。GraphQL也具有灵活性和可扩展性,因此常被用于构建大型应用程序。 准备工作 在开始构建GraphQL…

    node js 2023年6月8日
    00
  • Centos7 中 Node.js安装简单方法

    下面是详细的“Centos7 中 Node.js安装简单方法”的完整攻略: 简介 Node.js是一种基于Chrome JavaScript Runtime建立的一个平台,用于方便地构建快速、可扩展的网络应用程序。本文旨在介绍Centos7上安装Node.js的简单方法。 步骤一:下载Node.js二进制包 打开终端,输入以下命令下载Node.js最新版本的…

    node js 2023年6月8日
    00
  • nodejs异步编程基础之回调函数用法分析

    Node.js异步编程基础之回调函数用法分析 在 Node.js 中使用异步编程非常重要,因为 Node.js 应用程序一般都需要处理高并发、高 I/O 的情况。而回调函数是 Node.js 中异步编程的基础。 本篇攻略主要介绍 Node.js 中回调函数的用法,重点讲解如何编写和调用回调函数,以及如何处理回调函数中出现的错误。 什么是回调函数 回调函数是一…

    node js 2023年6月8日
    00
  • Node.js实用代码段之获取Buffer对象字节长度

    获取Buffer对象字节长度是在Node.js中处理二进制数据时非常常见的操作之一。本文将介绍如何在Node.js中获取Buffer对象字节长度的各种方法以及它们的优缺点。 1.使用Buffer.length获取字节长度 通过Buffer.length属性可以获取Buffer对象的字节长度。这种方法对于小型的Buffer对象非常有效,但是当需要处理大型的Bu…

    node js 2023年6月8日
    00
  • Node.js 进程平滑离场剖析小结

    Node.js 进程平滑离场剖析是指在 Node.js 应用程序运行过程中,如何平滑地结束进程,避免出现异常情况和数据丢失。下面是几个关键步骤: 1. 理解Node.js应用程序的运行模式 Node.js 应用程序的运行模式是“单线程、异步 I/O、事件循环”的模式。这意味着在 Node.js 应用程序中,多个操作可以同时进行,而不必等待之前的操作完成。这是…

    node js 2023年6月8日
    00
  • 深入内存原理谈JS中变量存储在堆中还是栈中

    如你所知,JavaScript是一门高级编程语言,它通常被认为是一种解释型语言,这意味着变量在代码运行时被计算机直接处理,而不是像编译型语言一样在编译时分配内存。那么,JavaScript中的变量存储在哪里呢?这就需要深入了解内存的工作原理了。 内存的工作原理 内存可以看作是一块计算机储存数据的区域,它是所有运行的程序都需要的基本元素之一。通常,内存被分为堆…

    node js 2023年6月8日
    00
  • Nodejs中koa2连接mysql的实现示例

    下面我将为您详细讲解“Nodejs中koa2连接mysql的实现示例”的完整攻略。 简介 Koa2 是一个轻量级 web 开发框架,适用于中小型 Web 应用的开发。它基于 ES6 的 Generator 实现异步流程控制,再配合上现代的语法,让我们的代码更加简洁,可读性也更强。而 MySQL 则是一款轻量级的关系型数据库,它可以支持多种前端和后端语言,因此…

    node js 2023年6月8日
    00
  • node基于express框架操作Mysql数据库的步骤

    下面我来为您详细讲解如何基于Express框架操作Mysql数据库,步骤如下: 1. 安装依赖 首先,我们需要安装以下依赖: npm install express mysql –save 其中,express 是框架,mysql 是操作 Mysql 数据库的库。–save 表示将依赖保存到 package.json 文件中。 2. 配置数据库连接 在程…

    node js 2023年6月8日
    00
合作推广
合作推广
分享本页
返回顶部