講師:洪安
堆疊與佇列
Stack and Queue
堆疊與佇列 (1/3)
堆疊 (Stack)
堆疊結構表示法
發牌問題
老鼠走迷宮問題 佇列 (Queue)
佇列結構表示法
排隊問題堆疊與佇列 (2/3)
堆疊(Stack)
加入(push)與刪除(pop)於同一端
具有後進先出(LIFO, Last-in-First-out)或先進後出 (FILO, First-in-Last-out)性質的有序串列
例子:疊盤子、發牌、走迷宮 佇列(Queue)
加入(enqueue)與刪除(dequeue)於不同端(front &rear)
先進先出(FIFO, First-in-First-out)
例子:排隊買票、坐公車pop
堆疊與佇列 (3/3)
#0
#n-1 stack
#0 #1
#n-1
queue
enqueue dequeue
push
top
front rear
堆疊結構表示法-陣列 (1/4)
類別定義
建構函數定義 class Stack {
int stack[MAX_SIZE];
int top;
public:
Stack();
void push(int value);
int pop();
};
Stack::Stack() { top = -1;
}
堆疊結構表示法-陣列 (2/4)
加入堆疊
void Stack::push(int value) {
if( top >= (MAX_SIZE-1) ) {
cout<<"堆疊容量超過!\n";
exit(-1);
}
//更新變數top top++;
stack[top] = value;
}
堆疊結構表示法-陣列 (3/4)
取出堆疊 int Stack::pop() {
int temp;
if( top<0 ) //判斷堆疊是否為空的 {
cout<<"堆疊容量為空的!\n";
return -1;
}
temp = stack[top];
//更新變數top top--;
return temp;
}
堆疊結構表示法-陣列 (4/4)
列出堆疊中的所有元素
堆疊結構表示法-鏈結串列 (1/4)
類別定義
建構函數定義
class node { private:
int data;
node *next;
friend class Stack;
};
class Stack { node *top;
public:
Stack();
void push(int value);
int pop();
};
Stack::Stack(){
top=NULL;
}
堆疊結構表示法-鏈結串列 (2/4)
加入堆疊
void Stack::push(int value) {
node *new_node;
new_node = new node;
if( new_node == NULL){ //判斷配置是否成功 cout << "記憶體配置失敗!\n";
exit(1);
}
new_node->data = value;
new_node->next = top;
top = new_node;
}
NULL
top
1
top
2 3
1
2 3
堆疊結構表示法-鏈結串列 (3/4)
取出堆疊
int Stack::pop() {
int temp;
node *ptr;
if( top != NULL ) //判斷堆疊是否為空的 {
//更新top, temp, stack指標 ptr = top; //1
top = top->next; //2 temp = ptr->data; //3 free(ptr); //4
return temp;
} else
exit(1);
}
11
NULL
top
1
2 3
ptr
top temp
4
堆疊結構表示法-鏈結串列 (4/4)
列出堆疊中的所有元素
free(ptr);
課堂練習-發牌問題
使用堆疊結構實作發牌程式
8_stack_array.cpp
8_stack_linkedlist.cpp
補充:隨機產生亂數
產生隨機亂數的函式:rand()
需#include<stdlib.h>
Ex: 產生一個0~99的整數亂數a = rand()%100;
Ex: 產生100~200的整數亂數 a= rand()%100+100; 初始化亂數表:srand(time(NULL))
需 #include <time.h>
功能:以電腦的時間作為亂數表的起始參數,否則每 次程式執行所取的亂數都會一樣課堂練習-老鼠走迷宮問題 (1/2)
使用堆疊結構實作老鼠走迷宮問題
8_stack_maze.cpp 0 可走
1 不能走
3 死路2 正確路徑
1 1 1 1 1 1 1 1 1 1 1 0 1 0 1 0 0 0 0 1 1 0 1 0 1 0 1 1 0 1 1 0 1 0 1 1 1 0 0 1 1 0 1 0 0 0 0 0 1 1 1 0 0 0 1 1 1 0 0 1 1 1 1 1 1 1 1 1 1 1
起點 (1,1)
終點 (8,5)
課堂練習-老鼠走迷宮問題 (2/2)
使用堆疊結構實作老鼠走迷宮問題
8_stack_maze.cpp 0 可走
1 不能走
3 死路2 正確路徑
1 1 1 1 1 1 1 1 1 1 1
2
13
13 3 3 3
1 12
13
13
1 13
1 12
13
1 1 13 3
1 12
12 2 2 2 2
1 1 12 2 2
1 1 12 2
1 1 1 1 1 1 1 1 1 1 1起點 (1,1)
終點 (8,5)
堆疊的應用-副程式的呼叫和返回
a
b a
程式A呼叫副程式B 程式B再呼叫副程式C
堆疊的應用-河內塔(1/2)
堆疊的應用
http://tw.t45ol.com/play/137/tower-of-hanoi.html
1. 每次僅可搬移一個碟片
2. 從某一根柱子上取出之碟片一定要放到另外兩根柱子之一後才可以再 搬另一個碟片
3. 無論何時,每一根柱子上之碟片都要保持上小下大的排列方式
A 柱
(a)
B 柱 C 柱
C 柱 B 柱
A 柱
19
堆疊的應用-河內塔(2/2)
當 N=3 時,整個搬移過程為:
o 步驟 < 1> 從 A 柱搬 1 號碟片到 C 柱
o 步驟 < 2> 從 A 柱搬 2 號碟片到 B 柱
o 步驟 < 3> 從 C 柱搬 1 號碟片到 B 柱
o 步驟 < 4> 從 A 柱搬 3 號碟片到 C 柱
o 步驟 < 5> 從 B 柱搬 1 號碟片到 A 柱
o 步驟 < 6> 從 B 柱搬 2 號碟片到 C 柱
o 步驟 < 7> 從 A 柱搬 1 號碟片到 C 柱
佇列結構表示法-陣列 (1/3)
類別定義
建構函數定義
佇列結構表示法-陣列 (2/3)
加入佇列
佇列結構表示法-陣列 (3/3)
取出佇列
佇列結構表示法-鏈結串列 (1/3)
類別定義
建構函數定義
佇列結構表示法-鏈結串列 (2/3)
加入佇列
佇列結構表示法-鏈結串列 (3/3)
取出佇列
小練習
實作佇列結構
實作enqueue()和dequeue()成員函數
實作print()成員函數 此函數可印出所有佇列中的資料
int main() {
Queue q;
q.enqueue(10);
q.enqueue(20);
q.enqueue(25);
q.print();
q.dequeue();
q.print();
system("pause");
return 0;
} 主程式
輸出
課堂練習-加入使用者介面
使用佇列結構加上使用者介面,讓使用者加入資料、
取出資料
8_queue_array.cpp
8_queue_linkedlist.cpp
佇列的應用-優先佇列 (1/2)
優先佇列結構 (採用陣列實施)
front_b,B 等級佇列的首端 C4
C3 C2 C1 4
3 2 1 0
B2 B1 A3 A2 A1 8
7 6 5
A 等級 B 等級 C 等級
rear_a ,A 等級佇列的尾端
front_a,A 等級佇列的首端 front_c,C 等級佇列的首端 rear_c ,C 等級佇列的尾端
rear_b ,B 等級佇列的尾端
佇列的應用-優先佇列 (2/2)
優先佇列結構(採用鏈結串列實施)
Priority Queue
A2
A1 A3 B1 B2 C1 C2 C3
front rear_a rear_b rear_c 0
C4 0
B3
佇列的應用-雙向佇列
左端佇列加入A、B、C,右端佇列加入甲、乙、丙
A 0
B 1
C
2 3
丙 n-3
乙 n-2
甲 n-1 n-4
‧‧‧
fl
rl
fr
rr