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] + " ");

    }

}

测试:

 1 //    初始化一个队列数组,用于存放所有0~9十个数字的队列

 2 var queues = [];

 3 for(var i=0; i<10; i++){

 4     queues[i] = new Queue();

 5 }

 6 

 7 //    初始化存放最后结果的数组

 8 var nums = [];

 9 

10 //    随机生成十个 1~99的整数

11 for(var i=0;i<10;i++){

12     nums[i] = Math.floor(Math.floor(Math.random() * 101));

13 }

14 

15 console.info("Before radix sort:");

16 dispArray(nums);

17 

18 //    根据个位数排序加入队列中

19 distribute(nums, queues, 10, 1);

20 

21 //    将第一次排序完的队列中的数存放到新数组中去

22 collect(queues, nums)

23 

24 //    根据十位数排序加入队列中

25 distribute(nums, queues, 10, 10);

26 

27 //    将第二次排序完的队列中的数存放到新数组中去

28 collect(queues, nums);

29 

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

31 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)