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 判断打开的是文件 还是 文件夹的实例

    要利用 Node.js 判断打开的是文件还是文件夹,可以使用 Node.js 核心模块 fs (file system) 模块中的 statSync() 方法。 statSync() 方法可以返回该文件或文件夹的状态,通过它的 isFile() 和 isDirectory() 方法,可以判断是文件还是文件夹。 以下是示例: 1. 判断文件是否存在 const…

    node js 2023年6月8日
    00
  • Angularjs—项目搭建图文教程

    AngularJS 项目搭建图文教程 AngularJS 是一款流行的前端 JavaScript 框架,它可以帮助开发者快速构建单页应用程序。本文将演示如何在自己的电脑上搭建 AngularJS 项目的环境并进行开发。 1. 安装 Node.js Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行环境。安装了 Node.js,…

    node js 2023年6月8日
    00
  • node.js中的emitter.emit方法使用说明

    我们来详细讲解一下”node.js中的emitter.emit方法使用说明”的完整攻略。 什么是EventEmitter EventEmitter是Node.js的一个重要模块,用来实现事件的订阅和发布。它是实现事件驱动编程的基础,同时它也是Node.js中许多API的基础。 EventEmitter是一个构造函数,在使用它之前需要通过require(‘ev…

    node js 2023年6月8日
    00
  • 详解webpack编译多页面vue项目的配置问题

    下面我将详细讲解webpack编译多页面vue项目的配置问题的完整攻略。 背景介绍 在实际项目中,我们可能需要使用vue框架来开发多个独立的页面,这时我们需要使用webpack来对这些页面进行打包编译。在vue-cli的默认配置中,webpack只会编译单页面应用,在多页面应用中需要对webpack进行一些配置才能实现编译多个页面。 配置方式 设置entry…

    node js 2023年6月9日
    00
  • 测试驱动ChatGPT编程示例详解

    下面就是测试驱动ChatGPT编程示例的完整攻略: 总述 第一步是准备好ChatGPT模型。ChatGPT是一种语言模型,可以进行自然语言生成。它的原理是基于大量文本数据进行训练,并且在训练好的基础上进行生成。 第二步是准备好ChatGPT的测试数据集。这个测试数据集可以来源于真实的人机对话,也可以仿真出来。测试数据集的作用是验证ChatGPT模型的生成效果…

    node js 2023年6月8日
    00
  • 详解如何在Node.js的httpServer中接收前端发送的arraybuffer数据

    要在 Node.js 的 httpServer 中接收前端发送的 ArrayBuffer 数据,按照以下步骤进行: 创建 HTTP 服务器 在 Node.js 中,可以使用 http 模块创建 HTTP 服务器。使用 http.createServer() 方法创建一个服务器对象,并设置响应请求的回调函数。示例代码如下: const http = requi…

    node js 2023年6月8日
    00
  • Javascript JSQL,SQL无处不在,

    JavaScript JSQL是一种使用JavaScript语言实现的数据库访问接口。它通过封装SQL命令,提供了一种直接使用JavaScript语言进行数据库访问的方式。很多JavaScript的开发者已经在使用JSQL来处理数据库了,本文将讲解如何在项目中使用JSQL,包括连接数据库、创建表和查询数据库等操作。 连接数据库 要使用JSQL,首先需要连接你…

    node js 2023年6月8日
    00
  • JavaScipt中栈的实现方法

    JavaScript中栈的实现方法 什么是栈 栈(Stack)是一种遵循后进先出(LIFO)原则的一种数据结构,类似于一摞书或光盘。在栈中,进行插入操作的一段被称为栈顶,而进行删除操作的一端被称为栈底。 在JavaScript中,栈主要用于实现函数调用堆栈。当函数嵌套调用时,需要将当前函数的状态(变量、参数等)以及下一步要执行的指令等信息保存在栈中;当函数调…

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