## 定義 通常討論時會唸英文,但硬要說中文就是雙向佇列 在線性資料結構中,資料可以從任一端進入,也可以從任一端取出資料 基本上就是 stack 跟 queue 的結合,在功能上也可以取代它們兩個 雙向佇列通常會使用幾個基本的功能:push_front()、pop_front()、push_back()、pop_back() 還有 front()、back()、empty()、size() * push_front() : 將資料推入 deque 的最前端 * pop_front() : 將 deque 最前端的資料取出(刪除) * push_back() : 將資料推入 deque 的最後端 * pop_back() : 將 deque 最後端的資料取出(刪除) * front() : 回傳 deque 最前端的資料 * back() : 回傳 deque 最後端的資料 * empty() : 回傳 deque 是否為空 * size() : 回傳 deque 的大小 ## 實作 通常會有多個方法實作,不過競程的大部分題目只需要用到 STL 內建的 deque 實際競賽上不太會需要自己搓一個,所以這裡的做法參考就好,知道怎麼做就可以了 以下是陣列的做法,用比較偷懶的方式實作的 ```cpp= #include<bits/stdc++.h> using namespace std ; int D[100] ; // deque 大小最多為 100 int f = 0, r = 0 ; // f 目前最前端(左邊)的位置, r 目前最尾端(右邊)的位置 void bpush_front(int data) { // push_front() 為內建函式,故取他名迴避 if ((r+1)%100 != f) { D[f] = data ; f = (f+99) % 100 ; } else cout << "The deque is already full." ; // 裝滿的 deque 沒辦法 push return ; } void bpush_back(int data) { // push_back() 為內建函式,故取他名迴避 if ((r+1)%100 != f) { D[r] = data ; r = (r+1) % 100 ; } else cout << "The deque is already full." ; // 裝滿的 deque 沒辦法 push return ; } void bpop_front() { // pop_front() 為內建函式,故取他名迴避 if (f != r) { D[f] = 0 ; f = (f+1) % 100 ; } else cout << "The deque is already empty." ; // 空 deque 沒辦法 pop return ; } void bpop_back() { // pop_back() 為內建函式,故取他名迴避 if (f != r) { D[r] = 0 ; r = (r+99) % 100 ; } else cout << "The deque is already empty." ; // 空 deque 沒辦法 pop return ; } int bfront() { if (f != r) return D[(f+1)%100] ; cout << "The deque is already empty." ; // 空 deque 沒辦法 front return -1 ; // 回傳 -1 表示 error } int bback() { if (f != r) return D[(r+99)%100] ; cout << "The deque is already empty." ; // 空 deque 沒辦法 back return -1 ; // 回傳 -1 表示 error } bool bempty() { // empty() 為內建函式,故取他名迴避 return f == r ; } int bsize() { // size() 為內建函式,故取他名迴避 return (r-f+100)%100 ; } int main() { ios::sync_with_stdio(0), cin.tie(0) ; int n, data ; cin >> n ; // 有 n 筆資料需要傳入 deque for (int i=0;i<n;i++) { cin >> data ; bpush_front(data) ; bpush_back(data) ; } while (!bempty()) { // 取出並輸出 deque 資料直到 deque 為空 data = bfront() ; bpop_front() ; cout << data << ' ' ; data = bback() ; bpop_back() ; cout << data << ' ' ; } return 0 ; } ``` --- 以下是 Linked List 實作的方式 ```cpp= #include<bits/stdc++.h> using namespace std ; struct Node { // Linked List 的結構 int data ; Node* next ; Node* prev ; } ; void bpush_front(Node* curr, int data) { Node* new_node = new Node ; new_node->data = data ; new_node->next = curr ; new_node->prev = curr->prev ; curr->prev->next = new_node ; curr->prev = new_node ; return ; } void bpush_back(Node* curr, int data) { Node* new_node = new Node ; new_node->data = data ; new_node->next = curr->next ; new_node->prev = curr ; curr->next->prev = new_node ; curr->next = new_node ; return ; } void bpop_front(Node* curr) { curr = curr->prev ; if (curr->data != -1) { Node* now = curr ; now->next->prev = now->prev ; now->prev->next = now->next ; delete now ; } else cout << "The deque is already empty." ; // 空 deque 沒辦法 pop return ; } void bpop_back(Node* curr) { curr = curr->next ; if (curr->data != -1) { Node* now = curr ; now->next->prev = now->prev ; now->prev->next = now->next ; delete now ; } else cout << "The deque is already empty." ; // 空 deque 沒辦法 pop return ; } int bfront(Node* curr) { curr = curr->prev ; if (curr->data != -1) // deque 非空 return curr->data ; cout << "The deque is already empty." ; // 空 deque 沒辦法 front return -1 ; // 回傳 -1 表示 error } int bback(Node* curr) { curr = curr->next ; if (curr->data != -1) // deque 非空 return curr->data ; cout << "The deque is already empty." ; // 空 deque 沒辦法 back return -1 ; // 回傳 -1 表示 error } int bsize(Node* curr) { // size() 為內建函式,故取他名迴避 Node *now = curr->prev ; int len = 0 ; while (curr != now) { if (now->data != -1) len++ ; now = now->prev ; } return len ; } bool bempty(Node* curr) { // empty() 為內建函式,故取他名迴避 return curr->prev->data == -1 ; } int main() { ios::sync_with_stdio(0), cin.tie(0) ; // 初始化(next 向右、prev 向左) Node *head = new Node ; // 最右端 Node *tail = new Node ; // 最左端 head->data = -1 ; head->next = head->prev = tail ; tail->data = -1 ; tail->next = tail->prev = head ; int n, data ; cin >> n ; // 有 n 筆資料需要傳入 deque for (int i=0;i<n;i++) { cin >> data ; bpush_front(head, data) ; bpush_back(tail, data) ; } while (!bempty(head)) { // 取出並輸出 deque 資料直到 deque 為空 data = bfront(head) ; bpop_front(head) ; cout << data << ' ' ; data = bback(tail) ; bpop_back(tail) ; cout << data << ' ' ; } return 0 ; } ``` ## STL deque ```cpp= #include<bits/stdc++.h> using namespace std ; int main() { ios::sync_with_stdio(0), cin.tie(0) ; deque<int> dq ; // 宣告一個儲存 int 的 deque int n, data ; cin >> n ; for (int i=0;i<n;i++) { cin >> data ; dq.push_front(data) ; // push data 進 dq dq.push_back(data) ; // push data 進 dq } while (!dq.empty()) { // 同 while (dq.size() > 0) cout << dq.front() << ' ' ; // 輸出 top dq.pop_front() ; // 取出 cout << dq.back() << ' ' ; // 輸出 top dq.pop_back() ; // 取出 } return 0 ; } ``` ## 總結 deque 可以同時做到 stack 跟 queue 的功能,但速度上會比較慢 之後在比較進階的演算法會用到 deque,但目前會用 STL 的 deque 就可以了