队列是一种列表,但是它只能够在队尾插入元素,在队首删除元素。队列用于存储按照顺序排列的数据,先进先出。而栈则是后入栈的元素反而被优先处理。

实际中一般被应用在进程池、排队操作上面。

1. 队列的操作

  和上一章的栈类似,队列也应该具有入队、出队、清空队列这几个基本操作。

  基本结构如下:

function Queue(){
    this.dataStore = [];
    this.enqueue = enqueue;
    this.dequeue = dequeue;
    this.front = front;
    this.back = back;
    this.isEmpty = isEmpty;    this.clear = clear;}

2.一个用数组实现的队列

  入队操作:  

function enqueue(elem){
    this.dataStore.push(elem);
}

出队操作(弹出数组头部元素):

function dequeue(){
    return this.dataStore.shft();
}

返回队首和队尾元素:

function front(){
    return this.dataStore[0]
}
function back(){
    return this.dataStore[this.dataStore.length-1];
}

判断队列是否为空:

function empty(){
   if(this.dataStore.length>0){
        return true;
   }else{
        return false;
   }
}

清空队列操作和其他操作一致,返回长度直接return this.dataStore.length即可。

3.方块舞的舞伴分配问题

首先我们要有舞池中的舞者Dancer:

function Dancer(name, sex){
   this.name = name;
   this.sex = sex;
}

然后我们再将舞者添加进入到队列中:

var maleQueue = new Queue();var femaleQueue = new Queue();
femaleQueue.enqueue(new Dancer('Herry', 'F')); femaleQueue.enqueue(new Dancer('Kerry', 'F')); 
maleQueue.enqueue(new Dancer('Jimmy', 'M')); maleQueue.enqueue(new Dancer('Lisa', 'M')); maleQueue.enqueue(new Dancer('Lima', 'M'));

匹配舞者:

function dance(males, females){
    console.info("The dancer partners are: \n");
    var person;
    while(!males.empty() && !females.empty()){
        person = males.dequeue();
        console.info("The Male is " + person.name);
        person = females.dequeue();
        console.info("The Female is " + person.name);
    }
    console.info('\n');
    while(!males.empty()){
        person = males.dequeue();
        console.info(person.name + " is waiting!");
    }
    while(!females.empty()){
        person = females.dequeue();
        console.info(person.name + " is waiting!");
    }
}

测试:

dance(femaleQueue, maleQueue);

4.对数据进行排序

使用队列排序并非是效率最高的排序算法,只能说是一个种比较有趣的方式,

我们在排序时,根据不同的位数进行排序:

比如有一组数字:

82,13,33,98,93,12, 5,88,3

我们先对其个位数进行一次排序:

0:

1:

2: 82, 12

3: 13, 33, 93, 3

4:

5: 5

6:

7:

8: 98, 88

9:

将其中的数字依次取出,可得到:

98,88,5,13,33,93,3,82,12

然后根据十位数字进行排序

0:

1:13,12

2:

3:33

4:

5:

6:

7:

8: 88, 82

9: 98, 93

取出数据:

98,93,88,82,33,13,12

再加上没剩余的个位数字:

98,93,88,82,33,13,12,5,3

实现:

首先我们要实现把一组数根据不同的位数分配到0~9十个队列中去

/**
*    nums ----- 要排序的数组
*    queues ----- 存放 0~9 十位数的队列数组
*    n ----- 对nums中的前n个数进行排序
*      digit ----- 对对应排序的位数
*/
function distribute(nums, queues, n, digit){

    //    队列下标
    var index = 0;

    //    遍历整个n个数
    for(var i=0;i<n;i++){

        //    如果求个位数
        if(digit == 1){

            //    不能被10整除的部分为对应队列的下标
            index = nums[i] % 10; 

            //    将当前数据加入队列
            queues[index].enqueue(nums[i]);
        }else{

            //    获取能被10整除的部分为对应队列的下标
            index = Math.floor(nums[i]/10); 

            //    将当前数据加入队列
            queues[index].enqueue(nums[i]);
        }
    }
}

每次进行分配后,我们都要进行一次出队操作,放到新的数组中去:

