基礎
上一節我總結了一下棧的資料結構,它在前端中的應用以及一些面試常問的題目。今天我總結一下佇列,棧和佇列總是孟不離焦。佇列也是一種特殊的線性表,可以用陣列或者連結串列實現。它和棧的不同點在於,棧是先進後出,而佇列中的資料總是先進先出。
假如有一個序列1,2,3,4,5。將它按順序加入佇列中,它的結構如下圖:
在現實生活中,排隊就是一個典型的佇列,不能插隊,只能排到隊尾,隨著前面的人辦完事出佇列,最後會輪到你。
而在JS的程式的事件迴圈中同樣用到了佇列,JS的在執行時會維護一個event queue,遇到非同步任務會將其加入event queue,執行完同步任務,就會從event queue中拿出非同步任務繼續執行。
佇列的實現
同樣js的陣列提供shift()方法,它可以刪除陣列的第一個元素。陣列提供的方法使我們可以很容易的用陣列來實現佇列這種資料結構。
實現佇列需要實現以下幾個基本的方法:enqueue(入佇列),dequeue(出佇列),head(返回佇列第一個元素),size(返回佇列的大小),clear(清除佇列),isEmpty(判斷佇列是否為空)。
function Queue() {
let items = [];
this.enqueue = function(item) {
items.push(item);
}
this.dequeue = function(item) {
return items.shift()
}
this.head = function() {
return items[0];
}
this.size = function() {
return items.length;
}
this.clear = function() {
items = []
}
this.isEmpty = function() {
return items.length == 0;
}
}
複製程式碼
佇列的應用題
- 佇列與棧的相互轉換
我們學習完棧和佇列這兩種資料結構之後就可以思考,如何用棧來實現一個佇列,又如何用佇列來實現一個棧。
用兩個佇列實現一個棧:
function QueueStack() {
let queue1 = new Queue();
let queue2 = new Queue();
let empty_queue = null;
let data_queue = null;
function initQueue() {
if (queue1.isEmpty() && queue2.isEmpty()) {
data_queue = queue1;
empty_queue = queue2;
} else if (queue1.isEmpty()) {
data_queue = queue2;
empty_queue = queue1;
} else {
data_queue = queue1;
empty_queue = queue2;
}
}
this.push = function(item) {
initQueue();
data_queue.push(item);
}
this.pop = function(item) {
initQueue();
while (data_queue.size() > 1) {
empty_queue.enqueue(data_queue.dequeue());
}
return data_queue.dequeue();
}
this.top = function() {
initQueue();
while (data_queue.size() > 1) {
empty_queue.enqueue(data_queue.dequeue());
}
let head = data_queue.head();
empty_queue.enqueue(data_queue.dequeue());
return head;
}
}
複製程式碼
用兩個棧實現一個佇列:
function StackQueue() {
let push_stack = new Stack();
let pop_stack = new Stack();
this.enqueue = function(item) { //醉了
push_stack.push(item);
}
this.dequeue = function() {
if (pop_stack.size() != 0) {
return pop_stack.pop();
} else {
while (push_stack.size()) {
let item = push_stack.pop();
pop_stack.push(item);
}
return pop_stack.pop();
}
}
this.head = function() {
if (pop_stack.size() != 0) {
return pop_stack.top();
} else {
while (push_stack.size()) {
let item = push_stack.pop();
pop_stack.push(item);
}
return pop_stack.top();
}
}
}
複製程式碼