javascript 数据结构和算法读书笔记 > 第五章 队列
队列是一种列表,但是它只能够在队尾插入元素,在队首删除元素。队列用于存储按照顺序排列的数据,先进先出。而栈则是后入栈的元素反而被优先处理。
实际中一般被应用在进程池、排队操作上面。
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 数据结构和算法读书笔记 > 第五章 队列的更多相关文章
- javascript 数据结构和算法读书笔记 > 第四章 栈
1. 对栈的操作 栈是一种特殊的列表,栈中的元素只能通过列表的一端进行访问,即栈顶.类似于累起一摞的盘子,只能最后被放在上面的,最先能被访问到. 就是我们所说的后入先出(LIFO). 对栈主要有入栈p ...
- javascript 数据结构和算法读书笔记 > 第三章 列表
1. 结构分析 列表首先要有以下几个属性: listSize 长度 pos 当前位置 dataStore 数据 我们要通过以下方法对上面三个属性进行操作: length() 获取长度 | getPos ...
- javascript 数据结构和算法读书笔记 > 第二章 数组
这章主要讲解了数组的工作原理和其适用场景. 定义: 一个存储元素的线性集合,元素可以通过索引来任意存取,索引通常是数字,用来计算元素之间存储位置的偏移量. javascript数组的特殊之处: jav ...
- javascript 数据结构和算法读书笔记 > 第一章 javascript的编程环境和模型
1.变量的声明和初始化 必须使用关键字 var,后跟变量名,后面还可以跟一个赋值表达式. var name; var age = 5; var str = 'hello'; var flg = fal ...
- 《Linux内核设计与实现》第四周读书笔记——第五章
<Linux内核设计与实现>第四周读书笔记--第五章 20135301张忻 估算学习时间:共1.5小时 读书:1.0 代码:0 作业:0 博客:0.5 实际学习时间:共2.0小时 读书:1 ...
- 《Linux内核设计与实现》读书笔记——第五章
<Linux内核设计与实现>读书笔记--第五章 标签(空格分隔): 20135321余佳源 第五章 系统调用 操作系统中,内核提供了用户进程与内核进行交互的一组接口.这些接口让应用程序受限 ...
- 深入Java虚拟机读书笔记第五章Java虚拟机
Java虚拟机 Java虚拟机之所以被称之为是虚拟的,就是因为它仅仅是由一个规范来定义的抽象计算机.因此,要运行某个Java程序,首先需要一个符合该规范的具体实现. Java虚拟机的生命周期 一个运行 ...
- 《Linux内核设计与实现》读书笔记 第五章 系统调用
第五章系统调用 系统调用是用户进程与内核进行交互的接口.为了保护系统稳定可靠,避免应用程序恣意忘形. 5.1与内核通信 系统调用在用户空间进程和硬件设备间添加了一个中间层, 作用:为用户空间提供了一种 ...
- Getting Started With Hazelcast 读书笔记(第五章,第六章)
第五章 监听 本章应该是Hazelcast的核心机制了,Hazelcast通过注册各种监听器获悉集群中其他应用对数据的修改,成员的加入,退出等. 分为3个层次. 1.EntryListener(对数据 ...
随机推荐
- 纯Html+Ajax和JSP两者对比的个人理解
最近写个人web,用jsp+servlet做,突然想到一个问题:html+ajax似乎和jsp实现效果一样:那么,两者到底有什么区别呢? 这里参考老猿的一段话: 全站ajax会维护大量的js代码,如何 ...
- [STOI2014]舞伴(dp)
STOI是汕头OI...无聊翻到了去年的比赛题目,就写然后自己测了一下. 其实我很想吐槽为什么题目名是perm,perm好像和舞伴完全无关.. dp(x,s)=∑dp(x-1,s-{i}))(0< ...
- php中Maximum execution time of 120 seconds exceeded时间超时错误解决方案
1.修改php的配置文件,找到php.ini文件 max_execution_time = 120 ;//设置成你想要的值,单位是秒 2.使用ini_set()函数,使用这个函数来改变你的最大执行时间 ...
- 去除除服串中的某些字符,不用String内置方法
import java.util.regex.Matcher; import java.util.regex.Pattern; public class test { public static vo ...
- synchronized 方式实现监控器中数据成员的同步
要对监控器中的数据成员进行访问,在考虑到多线程的情况下必须使用同步代码块来改变监控器中数据成员的值: synchronized (mAdapterLocking) { if (pEvery == 0) ...
- 使用runtime 实现weex 跳转原生页面
一.简述 最近项目组打算引入weex,并选定了一个页面进行试水.页面很简单,主要是获取数据渲染页面,并可以跳转到指定的页面.跟之前使用RN 相比,weex 确实要简单很多.从下图中我们可以看到,wee ...
- multiprocessing跨平台锁的使用(Windows问题)
在Windows上可能遇到,开启的子进程不会关闭的问题 参考multiprocessing官方文档: Explicitly pass resources to child processes On U ...
- 字符串水题(hdoj1049)
Problem Description Password security is a tricky thing. Users prefer simple passwords that are easy ...
- 定制化Azure站点Java运行环境(3)
定制化Azure Website提供的默认的Tomcat和JDK环境 在我们之前的测试中,如果你访问你的WEB站点URL时不加任何上下文,实际上你看到的web界面是系统自带的测试页面index.jsp ...
- 解决nginx上传模块nginx_upload_module传递GET参数
解决nginx上传模块nginx_upload_module传递GET参数的方法总结 最近用户反映我们的系统只能上传50M大小的文件, 希望能够支持上传更大的文件. 很显然PHP无法轻易实现大文件上传 ...