成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

JavaScript數(shù)據(jù)結(jié)構(gòu)03 - 隊(duì)列

Jonathan Shieber / 2632人閱讀

摘要:但是,還有一種隊(duì)列叫優(yōu)先隊(duì)列,元素的添加和移除是依賴優(yōu)先級(jí)的。分類優(yōu)先隊(duì)列分為兩類最小優(yōu)先隊(duì)列最大優(yōu)先隊(duì)列最小優(yōu)先隊(duì)列是把優(yōu)先級(jí)的值最小的元素被放置到隊(duì)列的最前面代表最高的優(yōu)先級(jí)。那么最小優(yōu)先隊(duì)列排序應(yīng)該為,,,。

一、定義

前面我們學(xué)習(xí)了棧的實(shí)現(xiàn),隊(duì)列和棧非常類似,但是使用了不同的原則,而非后進(jìn)先出。

隊(duì)列是遵循FIFO(First In First Out,先進(jìn)先出)原則的一組有序的項(xiàng)。隊(duì)列在尾部添加新元素,并從頂部移除元素。最新添加的元素必須排在隊(duì)列的末尾。

在計(jì)算機(jī)科學(xué)中,一個(gè)最常見(jiàn)的例子就是打印隊(duì)列。比如說(shuō)我們要打印五份文檔。我們會(huì)打開每個(gè)文檔,然后點(diǎn)擊打印按鈕。每個(gè)文檔都會(huì)被發(fā)送至打印隊(duì)列。第一個(gè)發(fā)送到打印隊(duì)列的文檔會(huì)首先被打印,以此類推,直到打印完所有文檔。

二、隊(duì)列的實(shí)現(xiàn) 2.1 普通隊(duì)列

創(chuàng)建普通隊(duì)列類:

// Queue類
function Queue () {
  this.items = [];

  this.enqueue = enqueue;
  this.dequeue = dequeue;
  this.front = front;
  this.isEmpty = isEmpty;
  this.size = size;
  this.clear = clear;
  this.print = print;
}

隊(duì)列里面有一些聲明的輔助方法:

enqueue(element):向隊(duì)列尾部添加新項(xiàng)

dequeue():移除隊(duì)列的第一項(xiàng)(即排在隊(duì)列最前面的項(xiàng)),并返回被移除的元素

front():返回隊(duì)列中第一個(gè)元素,隊(duì)列不做任何變動(dòng),和Stack的peek()方法類似

isEmpty():如果隊(duì)列中不包含任何元素,返回true,否則返回false

size():返回隊(duì)列包含的元素個(gè)數(shù),與數(shù)組的length屬性類似

print():打印隊(duì)列中的元素

clear():清空整個(gè)隊(duì)列

下面我們來(lái)一一實(shí)現(xiàn)這些輔助方法:

// 向隊(duì)列尾部添加元素
function enqueue (element) {
  this.items.push(element);
}

// 移除隊(duì)列的第一個(gè)元素,并返回被移除的元素
function dequeue () {
  return this.items.shift();
}

// 返回隊(duì)列的第一個(gè)元素
function front () {
  return this.items[0];
}

// 判斷是否為空隊(duì)列
function isEmpty () {
  return this.items.length === 0;
}

// 獲取隊(duì)列的長(zhǎng)度
function size () {
  return this.items.length;
}

// 清空隊(duì)列
function clear () {
  this.items = [];
}

// 打印隊(duì)列里的元素
function print () {
  console.log(this.items.toString());
}

創(chuàng)建普通隊(duì)列實(shí)例進(jìn)行測(cè)試:

// 創(chuàng)建Queue實(shí)例
var queue = new Queue();

console.log(queue.isEmpty());     // true
queue.enqueue("John");            // undefined
queue.enqueue("Jack");            // undefined
queue.enqueue("Camila");          // undefined
queue.print();                    // "John,Jack,Camila"
console.log(queue.size());        // 3
console.log(queue.isEmpty());     // false
queue.dequeue();                  // "John"
queue.dequeue();                  // "Jack"
queue.print();                    // "Camila"
queue.clear();                    // undefined
console.log(queue.size());        // 0
2.2 優(yōu)先隊(duì)列 2.2.1 定義

