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

??我們之前已經(jīng)學(xué)習(xí)過(guò)了一種受限的線性結(jié)構(gòu):棧結(jié)構(gòu)窒典,并且我們已經(jīng)知道這種受限的數(shù)據(jù)結(jié)構(gòu)對(duì)于解決某些特定問(wèn)題,會(huì)有特別的效果阿趁,下面我們來(lái)學(xué)習(xí)另外一種受限的數(shù)據(jù)結(jié)構(gòu):隊(duì)列
??之前說(shuō)過(guò)的棧結(jié)構(gòu)是一種遵循先進(jìn)后出規(guī)則的數(shù)據(jù)結(jié)構(gòu)膜蛔,它只允許在棧頂插入或刪除元素,而隊(duì)列則是遵循先進(jìn)先出規(guī)則的數(shù)據(jù)結(jié)構(gòu)脖阵,類似于現(xiàn)實(shí)生活中人們排隊(duì)買(mǎi)火車票皂股,先排隊(duì)的先買(mǎi)票,先到先得命黔,也就是它只允許在隊(duì)列前端進(jìn)行刪除操作(買(mǎi)票)呜呐,而在隊(duì)列的后端進(jìn)行插入操作(排隊(duì))

隊(duì)列結(jié)構(gòu)

生活中隊(duì)列

  1. 打印隊(duì)列:有五份文檔需要打印,這些文檔會(huì)按照次序放入到打印隊(duì)列中悍募,打印機(jī)會(huì)依次從隊(duì)列中取出文檔蘑辑,優(yōu)先放入的文檔,優(yōu)先會(huì)被取出并打印坠宴,依次類推直到隊(duì)列中沒(méi)有文檔為止
  2. 線程隊(duì)列:在開(kāi)發(fā)中洋魂,為了讓任務(wù)可以并行處理,通常會(huì)開(kāi)啟多個(gè)線程,但是副砍,我們不能讓大量的線程衔肢,同時(shí)運(yùn)行處理任務(wù)(占用過(guò)多的資源)這個(gè)時(shí)候,如果有需要開(kāi)啟線程處理任務(wù)的情況址晕,我們就會(huì)使用線程隊(duì)列膀懈。線程隊(duì)列會(huì)依照次序來(lái)啟動(dòng)線程,并且處理對(duì)應(yīng)的任務(wù)谨垃,

隊(duì)列結(jié)構(gòu)的實(shí)現(xiàn)以及應(yīng)用

下面代碼中我們創(chuàng)建了一個(gè)隊(duì)列類启搂,并實(shí)現(xiàn)了隊(duì)列常用的相關(guān)的方法。其實(shí)也比較簡(jiǎn)單刘陶,主要也是基于數(shù)組進(jìn)行實(shí)現(xiàn)

// 簡(jiǎn)單的隊(duì)列實(shí)現(xiàn)(基于數(shù)組胳赌,其實(shí)最好的方式是基于鏈表實(shí)現(xiàn),性能會(huì)高一些)
let Queue = (function(){
  let items = [];
  return class {
    // 向隊(duì)列尾部添加一項(xiàng)
    // 存
    enqueue(element) {
      items.push(element);
    }
    // 移除隊(duì)列的第一項(xiàng)匙隔,并返回被移除項(xiàng)
    // 取
    dequeue() {
      return items.shift();
    }
    // 返回隊(duì)列中的第一個(gè)元素
    // 查看
    front() {
      return items[0];
    }
    // 查看隊(duì)列是否為空
    isEmpty() {
      return items.length === 0;
    }
    // 查看大小
    size() {
      return items.length;
    }
    // 將隊(duì)列中的內(nèi)容轉(zhuǎn)換為字符串疑苫,并返回
    toString() {
      let resultString = "";
      for (let i in items) {
        resultString += items[i];
      }
      return resultString;
    }
  }
})()