/**
*    queues ----- 存放 0~9 十位数的队列数组
*    nums ----- 存放结果的数组
**/
function collect(queues, nums){

    //    数组下标
    var i = 0;

    //    遍历所有10组队列
    for(var digit=0; digit<10;digit++){

        //    将不为空的队列元素依次做出队操作
        while(!queues[digit].empty()){

            //    将队列中的元素添加到新的数组当中
            nums[i++] = queues[digit].dequeue();
        }
    }
}

显示数组结果:

//    依次显示数组内容
function dispArray(arr){
    for(var i=0;i<arr.length;i++){
        console.info(arr[i] + " ");
    }
}

测试:

 //    初始化一个队列数组,用于存放所有0~9十个数字的队列
 var queues = [];
 for(var i=0; i<10; i++){
     queues[i] = new Queue();
 }

 //    初始化存放最后结果的数组
 var nums = [];

 //    随机生成十个 1~99的整数
 for(var i=0;i<10;i++){
     nums[i] = Math.floor(Math.floor(Math.random() * 101));
 }

 console.info("Before radix sort:");
 dispArray(nums);

 //    根据个位数排序加入队列中
 distribute(nums, queues, 10, 1);

 //    将第一次排序完的队列中的数存放到新数组中去
 collect(queues, nums)

 //    根据十位数排序加入队列中
 distribute(nums, queues, 10, 10);

 //    将第二次排序完的队列中的数存放到新数组中去
 collect(queues, nums);

 console.info('\n\n After radix sort:');
 dispArray(nums);

5.优先队列

我们知道普通情况下队列采取先进先出的方式进行出队操作,但是这种方式不能满足一些特殊情况,例如如果我们有排队时,会有vip成员,这样就需要我们去重写dequeue除对操作了

我们可以在队列中的对象上添加一个code属性,表明该变量的优先级:

function Customer(name, code){
      this.name = name;
      this.code = code;    this.toString = function(){         console.info(this.name+":"+this.code);      };}
var ord1 = new Customer('Jimmery', 1);
var ord2 = new Customer('Kate', 1);
var ord3 = new Customer('Lame', 1);

var vip1 = new Customer('Andy', 2);
var vip2 = new Customer('Dave', 2);

var cusQueues = new Queue();
cusQueues.push(ord1);
cusQueues.push(vip1);
cusQueues.push(ord2);
cusQueues.push(vip2);
cusQueues.push(ord3);

这样我们做出队操作时,就要进行对优先级的比较:

var dequeue = function(){

   //  获取当前第一个元素的优先级
   var prio = this.dataStore[0].code;

   //    获取初始化下标
   var index = 0;
   for(var i=1; i<this.dataStore.length; i++){

        //  优先级值越大优先级越高
        if(this.dataStore[i].code>prio){

               //  记录下优先级最高元素的下标
               index = i;
        }
   }

   return this.dataStore.splice(index, 1);
} 

现在我们进行测试,进行出队操作:

while(!cusQueues.empty()){
    var cus = cusQueues.dequeue();
    console.info(cus.toString());
}

