什么是隊列
隊列是一種列表,不同的是隊列只能在隊尾插入元素,在隊首刪除元素。隊列用于存儲按 順序排列的數(shù)據(jù),先進先出,這點和棧不一樣,在棧中,最后入棧的元素反而被優(yōu)先處 理。
隊列是一種先進先出(First-In-First-Out,F(xiàn)IFO)的數(shù)據(jù)結(jié)構(gòu)。
隊列的實現(xiàn)
在JavaScript中,我們可以用如下函數(shù)實現(xiàn)隊列:
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() 顯示隊列內(nèi)的所有元素
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;
}
}
//顯示元素個數(shù)
function count() {
return this.dataStore.length;
}
實戰(zhàn)
習題一
使用隊列來模擬跳方塊舞的人。當 男男女女來到舞池,他們按照自己的性別排成兩隊。當舞池中有地方空出來時,選兩個隊 列中的第一個人組成舞伴。他們身后的人各自向前移動一位,變成新的隊首。當一對舞伴 邁入舞池時,主持人會大聲喊出他們的名字。當一對舞伴走出舞池,且兩排隊伍中有任意 一隊沒人時,主持人也會把這個情況告訴大家。
代碼如下:
// 模擬舞會成員
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.");
}
結(jié)果如下:
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 的數(shù)字,基數(shù)排序?qū)?shù)據(jù)集掃描兩次。第一次按個位上的數(shù)字進行排序,第二 次按十位上的數(shù)字進行排序。每個數(shù)字根據(jù)對應(yīng)位上的數(shù)值被分在不同的盒子里。
用以上算法對數(shù)據(jù)進行排序。
思路:
我們需要九個隊列,每個對應(yīng)一個數(shù)字。將所有 隊列保存在一個數(shù)組中,使用取余和除法操作決定個位和十位。算法的剩余部分將數(shù)字加 入相應(yīng)的隊列,根據(jù)個位數(shù)值對其重新排序,然后再根據(jù)十位上的數(shù)值進行排序,結(jié)果即 為排好序的數(shù)字。
// nums 要排序的數(shù)字數(shù)組。 queues 0-9隊列數(shù)組 n 數(shù)字的個數(shù) 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])
}
}
}
// 從隊列中收集數(shù)字
function collect(queues, nums) {
var i = 0;
for (var digit = 0; digit < 10; digit++) {
while (!queues[digit].empty()) {
nums[i++] = queues[digit].dequeue();
}
}
}
// 顯示數(shù)組
function dispArray(arr) {
console.log(arr);
}
var queues = [];
for (var i = 0; i < 10; i++) {
queues[i] = new Queue();
}
var nums = [];
// 隨機生成10個數(shù)字
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);
結(jié)果可能如下:
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 類。這是一個和隊列類似的數(shù)據(jù)結(jié)構(gòu),允許從隊列兩端 添加和刪除元素,因此也叫雙向隊列。寫一段測試程序測試該類
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() 顯示隊列內(nèi)的所有元素
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;
}
}
//顯示元素個數(shù)
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);
結(jié)果如下:
[ '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 類來判斷一個給定單詞是否為回文。
思路:
將字符串中的字符挨個推入雙向隊列中。然后每次彈出隊列的首部元素和尾部元素進行比較。如果不相等,就說明不是回文。當雙向隊列中的元素只剩一個或一個不剩,循環(huán)結(jié)束。
代碼如下:
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