javascript数据结构与算法---队列

队列是一种列表,不同的是队列只能在队尾插入元素,在队首删除元素。队列用于存储按顺序排列的数据,先进先出,这点和栈不一样(后入先出)。在栈中,最后入栈的元素反而被优先处理。我们现在可以把队列想象对我们去餐馆吃饭的情景,很多人排队吃饭,排在最前面的人先打饭。新来的人只能在后面排队。直到轮到他们为止。

一:对队列的操作

队列有2种主要的操作,向队尾中插入新元素enqueue()方法和删除队列中的队首的元素的dequeue()方法,另外我们还有一个读取队头的元素,这个方法我们可以叫front()方法。该方法返回队头元素等等方法。

看到如上描述,我们很多人可能会想到数组,数组里面也有2个方法和上面的方法功能类似,数组中push()方法也是往数组后面加入新元素,数组中shift()方法则可以删除数组里面的第一个元素。如下代码:

var arrs = [];

arrs.push("a");

arrs.push("b");

console.log(arrs);  // ["a","b"];

arrs.shift();

console.log(arrs); // [‘b‘];

下面我们可以使用上面的数组中的push()和shift()的2个方法来封装我们的队列Queue类;

1.  我们可以先定义一个构造函数Queue类,如下:

function Queue() {
    this.dataStore = [];
}

如上:this.dataStore = []; 空数组时存储队列中所有的元素的。

2. 向队尾中添加一个元素方法如下:

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

3. 删除队首的元素如下:

function dequeue() {
    return this.dataStore.shift()
}

4. 读取队首的元素如下:

function front() {
    return this.dataStore[0];
}

5. 读取队尾的元素如下:

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

6. 显示队列中的所有元素

function toString() {
   var retStr = "";
   for(var i = 0; i < this.dataStore.length; ++i) {
       retStr += this.dataStore[i] + "\n";
   }
   return retStr;
}

7. 判断队列是否为空如下:

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

下面是完整的JS代码如下:

function Queue() {
    this.dataStore = [];
}

Queue.prototype = {

    // 向队尾添加一个元素
    enqueue: function(element) {
        this.dataStore.push(element);
    },
    // 删除队首的元素
    dequeue: function(){
        return this.dataStore.shift();
    },
    // 读取队首的元素
    front: function(){
        return this.dataStore[0];
    },
    // 读取队尾的元素
    back: function(){
        return this.dataStore[this.dataStore.length - 1];
    },
    // 显示队列内的所有元素
    toString: function(){
        var retStr = "";
        for(var i = 0; i < this.dataStore.length; ++i) {
            retStr += this.dataStore[i] + "\n";
        }
        return retStr;
    },
    // 判断队列是否为空
    empty: function(){
        if(this.dataStore.length == 0) {
            return true;
        }else {
            return false;
        }
    }

};

我们现在可以对以上代码测试下:如下:

var q = new Queue();
q.enqueue("a");
q.enqueue("b");
q.enqueue("c");

console.log(q.toString());  // a b c
q.dequeue();
console.log(q.toString()); // b c

console.log("Front of queue:" +q.front()); // b
console.log("Back of queue:" +q.back()); // c

二:使用队列对数据进行排序

比如对于 0 ~ 99 的数字进行排序,原理是:先对个位上的数字进行排序一次,然后对十位上的数字再进行排序一次。每个数字根据对应位上的数值被分在不同的盒子里面,然后对于个位上的数字采用除余数的方法,对于10位上的数字采用除法的方法,那么这种排序叫做 “基数排序”. 但是它不是最快的排序方法,但是它描述了一些有趣的队列使用方法。

比如如下数组:

var nums = ["50","12","95","7","90","3","74","81","91","72"];

1. 经过基数排序--个位排序后,数字被分配在不同的盒子里面。(在JS里面,我们可以分配在不同的队列Queue实例类里面)。如下

queues[0] = 50 或者 90
queues[1] = 81 或者 91
queues[2] = 12 或者 72
queues[3] = 3
queues[4] = 74
queues[5] = 95
queues[6]
queues[7] = 7
queues[8]
queues[9]

根据盒子的顺序,对数字第一次个位排序后结果如下:

nums = [50,90,81,91,12,72,3,74,95,7]

2. 然后根据十位上的数值再将上次排序后的结果分配到不同的盒子中。如下:

queues[5] = 50
queues[9] = 90
queues[8] = 81
queues[9] = 91
queues[1] = 12
queues[7] = 72
queues[0] = 3
queues[7] = 74
queues[9] = 95
queues[0] = 7

最后,将盒子中的数字取出,组成一个新的列表,该列表即为排序好的数字。如下:

即可生成如下:
nums = [3,7,12,50,72,74,81,90,91,95];

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