javascript 数据结构和算法读书笔记 > 第五章 队列的更多相关文章

  1. javascript 数据结构和算法读书笔记 > 第四章 栈

    1. 对栈的操作 栈是一种特殊的列表,栈中的元素只能通过列表的一端进行访问,即栈顶.类似于累起一摞的盘子,只能最后被放在上面的,最先能被访问到. 就是我们所说的后入先出(LIFO). 对栈主要有入栈p ...

  2. javascript 数据结构和算法读书笔记 > 第三章 列表

    1. 结构分析 列表首先要有以下几个属性: listSize 长度 pos 当前位置 dataStore 数据 我们要通过以下方法对上面三个属性进行操作: length() 获取长度 | getPos ...

  3. javascript 数据结构和算法读书笔记 > 第二章 数组

    这章主要讲解了数组的工作原理和其适用场景. 定义: 一个存储元素的线性集合,元素可以通过索引来任意存取,索引通常是数字,用来计算元素之间存储位置的偏移量. javascript数组的特殊之处: jav ...

  4. javascript 数据结构和算法读书笔记 > 第一章 javascript的编程环境和模型

    1.变量的声明和初始化 必须使用关键字 var,后跟变量名,后面还可以跟一个赋值表达式. var name; var age = 5; var str = 'hello'; var flg = fal ...

  5. 《Linux内核设计与实现》第四周读书笔记——第五章

    <Linux内核设计与实现>第四周读书笔记--第五章 20135301张忻 估算学习时间:共1.5小时 读书:1.0 代码:0 作业:0 博客:0.5 实际学习时间:共2.0小时 读书:1 ...

  6. 《Linux内核设计与实现》读书笔记——第五章

    <Linux内核设计与实现>读书笔记--第五章 标签(空格分隔): 20135321余佳源 第五章 系统调用 操作系统中,内核提供了用户进程与内核进行交互的一组接口.这些接口让应用程序受限 ...

  7. 深入Java虚拟机读书笔记第五章Java虚拟机

    Java虚拟机 Java虚拟机之所以被称之为是虚拟的,就是因为它仅仅是由一个规范来定义的抽象计算机.因此,要运行某个Java程序,首先需要一个符合该规范的具体实现. Java虚拟机的生命周期 一个运行 ...

  8. 《Linux内核设计与实现》读书笔记 第五章 系统调用

    第五章系统调用 系统调用是用户进程与内核进行交互的接口.为了保护系统稳定可靠,避免应用程序恣意忘形. 5.1与内核通信 系统调用在用户空间进程和硬件设备间添加了一个中间层, 作用:为用户空间提供了一种 ...

  9. Getting Started With Hazelcast 读书笔记(第五章,第六章)

    第五章 监听 本章应该是Hazelcast的核心机制了,Hazelcast通过注册各种监听器获悉集群中其他应用对数据的修改,成员的加入,退出等. 分为3个层次. 1.EntryListener(对数据 ...

随机推荐

  1. 《JavaScript权威指南》读书笔记2

    3.6-3.8 这三章主要介绍了JS的包装对象.不可变的原始值和可变的对象引用.JS中的类型转换. 包装对象主要指当原始值需要调用一些方法的时候(原始值本身是不能通过"."来调用的 ...

  2. Python之路第八天,基础(9)-面向对象(下)

    类的成员 类的成员可以分为三大类:字段.方法和属性 注:所有成员中,只有普通字段的内容保存对象中,即:根据此类创建了多少对象,在内存中就有多少个普通字段.而其他的成员,则都是保存在类中,即:无论对象的 ...

  3. SQL Server 提高创建索引速度的 2 个方法

    方法 1. 使用tempdb来提速 create index index_name on table_name (column_list) with(sort_in_tempdb = on); 方法 ...

  4. android textView 富文本显示

    String parenName = entity.getParent().getMember_nickname(); parantNameRich = "<font color='# ...

  5. C# 动态语言特性,dynamic 关键字研究

    1       动态语言简介 支持动态特性的语言现在大行其道,并且有继续增长的趋势.比如 Ruby 和 Python, 还有天王级的巨星 --- JavaScript. 现在一个程序员说自己对 Jav ...

  6. Inno Setup 打包工具总结(转)

    最近打包用到了Inno setup,在这个过程中容易犯一些低级错误,特别写出来已提醒自己 1.打包文件夹 打包文件按照向导来一般没什么问题,但文件夹就不一样了.向导生成的打包文件夹的代码如下: Sou ...

  7. Android仿微信图片上传,可以选择多张图片,缩放预览,拍照上传等

    仿照微信,朋友圈分享图片功能 .可以进行图片的多张选择,拍照添加图片,以及进行图片的预览,预览时可以进行缩放,并且可以删除选中状态的图片 .很不错的源码,大家有需要可以下载看看 . 微信 微信 微信 ...

  8. Android之用PopupWindow实现弹出listview形式菜单

    Android 4.0之前的菜单使用非常广泛,但是在android4.0之后,很少使用先前的菜单样式了.那如何实现下图的样式了? 我们简单模拟一下. (1)屏蔽系统弹出的菜单: 1.首先创建至少一个系 ...

  9. Node.js log3:create ejs engine and jade engine

    The base condition is ensure that you have  installed express. 1.create   ejs engine Using windows d ...

  10. [Leetcode][Python]45: Jump Game II

    # -*- coding: utf8 -*-'''__author__ = 'dabay.wang@gmail.com' 45: Jump Game IIhttps://oj.leetcode.com ...