普通隊(duì)列的添加和移除只依賴于先后順序,先來(lái)的先添加,后來(lái)的后添加,然后按照先后順序依次從隊(duì)列移除。

但是,還有一種隊(duì)列叫優(yōu)先隊(duì)列,元素的添加和移除是依賴優(yōu)先級(jí)的。

一個(gè)現(xiàn)實(shí)的例子就是機(jī)場(chǎng)登機(jī)的順序。頭等艙和商務(wù)艙乘客的優(yōu)先級(jí)要高于經(jīng)濟(jì)艙乘客。再比如火車,老年人、孕婦和帶小孩的乘客是享有優(yōu)先檢票權(quán)的。

2.2.2 分類

優(yōu)先隊(duì)列分為兩類:

最小優(yōu)先隊(duì)列

最大優(yōu)先隊(duì)列

最小優(yōu)先隊(duì)列是把優(yōu)先級(jí)的值最小的元素被放置到隊(duì)列的最前面(代表最高的優(yōu)先級(jí))。比如有四個(gè)元素:"John", "Jack", "Camila", "Tom",他們的優(yōu)先級(jí)值分別為4,3,2,1。

那么最小優(yōu)先隊(duì)列排序應(yīng)該為:"Tom","Camila","Jack","John"。

最大優(yōu)先隊(duì)列正好相反,把優(yōu)先級(jí)值最大的元素放置在隊(duì)列的最前面,以上面的為例,最大優(yōu)先隊(duì)列排序應(yīng)該為:"John", "Jack", "Camila", "Tom"。

2.2.2 實(shí)現(xiàn)

實(shí)現(xiàn)一個(gè)優(yōu)先隊(duì)列,有兩種選項(xiàng):

設(shè)置優(yōu)先級(jí),根據(jù)優(yōu)先級(jí)正確添加元素,然后和普通隊(duì)列一樣正常移除

設(shè)置優(yōu)先級(jí),和普通隊(duì)列一樣正常按順序添加,然后根據(jù)優(yōu)先級(jí)移除

這里最小優(yōu)先隊(duì)列和最大優(yōu)先隊(duì)列我都采用第一種方式實(shí)現(xiàn),大家可以嘗試一下第二種。

所以我只重寫enqueue()方法和print()方法,其他方法和上面的普通隊(duì)列完全相同。完整代碼見(jiàn)我的github。

實(shí)現(xiàn)最小優(yōu)先隊(duì)列

// 定義最小優(yōu)先隊(duì)列
function MinPriorityQueue () {
  this.items = [];

  this.enqueue = enqueue;
  this.dequeue = dequeue;
  this.front = front;
  this.isEmpty = isEmpty;
  this.size = size;
  this.clear = clear;
  this.print = print;
}

實(shí)現(xiàn)最小優(yōu)先隊(duì)列enqueue()方法和print()方法

// 優(yōu)先隊(duì)列添加元素,要根據(jù)優(yōu)先級(jí)判斷在隊(duì)列中的插入順序
function enqueue (element, priority) {
  var queueElement = {
    element: element,
    priority: priority
  };

  if (this.isEmpty()) {
    this.items.push(queueElement);
  } else {
    var added = false;

    for (var i = 0; i < this.size(); i++) {
      if (queueElement.priority < this.items[i].priority) {
        this.items.splice(i, 0, queueElement);
        added = true;
        break ;
      }
    }

    if (!added) {
      this.items.push(queueElement);
    }
  }
}

// 打印隊(duì)列里的元素
function print () {
  var strArr = [];

  strArr = this.items.map(function (item) {
    return `${item.element}->${item.priority}`;
  });

  console.log(strArr.toString());
}

最小優(yōu)先隊(duì)列測(cè)試:

// 創(chuàng)建最小優(yōu)先隊(duì)列minPriorityQueue實(shí)例
var minPriorityQueue = new MinPriorityQueue();