下面介紹一個(gè)關(guān)于隊(duì)列面試題:擊鼓傳花
??游戲規(guī)則:隨意人數(shù)的同學(xué)圍成一圈,由某個(gè)人開(kāi)始數(shù)數(shù)纷责,比如從班長(zhǎng)(隨機(jī)的)開(kāi)始捍掺,班長(zhǎng)數(shù)1,然后旁邊的人就數(shù)2再膳,依次往后挺勿,當(dāng)數(shù)到某個(gè)人數(shù)到特定數(shù)字之后(事先約定好這個(gè)數(shù)字),那么這個(gè)人將會(huì)被淘汰,此時(shí)下一個(gè)人從頭開(kāi)始數(shù)1喂柒。依次類推不瓶,當(dāng)所有人被淘汰只留一個(gè)人的時(shí)候,即游戲結(jié)束這個(gè)人為勝者

// 擊鼓傳花游戲應(yīng)用
function passGame(nameList, num) {
  // 定義一個(gè)隊(duì)列
  let queue = new Queue();
  // 循環(huán)角色
  // 以此添加到隊(duì)列中
  for (let i in nameList) {
    queue.enqueue(nameList[i]);
  }

  // 隊(duì)列人數(shù)為1之前一直循環(huán)
  while (queue.size() > 1) {
    // 根據(jù)數(shù)字進(jìn)行循環(huán)
    for (let i = 0; i < num - 1; i++) {
      queue.enqueue(queue.dequeue());
    }
    // 移除數(shù)到的人
    queue.dequeue();
  }
  return queue.front()
}

console.log(passGame(["小明","小紅","小呂","張三","李四","十五"],7))

優(yōu)先級(jí)隊(duì)列

??優(yōu)先級(jí)隊(duì)列的特點(diǎn)灾杰,我們知道普通的隊(duì)列插入一個(gè)元素蚊丐,數(shù)據(jù)會(huì)直接被放在隊(duì)尾,但是優(yōu)先級(jí)隊(duì)列在插入一個(gè)新元素前會(huì)考慮該數(shù)據(jù)的優(yōu)先級(jí)艳吠,就是即將插入的數(shù)據(jù)會(huì)和隊(duì)列中其他數(shù)據(jù)的優(yōu)先級(jí)進(jìn)行比較麦备,比較完成后,才可以得出這個(gè)元素在隊(duì)列中的正確位置昭娩,除此之外其他處理方式和普通隊(duì)列的處理方式一樣泥兰,那么我們?cè)撊绾螌?shí)現(xiàn),其實(shí)要實(shí)現(xiàn)優(yōu)先級(jí)隊(duì)列主要就是需要修改 enqueue 方法就可以實(shí)現(xiàn)

let PriorityQueue = (function() {
  // 基于數(shù)組
  let items = [];
  // 內(nèi)部類,用于創(chuàng)建元素節(jié)點(diǎn)
  let _createQueuElement = class {
    constructor(element, priority) {
      this.element = element;
      this.priority = priority;
    }
  };
  return class {
    // 向隊(duì)列尾部添加一項(xiàng)
    // 存
    enqueue(element, priority) {
      // 創(chuàng)建
      let queuelement = new _createQueuElement(element, priority);
      // 如果為空
      if (items.length === 0) {
        // 直接添加
        items.push(queuelement);
        return;
      } else {
        // 如果插入元素题禀,
        if (queuelement.priority <= items[0].priority) {
          items.unshift(queuelement);
          return;
        } else if (
          queuelement.priority > items[items.length - 1].priority
        ) {
          items.push(queuelement);
          return;
        }
        // 預(yù)先定義 index 值
        let index;
        items.forEach((v, i) => {
          if (
            queuelement.priority > items[i].priority &&
            queuelement.priority <= items[i + 1].priority
          ) {
            index = i + 1;
          }
        });
        items.splice(index, 0, queuelement);
        return index;
      }
    }
    // 移除隊(duì)列的第一項(xiàng),并返回被移除項(xiàng)
    // 取
    dequeue() {
      return items.shift();
    }
    // 返回隊(duì)列中的第一個(gè)元素
    // 查看
    front() {
      return items[0];
    }
    // 查看隊(duì)列是否為空
    isEmpty() {
      return items.length === 0;
    }
    // 查看大小
    size() {
      return items.length;
    }
    // 將隊(duì)列中的內(nèi)容轉(zhuǎn)換為字符串膀捷,并返回
    toString() {
      let resultString = "";
      for (let i in items) {
        resultString += JSON.stringify(items[i]);
      }
      return resultString;
    }
  };
})();