下面根据个位或十位上的数值,将数字分配到相应队列的函数。

/*
 * 根据个位或十位上的数值,将数字分配到相应队列的函数
 * @param digit
 * digit=1 表示先按个位来分配
 * digit = 10 表示是按十位来分配的
 * @param n 表示循环比较多少次 一般数组几个数字就比较多少次
 */
 distribute: function(nums,queues,n,digit){
     for(var i = 0; i < n; ++i) {
        if(digit == 1) {
            queues[nums[i] % 10].enqueue(nums[i]);
         }else {
            queues[Math.floor(nums[i] / 10)].enqueue(nums[i]);
         }
      }
  }

下面是从队列中收集数字的函数如下:

// 收集数字的函数
collect: function(queues,nums,n) {
    var i = 0;
    for(var digit = 0; digit < n; ++digit) {
        while(!queues[digit].empty()) {
            nums[i++] = queues[digit].dequeue();
        }
    }
}

由于上面省略了很多步骤,可能描述的不是很清楚,我们现在先来看看流程图,结合流程图,最后结合JS的所有代码就可以理解"基数排序的"基本原理了;下面我们可以看看如下的流程图;

最后是所有的JS代码如下:

function Queue() {
    this.dataStore = [];
}

Queue.prototype = {

    // 向队尾添加一个元素
    enqueue: function(element) {
        this.dataStore.push(element);
    },
    // 删除队首的元素
    dequeue: function(){
        return this.dataStore.shift();
    },
    // 读取队首的元素
    front: function(){
        return this.dataStore[0];
    },
    // 读取队尾的元素
    back: function(){
        return this.dataStore[this.dataStore.length - 1];
    },
    // 显示队列内的所有元素
    toString: function(){
        var retStr = "";
        for(var i = 0; i < this.dataStore.length; ++i) {
            retStr += this.dataStore[i] + "\n";
        }
        return retStr;
    },
    // 判断队列是否为空
    empty: function(){
        if(this.dataStore.length == 0) {
            return true;
        }else {
            return false;
        }
    },
    /*
     * 根据个位或十位上的数值,将数字分配到相应队列的函数
     * @param digit
     * digit=1 表示先按个位来分配
     * digit = 10 表示是按十位来分配的
     * @param n 表示循环比较多少次 一般数组几个数字就比较多少次
     */
    distribute: function(nums,queues,n,digit){
        for(var i = 0; i < n; ++i) {
            if(digit == 1) {
                queues[nums[i] % 10].enqueue(nums[i]);
            }else {
                queues[Math.floor(nums[i] / 10)].enqueue(nums[i]);
            }
        }
    },
    // 收集数字的函数
    collect: function(queues,nums,n) {
        var i = 0;
        for(var digit = 0; digit < n; ++digit) {
            while(!queues[digit].empty()) {
                nums[i++] = queues[digit].dequeue();
            }
        }
    },
    dispArray: function(arr) {
        for(var i = 0; i < arr.length; ++i) {
            console.log(arr[i]);
        }
    }
};

下面的是对 "基数排序的" JS代码进行测试;如下代码:

var q = new Queue();
    q.enqueue("a");
    q.enqueue("b");
    q.enqueue("c");

console.log(q.toString());
q.dequeue();
console.log(q.toString());

console.log("Front of queue:" +q.front());
console.log("Back of queue:" +q.back());

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

var nums = ["50","12","95","7","90","3","74","81","91","72"];

console.log("before radix sort: ");
console.log(nums);

q.distribute(nums,queues,10,1);

q.collect(queues,nums,10);
q.dispArray(nums);
console.log("分割线");

q.distribute(nums,queues,10,10);
q.collect(queues,nums,10);

q.dispArray(nums);

如上测试代码 大家可以运行下 就可以看到排序后的效果!

三: 优先队列

由于时间的关系;明天继续理解 "javascript数据结构与算法的" 优先队列,今天晚上先到此为止!明天晚上继续。

时间: 2024-10-16 14:08:29

javascript数据结构与算法---队列的相关文章

JavaScript数据结构和算法----队列

前言 队列和栈很像,只是用了不同的原则.队列是遵循先进先出(FIFO)原则的一组有序的的项,队列在尾部添加新元素,从顶部移除元素.最新添加的元素必须必须排队在队列的,末尾.可以想象食堂排队买饭的样子. 一.创建队列 1.创建一种数据结构来保存队列里面的数据,这里选择数组 2.声明一些栈的方法 enqueue(element(s)) : 添加一个或一些元素到队列的末尾 dequeue() : 移除队列第一个的元素(就是排队在最前面的),同时返回被移除的元素. front() : 返回队列第一个的元

javascript数据结构和算法 零(前记+序言)