console.log(minPriorityQueue.isEmpty());     // true
minPriorityQueue.enqueue("John", 1);         // undefined
minPriorityQueue.enqueue("Jack", 3);         // undefined
minPriorityQueue.enqueue("Camila", 2);       // undefined
minPriorityQueue.enqueue("Tom", 3);          // undefined
minPriorityQueue.print();                    // "John->1,Camila->2,Jack->3,Tom->3"
console.log(minPriorityQueue.size());        // 4
console.log(minPriorityQueue.isEmpty());     // false
minPriorityQueue.dequeue();                  // {element: "John", priority: 1}
minPriorityQueue.dequeue();                  // {element: "Camila", priority: 2}
minPriorityQueue.print();                    // "Jack->3,Tom->3"
minPriorityQueue.clear();                    // undefined
console.log(minPriorityQueue.size());        // 0

實(shí)現(xiàn)最大優(yōu)先隊(duì)列

最大優(yōu)先隊(duì)列只要將優(yōu)先級(jí)的判斷改為大于號(hào)">"就可以了:

// 最大優(yōu)先隊(duì)列MaxPriorityQueue類
function MaxPriorityQueue () {
  this.items = [];

  this.enqueue = enqueue;
  this.dequeue = dequeue;
  this.front = front;
  this.isEmpty = isEmpty;
  this.size = size;
  this.clear = clear;
  this.print = print;
}

// 優(yōu)先隊(duì)列添加元素,要根據(jù)優(yōu)先級(jí)判斷在隊(duì)列中的插入順序
function enqueue (element, priority) {
  var queueElement = {
    element: element,
    priority: priority
  };

  if (this.isEmpty()) {
    this.items.push(queueElement);
  } else {
    var added = false;

    for (var i = 0; i < this.items.length; i++) {
      // 注意,只需要將這里改為大于號(hào)就可以了
      if (queueElement.priority > this.items[i].priority) {
        this.items.splice(i, 0, queueElement);
        added = true;
        break ;
      }
    }

    if (!added) {
      this.items.push(queueElement);
    }
  }
}

最大優(yōu)先隊(duì)列測(cè)試:

// 創(chuàng)建最大優(yōu)先隊(duì)列maxPriorityQueue實(shí)例
var maxPriorityQueue = new MaxPriorityQueue();

console.log(maxPriorityQueue.isEmpty());     // true
maxPriorityQueue.enqueue("John", 1);         // undefined
maxPriorityQueue.enqueue("Jack", 3);         // undefined
maxPriorityQueue.enqueue("Camila", 2);       // undefined
maxPriorityQueue.enqueue("Tom", 3);          // undefined
maxPriorityQueue.print();                    // "Jack->3,Tom->3,Camila->2,John->1"
console.log(maxPriorityQueue.size());        // 4
console.log(maxPriorityQueue.isEmpty());     // false
maxPriorityQueue.dequeue();                  // {element: "Jack", priority: 3}
maxPriorityQueue.dequeue();                  // {element: "Tom", priority: 3}
maxPriorityQueue.print();                    // "Camila->2,John->1"
maxPriorityQueue.clear();                    // undefined
console.log(maxPriorityQueue.size());        // 0
2.3 循環(huán)隊(duì)列

還有一種隊(duì)列實(shí)現(xiàn)叫做循環(huán)隊(duì)列。

循環(huán)隊(duì)列的一個(gè)例子就是擊鼓傳花游戲(Hot Potato)。在這個(gè)游戲中,孩子們圍城一個(gè)圓圈,擊鼓的時(shí)候把花盡快的傳遞給旁邊的人。某一時(shí)刻擊鼓停止,這時(shí)花在誰(shuí)的手里,誰(shuí)就退出圓圈直到游戲結(jié)束。重復(fù)這個(gè)過(guò)程,直到只剩一個(gè)孩子(勝者)。

下面我們?cè)谄胀?duì)列的基礎(chǔ)上,實(shí)現(xiàn)一個(gè)模擬的擊鼓傳花游戲:

// 實(shí)現(xiàn)擊鼓傳花
function hotPotato (nameList, num) {
  var queue = new Queue();

  for (var i = 0; i < nameList.length; i++) {
    queue.enqueue(nameList[i]);
  }

  var eliminated = "";

  while (queue.size() > 1) {
    // 循環(huán)num次,隊(duì)首出來(lái)去到隊(duì)尾
    for (var i = 0; i < num; i++) {
      queue.enqueue(queue.dequeue());
    }
    // 循環(huán)num次過(guò)后,移除當(dāng)前隊(duì)首的元素
    eliminated = queue.dequeue();
    console.log(`${eliminated}在擊鼓傳花中被淘汰!`);
  }

  // 最后只剩一個(gè)元素
  return queue.dequeue();
}