let pq = new PriorityQueue();
pq.enqueue("哥哥", 30);
pq.enqueue("小紅", 10);
pq.enqueue("小呂", 20);
pq.enqueue("銀時(shí)", 40);
pq.enqueue("神樂(lè)", 50);

pq.enqueue("神樂(lè)2號(hào)", 15);
pq.enqueue("神樂(lè)3號(hào)", 15);
pq.enqueue("神樂(lè)2號(hào)", 16);
pq.enqueue("神樂(lè)2號(hào)", 17);

console.log(pq.toString());

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末迈嘹,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌秀仲,老刑警劉巖融痛,帶你破解...
    沈念sama閱讀 221,198評(píng)論 6 514
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異神僵,居然都是意外死亡雁刷,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,334評(píng)論 3 398
  • 文/潘曉璐 我一進(jìn)店門(mén)保礼,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人炮障,你說(shuō)我怎么就攤上這事目派。” “怎么了胁赢?”我有些...
    開(kāi)封第一講書(shū)人閱讀 167,643評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵企蹭,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我智末,道長(zhǎng)谅摄,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 59,495評(píng)論 1 296
  • 正文 為了忘掉前任系馆,我火速辦了婚禮送漠,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘它呀。我一直安慰自己螺男,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,502評(píng)論 6 397
  • 文/花漫 我一把揭開(kāi)白布纵穿。 她就那樣靜靜地躺著下隧,像睡著了一般。 火紅的嫁衣襯著肌膚如雪谓媒。 梳的紋絲不亂的頭發(fā)上淆院,一...
    開(kāi)封第一講書(shū)人閱讀 52,156評(píng)論 1 308
  • 那天,我揣著相機(jī)與錄音句惯,去河邊找鬼土辩。 笑死,一個(gè)胖子當(dāng)著我的面吹牛抢野,可吹牛的內(nèi)容都是我干的拷淘。 我是一名探鬼主播,決...
    沈念sama閱讀 40,743評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼指孤,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼启涯!你這毒婦竟也來(lái)了贬堵?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,659評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤结洼,失蹤者是張志新(化名)和其女友劉穎黎做,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體松忍,經(jīng)...
    沈念sama閱讀 46,200評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡蒸殿,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,282評(píng)論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了鸣峭。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片宏所。...
    茶點(diǎn)故事閱讀 40,424評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖叽掘,靈堂內(nèi)的尸體忽然破棺而出楣铁,到底是詐尸還是另有隱情,我是刑警寧澤更扁,帶...
    沈念sama閱讀 36,107評(píng)論 5 349
  • 正文 年R本政府宣布盖腕,位于F島的核電站,受9級(jí)特大地震影響浓镜,放射性物質(zhì)發(fā)生泄漏溃列。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,789評(píng)論 3 333
  • 文/蒙蒙 一膛薛、第九天 我趴在偏房一處隱蔽的房頂上張望听隐。 院中可真熱鬧,春花似錦哄啄、人聲如沸雅任。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,264評(píng)論 0 23
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)女淑。三九已至出皇,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間昌粤,已是汗流浹背艇搀。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,390評(píng)論 1 271
  • 我被黑心中介騙來(lái)泰國(guó)打工遣耍, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留刊殉,地道東北人殉摔。 一個(gè)月前我還...
    沈念sama閱讀 48,798評(píng)論 3 376
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像记焊,于是被迫代替她去往敵國(guó)和親逸月。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,435評(píng)論 2 359

推薦閱讀更多精彩內(nèi)容