Stacks and Queues

Stacks 與 Queues 是相對單純的資料結構,在取得資料時,只會依序取得最前或最後的那一筆資料,目的也是為了限制資料的使用; 而實作上,並不限於使用 Array 或 Linked List,只要符合個別的定義都可以稱為 Stacks 或 Queues。

Stacks

採用後進先出 last-in-first-out (LIFO) 的方式排列,可以想像成蝶盤子的形式,最後疊上來的盤子會優先被取出,使用上常用於操昨工具時的上一步或瀏覽器的上一頁

Method

  • pop: 刪除最上層的一筆資料,時間複雜度為 O(1)
  • push: 加入一筆資料在最上層,時間複雜度為 O(1)
  • peek: 取得最上層的一筆資料,但不刪除資料,時間複雜度為 O(1)
  • isEmpty: 檢查 Stacks 是否為空

在 JavaScript 中,Array 有直接提供 method 來完成 Stack 的需求,而如果採用 Linked List 來實作,就需要使用 Doubly Linked List 來提供 previous data

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
export class Node {
value: any;
next: Node | null;
prev: Node | null;

constructor(value: any) {
this.value = value;
this.next = null;
this.prev = null;
}
}

export default class Stacks {
length: number;
head: Node | null;
tail: Node | null;

push(value: any) {
const newNode = new Node(value);

if (this.length === 0) {
this.head = newNode;
this.tail = newNode;
} else {
newNode.prev = this.tail;
this.tail!.next = newNode;
this.tail = newNode;
}
this.length++;
}

pop() {
if (this.length === 0) {
return null;
} else if (this.length === 1) {
const value = this.tail!.value;
this.head = null;
this.tail = null;

return value;
} else {
const value = this.tail!.value;
this.tail = this.tail!.prev;
this.tail!.next = null;

return value;
}
}

peek() {
if (this.length === 0) {
return null;
} else {
return this.tail!.value;
}
}

isEmpty() {
return this.length === 0;
}
}

Queues

採用先進先出 first-in-first-out (FIFO) 的方式排列,可以想像成排隊的人潮,第一個排隊的人就可以優先進場

Method

  • add (enqueue): 加入一筆資料在最後面,時間複雜度為 O(1)
  • remove (dequeue): 移除最前面的一筆資料,時間複雜度為 O(1)
  • peek: 取得最前面的一筆資料,但不刪除資料,時間複雜度為 O(1)
  • isEmpty: 檢查 Queues 是否為空
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
export class Node {
value: any;
next: Node | null;
prev: Node | null;

constructor(value: any) {
this.value = value;
this.next = null;
this.prev = null;
}
}

export default class Queues {
length: number;
head: Node | null;
tail: Node | null;

add(value: any) {
const newNode = new Node(value);
if (this.length === 0) {
this.head = newNode;
this.tail = newNode;
} else {
newNode.next = this.head;
this.head!.prev = newNode;
this.head = newNode;
}
this.length++;
}

remove() {
if (this.length === 0) {
return null;
} else if (this.length === 1) {
const value = this.head!.value;
this.head = null;
this.tail = null;

return value;
} else {
const value = this.head!.value;
this.head = this.head!.next;
this.head!.prev = null;

return value;
}
}

peek() {
if (this.length === 0) {
return null;
} else {
return this.head!.value;
}
}

isEmpty() {
return this.length === 0;
}
}

Array 與 Linked List 比較

在 JavaScript 中,如果使用 Array 來實作 Stacks 與 Queues,其實都有預設的 Array functions 可以直接達到目的,只是因為 Queues 所使用的 remove (unshift) 會改變所有 Array 的 index,所以在效能上會比較差 (同理 shift 也是),所以如果有效能上的考量,Queues 會建議使用 Linked List 來進行實作。

資料參考

Cracking the Coding Interview
[資料結構] Stacks and Queues