JavaScript算法练习之队列

什么是队列

队列是一种列表,不同的是队列只能在队尾插入元素,在队首删除元素。队列用于存储按 顺序排列的数据,先进先出,这点和栈不一样,在栈中,最后入栈的元素反而被优先处 理。
队列是一种先进先出(First-In-First-Out,FIFO)的数据结构。

队列的实现

在JavaScript中,我们可以用如下函数实现队列:

 function Queue() {
    this.dataStore = [];
    this.enqueue = enqueue;
    this.dequeue = dequeue;
    this.front = front;
    this.back = back;
    this.toString = toString;
    this.empty = empty;
    this.count = count;
}
//enqueue() 方法向队尾添加一个元素:
function enqueue(element) {
    this
        .dataStore
        .push(element);
}
// dequeue() 方法删除队首的元素:
function dequeue() {
    return this
        .dataStore
        .shift();
}

// front() 读取队首元素:
function front() {
    return this.dataStore[0];
}

// back 读取队尾的元素:
function back() {
    return this.dataStore[this.dataStore.length - 1];
}

// toString() 显示队列内的所有元素
function toString() {
    var retStr = "";
    for (var i = 0; i < this.dataStore.length; ++i) {
        retStr += this.dataStore[i] + "\n";
    }
  return retStr;
}
//判断队列是否为空:
  function empty() {
   if (this.dataStore.length == 0) {
    return true;
  } else {
      return false;
  }
}

//显示元素个数
function count() {
    return this.dataStore.length;
}

实战

习题一

使用队列来模拟跳方块舞的人。当 男男女女来到舞池,他们按照自己的性别排成两队。当舞池中有地方空出来时,选两个队 列中的第一个人组成舞伴。他们身后的人各自向前移动一位,变成新的队首。当一对舞伴 迈入舞池时,主持人会大声喊出他们的名字。当一对舞伴走出舞池,且两排队伍中有任意 一队没人时,主持人也会把这个情况告诉大家。

代码如下:

  // 模拟舞会成员
  var dancers = [
    'F Allison McMillan',
    'M Frank Opitz',
    'M Mason McMillan',
    'M Clayton Ruff',
    'F Cheryl Ferenback',
    'M Raymond Williams',
    'F Jennifer Ingram',
    'M Bryan Frazer',
    'M David Durr',
    'M Danny Martin',
    'F Aurora Adney'
];

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

// 对跳舞的成员按性别分组
function getDancers(males, females) {
    var dancer,
        sex,
        name;
      for (var i = 0; i < dancers.length - 1; i++) {
        dancer = dancers[i].split(' ');
        sex = dancer[0];
        name = dancer[1];
        if (sex === 'F') {
            females.enqueue(new Dancer(name, sex));
        } else {
            males.enqueue(new Dancer(name, sex));
        }
    }
}
// 进入舞池跳舞
function dance(males, females) {
    console.log('The dance partners are: \n');
    var person;
    while (!females.empty() && !males.empty()) {
        person = females.dequeue();
        console.log("Female dancer is: " + person.name);
        person = males.dequeue();
        console.log(" and the male dancer is: " + person.name);
    }
}

var maleDancers = new Queue();
var femaleDancers = new Queue();
getDancers(maleDancers, femaleDancers);
dance(maleDancers, femaleDancers);

if (!femaleDancers.empty()) {
    console.log(femaleDancers.front().name + " is waiting to dance.");
}
if (!maleDancers.empty()) {
    console.log(maleDancers.front().name + " is waiting to dance.");
}

结果如下:

The dance partners are: 

Female dancer is: Allison and the male dancer is: Frank
Female dancer is: Cheryl  and the male dancer is: Mason
Female dancer is: Jennifer and the male dancer is: Clayton
Raymond is waiting to dance.

习题二

对于 0~99 的数字,基数排序将数据集扫描两次。第一次按个位上的数字进行排序,第二 次按十位上的数字进行排序。每个数字根据对应位上的数值被分在不同的盒子里。
用以上算法对数据进行排序。

思路:

我们需要九个队列,每个对应一个数字。将所有 队列保存在一个数组中,使用取余和除法操作决定个位和十位。算法的剩余部分将数字加 入相应的队列,根据个位数值对其重新排序,然后再根据十位上的数值进行排序,结果即 为排好序的数字。

// nums 要排序的数字数组。 queues 0-9队列数组 n 数字的个数 digit 按个位还是十位排序
function distribute(nums, queues, n, digit) {
    for (var i = 0; i < n - 1; i++) {
        if (digit == 1) {
            queues[nums[i] % 10].enqueue(nums[i]);
        } else {
            queues[Math.floor(nums[i] / 10)].enqueue(nums[i])
        }
    }
}

// 从队列中收集数字
function collect(queues, nums) {
    var i = 0;
    for (var digit = 0; digit < 10; digit++) {
        while (!queues[digit].empty()) {
            nums[i++] = queues[digit].dequeue();
        }
    }
}

// 显示数组

function dispArray(arr) {
    console.log(arr);
}

var queues = [];
for (var i = 0; i < 10; i++) {
    queues[i] = new Queue();
}

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