// 測(cè)試
var nameList = ["John", "Jack", "Camila", "Ingrid", "Carl"];
var winner = hotPotato(nameList, 10);
console.log(`最后的勝利者是:${winner}`);

執(zhí)行結(jié)果為:

// John在擊鼓傳花中被淘汰!
// Ingrid在擊鼓傳花中被淘汰! 
// Jack在擊鼓傳花中被淘汰!
// Camila在擊鼓傳花中被淘汰!
// 最后的勝利者是:Carl
三、結(jié)束

本文會(huì)同步到我的個(gè)人博客,完整代碼可以到我的github倉(cāng)庫(kù)查看,如果對(duì)你有幫助的話歡迎點(diǎn)一個(gè)Star~~

歡迎關(guān)注我的公眾號(hào)

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/96294.html

相關(guān)文章

  • 分布式代理爬蟲:架構(gòu)篇

    摘要:降低的結(jié)果可能有三個(gè)隨著數(shù)據(jù)量的增大的性能受到了一定的影響知乎校驗(yàn)器在把中的代理消費(fèi)完之后,由于是定時(shí)任務(wù),所以導(dǎo)致某段時(shí)間內(nèi)新鮮的空缺。 歷時(shí)大致兩個(gè)月,到現(xiàn)在終于完成了分布式代理抓取爬蟲,目前開源在了Github上。寫這個(gè)項(xiàng)目的原因主要有兩點(diǎn),一是自己平時(shí)的部分工作需要和爬蟲打交道,代理IP在有的時(shí)候可以發(fā)揮非常重要的作用,調(diào)研過(guò)一些開源的代理IP采集程序,發(fā)現(xiàn)在抓取、解析、校驗(yàn)、...

    qujian 評(píng)論0 收藏0
  • 100行代碼實(shí)現(xiàn)任務(wù)隊(duì)列

    摘要:最近剛看完多線程,為了加深印象,按照分鐘實(shí)現(xiàn)延遲消息功能的思路,實(shí)現(xiàn)了一個(gè)簡(jiǎn)易版的異步隊(duì)列。讀取任務(wù)時(shí),計(jì)算當(dāng)前和,取出需要執(zhí)行的任務(wù),使用多線程的形式執(zhí)行。加鎖的主要作用是防止多線程同時(shí)操作文件讀寫,影響數(shù)據(jù)一致性。 最近剛看完python多線程,為了加深印象,按照1分鐘實(shí)現(xiàn)延遲消息功能的思路,實(shí)現(xiàn)了一個(gè)簡(jiǎn)易版的異步隊(duì)列。 高效延時(shí)消息,包含兩個(gè)重要的數(shù)據(jù)結(jié)構(gòu): 1.環(huán)形隊(duì)列,例...

    xorpay 評(píng)論0 收藏0
  • 多線程+代理池爬取天天基金網(wǎng)、股票數(shù)據(jù)(無(wú)需使用爬蟲框架)

    摘要:本次使用天天基金網(wǎng)進(jìn)行爬蟲,該網(wǎng)站具有反爬機(jī)制,同時(shí)數(shù)量足夠大,多線程效果較為明顯。技術(shù)路線代理池多線程爬蟲與反爬編寫思路首先,開始分析天天基金網(wǎng)的一些數(shù)據(jù)。一旦使用多線程,則需要考慮到數(shù)據(jù)的讀寫順序問(wèn)題。 @[TOC] 簡(jiǎn)介 提到爬蟲,大部分人都會(huì)想到使用Scrapy工具,但是僅僅停留在會(huì)使用的階段。為了增加對(duì)爬蟲機(jī)制的理解,我們可以手動(dòng)實(shí)現(xiàn)多線程的爬蟲過(guò)程,同時(shí),引入IP代理池進(jìn)行...

    jaysun 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<