前记 这本书Data Structure and Algorithm with Javascript 我将其翻译成<< javascript 数据结构和算法>> 为什么这么翻译?而不是翻译成"用javascript实现数据结构和算法" 原因有二: 一个,我觉的它更加简洁,第二个,我是想强调我们在这里使用的是javascript. 我不喜欢一些翻译的人把一个简单的语句进行加工,搞得晦涩难懂.我更喜欢外国人写书的 那种原汁原味.同样,我很喜欢外国人的那种分享精神,它

javascript数据结构和算法 一(本书组织结构)

环境 我们在本书中使用的Javascript编程环境是基于SpiderMonkey 引擎的javascript shell. 第一章讲述了在你的环境中下载 shell的介绍. 其他的shell例如Nodejs同样可以工作,虽然你可能需要简单的改变下代码. 除了shell,唯一你要准备的就是文本编辑器. 本书的组织结构 第一章:javascript语言的概览,至少是在本书中使用的javascript的一些特征.这一章同时展示了在整本书中使用的一些编程风格. 第二章:讨论了在计算机科学中最通用的数据

算法入门《数据结构与算法图解》+《我的第一本算法书》+《学习JavaScript数据结构与算法第3版》

最近几年学前端的人会越来越多,再加上前端的范围越来越广,从前端发展为全栈,数据结构和算法的功底要求势必将越来越高. <数据结构与算法图解>电子书及代码是数据结构与算法的入门指南,不局限于某种特定语言,略过复杂的数学公式,用通俗易懂的方式针对编程初学者介绍数据结构与算法的基本概念,培养编程逻辑.主要内容包括:为什么要了解数据结构与算法,大O表示法及其代码优化利用,栈.队列等的合理使用,等等. <算法图解>电子书非常的体贴,看起来也很快,用图来解释算法是非常好的想法,可作为学习数据结构

javascript数据结构与算法--二叉树(插入节点、生成二叉树)

javascript数据结构与算法-- 插入节点.生成二叉树 二叉树中,相对较小的值保存在左节点上,较大的值保存在右节点中 /* *二叉树中,相对较小的值保存在左节点上,较大的值保存在右节点中 * * * */ /*用来生成一个节点*/ function Node(data, left, right) { this.data = data;//节点存储的数据 this.left = left; this.right = right; this.show = show; } function sh

javascript数据结构与算法---列表

前言:在日常生活中,人们经常要使用列表,比如我们有时候要去购物时,为了购物时东西要买全,我们可以在去之前,列下要买的东西,这就要用的列表了,或者我们小时候上学那段时间,每次考完试后,学校都会列出这次考试成绩前十名的同学的排名及成绩单,等等这些都是列表的列子.我们计算机内也在使用列表,那么列表适合使用在什么地方呢?不适合使用在什么地方呢? 适合使用在:当列表的元素不是很多的情况下,可以使用列表,因为对列表中的元素查找或者排序时,效率还算非常高,反之:如果列表元素非常多的情况下,就不适合使用列表了.

javascript数据结构和算法 第一章(编程体验)一

声明和初始化变量 Javascript变量默认是全局作用域的.严格来说,使用之前是不需要定义的. 当一个javascript变量在没有被声明之前直接进行初始化,它就是一个全局变量.在这本书中,我们沿用编译语言如c++和java的编程约定.在使用变量之前都进行声明. 这还有一个附带的好处,声明的变量可以作为本地变量. 我们将会在本章节的后面讨论更多关于变量的作用域. 声明javascript变量,使用关键字var 变量名称.可选择的,可以带上赋值表达式. 下面是一些例子 var number; v

javascript数据结构和算法 第一章(编程体验)三

变量作用域 变量作用域就是指在一个程序中,变量的值在哪里可以被获取到.javascript函数作用域被定义为函数作用域,这意味着变量的值在定义和声明该变量的函数,包括任何在该函数的嵌套函数里是可见的. 当一个变量定义在函数的外面,在主程序中,该变量将会拥有全局作用域.这就意味着它的值可以被程序的任何地方,包括函数获取. 下面的小程序演示全局变量时如何工作的. function showScope() { return scope; } var scope = "global"; pri

javascript数据结构和算法 第一章(Javascript编程环境和模型) 一

这一章介绍了我们在这本书中使用的描述各种数据结构和算法的Javascript的编程环境和编程架构. Javascript 环境 Javascript 在很长一段时间都是被作为web浏览器内置脚本编程语言来使用. 然而,在过去几年里,javascript编程环境得到了极大的发展,他们可以使javascript在桌面或者服务端运行. 在我们这本书中,我们使用其中的一个javascript环境:javascript shell:是Mozilla公司的javascript环境,被称为SpiderMonk