console.log("Before radix sort: ");
dispArray(nums);
distribute(nums, queues, 10, 1);
collect(queues, nums);
distribute(nums, queues, 10, 10);
collect(queues, nums);
console.log("\n\nAfter radix sort: ");
dispArray(nums);

结果可能如下:

  Before radix sort: 
[ 18, 80, 5, 71, 18, 78, 87, 61, 19, 38 ]
After radix sort: 
[ 5, 18, 18, 19, 61, 71, 78, 80, 87, 38 ]

习题三

修改 Queue 类,形成一个 Deque 类。这是一个和队列类似的数据结构,允许从队列两端 添加和删除元素,因此也叫双向队列。写一段测试程序测试该类

Deque类的代码如下:

function Deque() {
  this.dataStore = [];
  this.enterFrontQueue = enterFrontQueue;
  this.enterBackQueue = enterBackQueue;
  this.delFrontQueue = delFrontQueue;
  this.delBackQueue = delBackQueue;
  this.front = front;
  this.back = back;
  this.toString = toString;
  this.empty = empty;
  this.count = count;
}

// enterFrontQueue 向队列头部添加元素
function enterFrontQueue(element) {
    this.dataStore.unshift(element);
}

// enterBackQueue 向队列尾部添加元素
function enterBackQueue(element) {
  return  this.dataStore.push(element);
}

// delFrontQueue 从队列头部删除元素

function delFrontQueue() {
    return this.dataStore.shift();
}

// delBackQueue 从队列尾部删除元素
function delBackQueue() {
    this.dataStore.pop();
}
// front() 读取队首元素:
function front() {
    return this.dataStore[0];
}
// back() 读取队尾元素:
function back() {
    return this.dataStore[this.dataStore.length - 1];
}

// toString() 显示队列内的所有元素
function toString() {
    var retStr = "";
    for (var i = 0; i < this.dataStore.length; ++i) {
        retStr += this.dataStore[i] + "\n";
    }
    return retStr;
}
//判断队列是否为空:
function empty() {
    if (this.dataStore.length == 0) {
        return true;
    } else {
        return false;
    }
}

//显示元素个数
function count() {
    return this.dataStore.length;
}

测试Deque类:

var d = new Deque();
d.enterBackQueue('a');
console.log(d.dataStore);
d.enterBackQueue('b');
console.log(d.dataStore);
d.enterFrontQueue('c');
console.log(d.dataStore);
d.enterFrontQueue('d');
console.log(d.dataStore);
d.enterFrontQueue('e');
console.log(d.dataStore);
d.enterBackQueue('f');

console.log(d.dataStore);

d.delBackQueue();
console.log(d.dataStore);
d.delFrontQueue();
console.log(d.dataStore);

结果如下:

[ 'a' ]
[ 'a', 'b' ]
[ 'c', 'a', 'b' ]
[ 'd', 'c', 'a', 'b' ]
[ 'e', 'd', 'c', 'a', 'b' ]
[ 'e', 'd', 'c', 'a', 'b', 'f' ]
[ 'e', 'd', 'c', 'a', 'b' ]
[ 'd', 'c', 'a', 'b' ]

习题四

使用前面完成的 Deque 类来判断一个给定单词是否为回文。

思路:
将字符串中的字符挨个推入双向队列中。然后每次弹出队列的首部元素和尾部元素进行比较。如果不相等,就说明不是回文。当双向队列中的元素只剩一个或一个不剩,循环结束。

代码如下:

function isPalindrome(word){
    var deque = new Deque();
    var result =true; //是否是回文。默认为true,即是回文。
    for(var i=0;i<word.length;i++){
        deque.enterBackQueue(word[i]);
    }
    while(deque.count()>1){
        if(deque.delBackQueue() !== deque.delFrontQueue()){
            result = false;
            break;
        }
    }
   return result;
}

console.log(isPalindrome('word')); // false
console.log(isPalindrome('pop')); // true
console.log(isPalindrome('woow')); // true
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,539评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,911评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,337评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,723评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,795评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,762评论 1 294
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,742评论 3 416
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,508评论 0 271
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,954评论 1 308
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,247评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,404评论 1 345
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,104评论 5 340
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,736评论 3 324
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,352评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,557评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,371评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,292评论 2 352

推荐阅读更多精彩内容

  • 栈 栈的英文单词是Stack,它代表一种特殊的线性表,这种线性表只能在固定一端(通常认为是线性表的尾端)进行插入,...
    Jack921阅读 1,500评论 0 5
  • 本系列博客习题来自《算法(第四版)》,算是本人的读书笔记,如果有人在读这本书的,欢迎大家多多交流。为了方便讨论,本...
    kyson老师阅读 1,790评论 0 50
  • 容器的概念所谓STL容器,即是将最常运用的一些数据结构(data structures)实现出来。容器是指容纳特定...
    饭饭H阅读 381评论 0 0
  • 排序的基本概念 在计算机程序开发过程中,经常需要一组数据元素(或记录)按某个关键字进行排序,排序完成的序列可用于快...
    Jack921阅读 1,428评论 1 4
  • 狂风暴雨敲打着车窗 家人们坐在车里 静静的等待着 望着高墙下的那一扇黑色的铁门 心情无比焦虑复杂 雨越下越大 天色...
    天魁诗词书画阅读 260评论 0 0