1 Chapter 8 Stacks and Queues. 2 This is a stack of books.
-
date post
20-Dec-2015 -
Category
Documents
-
view
218 -
download
0
Transcript of 1 Chapter 8 Stacks and Queues. 2 This is a stack of books.
4
Chap.8 Contents8.1 Stacks 8.1.1 The PureStack Interface 8.1.2 Implementations of the PureStack Interface 8.1.3 Stack Application 1: How Compilers Implement Recursion 8.1.4 Stack Application 2: Converting from Infix to Postfix 8.1.5 Prefix Notation8.2 Queues 8.2.1 The PureQueue Interface 8.2.2 Implementations of the PureQueue Interface 8.2.3 Computer Simulation 8.2.4 Queue Application: A Simulated Car Wash
5
A stack is a special list: the only element 可 remove, access, or modify 的 是最近一次 insert的 element .
8.1 Stacks
6
That is, the element most recently inserted
is the next element to be removed.
Last-In,First-Out (LIFO)
7
Object-Oriented (O-O) Terms
• Stack, Queue 是特別的 list. 以 O-O 術語 , 它們 EXTEND ( 延伸 )
list (ArrayList 或 LinkedList)
General concepts ( 通用觀念 ) are Super class such as ArrayList
Specialized concepts ( 專用觀念 ) are Sub class such as Stack
15
public interface PureStack<E> { /** size * 紀錄在 PureStack有多少 elements * * @return PureStack中 elements 的數量
*/ int size();
8.1.1 The PureStack Interface
16
/** isEmpty * 記錄此 PureStack object是否內部沒有任何 element. * * @return true – 如果此 PureStack object 沒有任何 * elements; 否則, return false. */
boolean isEmpty();
/** push * inserts a 指定的 element
* on the top of this PureStack object. *
* The averageTime(n) is constant and * worstTime(n) is O(n).
* * @param element – the element to be pushed. * */ void push (E element);
17
/** pop * removes the top element from this PureStack object. * * @return – the element removed.
* @throws NoSuchElementException * – 如果此 PureStack is empty.
*/ E pop(); /** peek * returns the top element on this PureStack object. * * @return – the element returned. * @throws NoSuchElementException
* – 如果此 PureStack object is empty. */ E peek(); } // interface PureStack
20
The push, pop and peek methods
are easily defined. For example: public E push (E item)
{ addElement(item); return item; }
21
But NO Vector methods are overridden(覆蓋) 所以可呼叫 vector的任何 method 這會干擾到 stack的定義! For example, it is NOT allowed to remove a stack element at index 7:
myStack.remove (7);
22
解決之道有三: 1. Inherit (繼承) from ArrayList 或 LinkedList
Ugh! 唉阿! Too many overrides. 2. Use an array
protected E[ ] data; protected int top;
Then, top 將會是 array的尾端 (不是前端 index 0)不方便.
3.Aggregate (組成) an ArrayList or LinkedList Yes, and all method definitions are one-liners. 採此法
23
public class LinkedListPureStack <E> { protected LinkedList<E> list; // aggregate a list
public LinkedListPureStack // copy constructor (LinkedListPureStack<E> otherStack)
{ list = new LinkedList<E> (otherStack.list); } public void push (E element) { list.add (element); } // push … } // LinkedListPureStack
24
寫出下列的輸出結果 :LinkedListPureStack<Integer> myStack =
new LinkedListPureStack<Integer>( );
for (int i = 0; i < 10; i++) myStack.push (i * i);
while (!myStack.isEmpty( )) System.out.println (myStack.pop( ));
ANS: 81 (9*9), 64 (8*8), 49, 36, 25, 16, 9, 4, 1, 0
25
8.1.3 Stack 的應用 1: Compiler 如何實作 Recursive
每當有 recursive method 被呼叫, 前一次 method資訊會被儲存,不被覆蓋. 這資訊叫 activation record.
26
Activation record 包含: 1. 呼叫 method的 return address 2. 每個被呼叫 method的 parameter 所對應之
argument 3. 每個被呼叫 method的 local variable
27
Run-time stack 處理 activation records.
Push: When method is called
Pop: When execution of method is completed
28
Decimal to Binary: Ex: get binary “101” from decimal “5” public static String getBinary (int n) { if (n < 0) throw new IllegalArgumentException(); if (n <= 1) return Integer.toString (n); return getBinary(n / 2) + Integer.toString(n % 2); } // method getBinary
30
public static String getBinary (int n) {
ArrayStack<Integer> myStack = new ArrayStack<Integer>();
String binary = new String(); If(n<0)throw new IllegalArgumentException( );
myStack.push (n % 2); while (n > 1) { n /= 2; myStack.push (n % 2); }
while(!myStack.isEmpty()) binary+=myStack.pop();
return binary; } // end of getBinary
32
Exercise: Trace the execution of the above method after an initial call of:
getBinary (20);
show the contents of myStack.
33
8.1.4 Stack 應用 2: 轉換 Infix( 中置式 ) 到 Postfix( 後置式 )
在 infix 表示法中 , operator(運算子 ) 放置於operands(運算元 ) 之間 .
For example: a + b
c – d + (e * f – g * h) / i
34
Old compilers:
Infix Machine language
這會因為 parentheses( 小括號 ) 而產生混亂 .
Newer compilers:
Infix Postfix Machine language
35
在 postfix 表示法中 , an operator 直接地放置於他的 operands之後 . No parenthesis needed.
Infix
Postfix
a + b
ab+
a + b * c
abc*+
a * b + c
ab*c+
(a + b) * c
ab+c*
38
Postfix 保留 operands 的先後順序 ,
so an operand can be appended to postfix as soon as that operand is encountered in infix.
45
As another test case, we start with x*y-z. After moving ‘x’ to postfix,
‘*’ is temporarily saved, and then
‘y’ 被加到 postfix.
What happens when ‘-’ is accessed?
Infix Postfix
x * y – z xy
46
‘*’ 現在一定要移到 postfix 中, 因為‘*’的所有 operands都已在 postfix了. 接著‘-’ 要暫存起來. 在 ‘z’ 被移到 postfix後, ‘-’ 被移到 postfix,
and we are done 我們完成了! Infix Postfix
x * y – z xy*z– (ANS.)
48
for each operator in infix: loop until operator pushed: if operator stack is empty, Push
else if infix operator has greater precedence than top operator on stack,
Push else Pop and append to postfix endif endif endLoop endFor
52
What about parentheses? Left parenthesis: Push, but with lowest 優先權. Right parenthesis: 持續 pop加到 postfix 直到‘(‘ popped; 丟棄‘(‘ 及 ‘)‘
56
為了決定轉換 infix 成 postfix的所有動作, 我們必須知道
1) the current token in infix 2) the top token on operator stack.
58
Top token on Stack
( +, - *, / empty
Operand
)
( +, -
*, /
empty
Append Append Append Append to to to to Postfix Postfix Postfix Postfix
Pop; Pop to Pop to Error Pitch ‘(‘ Postfix Postfix Push Push Push Push Push Pop to Pop to Push Postfix Postfix Push Push Pop to Push Postfix Error Pop to Pop to Done Postfix Postfix
Infi
x to
ken
60
A token 是 program最小有意義單元 (smallest meaningful unit).
Each token has two parts:
1. A generic part, for the category(分類) of the token;
2. A specific part,
to access the characters in the token.
64
Whenever opt is popped from operator stack, opd1 and then opd2 are popped
from operand stack. The string opt + opd2 + opd1
is pushed onto operand stack.
Note: opd2 was pushed before opd1.
67
Infix Prefix a + (b * c – d) / e +a/– *bcde +a/– *bcde /– *bcde e –*bcd d *bc c * b ( a +
Operand Operator stack stack
70
Enqueue –在尾端 insert element Dequeue –在前端 delete element Front – return 前端 element (的 reference)
Queue的 first element inserted will be the first element deleted:
First-In, First-Out (FIFO)
80
8.2.1 The PureQueue Interface
public interface PureQueue<E> {
//size returns elements 數量在此 PureQueue object. int size( );
// isEmpty returns true // if this PureQueue object has no elements. boolean isEmpty( );
81
/**enqueue * inserts 一個指定的 element 在此 PureQueue object. * 的尾端 The averageTime(n) is * constant and worstTime(n) is O(n). * * @param element – the element to be appended. */ void enqueue (E element);
/** dequeue * removes 在此 PureQueue * object最前端的 element. * * @return – the element removed. * @throws NoSuchElementException – if this * PureQueue object is empty. */ E dequeue();
82
/** front * returns the front element in this PureQueue * object. * * @return – the element returned. * * @throws NoSuchElementException – if * PureQueue object is empty. * */ E front(); } // PureQueue
84
為了 code re-use 的目的, the implementation will work with an 現有的 class.
ArrayList?
LinkedList?
8.2.2 Implementations of the PureQueue Interface
85
Inheritance (繼承法):
The implementation of
PureQueue is-a LinkedList
OR Aggregation (組成法):
The implementation of
PureQueue has-a LinkedList
86
Inheritance 帶來沉重負擔: 必須 override 32 個 不適用的 super class methods.
Ex: public E get (int index) { throw new UnsupportedOperationException( );}
87
Heavy Inheritance Tax
在 class reuse 實務上, 被 reuse的 class 要有完整 method description
developers 清楚了解後, 再寫 dummy code ( 如上述 get) 來 override
不能 reuse的 methods.
這是相當沉重的負擔,有如稅負,故叫 Inheritance Tax .
88
So, we’ll use aggregation: public class LinkedListPureQueue<E> implements PureQueue<E> { protected LinkedList<E> list;
89
public LinkedListPureQueue() {list = new LinkedList<E>(); }
public void enqueue (E element) { {list.addLast (element); // same as list.add (element);}
public E dequeue() {return list.removeFirst(); }
90
Determine the output from the following:
LinkedListPureQueue<Integer> myQueue = new LinkedListPureQueue<Integer>();
for (int i = 0; i < 10; i++) myQueue.enqueue (i * i);
while (!myQueue.isEmpty( )) System.out.println (myQueue.dequeue( ));
ANS: 0(0*0),1(1*1),4, 9, 16, 25, 36, 49, 64, 81
95
A 500’ D ? 200’ 500’ C B 400’ E Assumptions: Angle ADC = angle BCD BEC forms a right triangle DCE forms a straight line Line segment AB parallel to DC Distance from A to B?
96
徒手解決 math model 不可行, 所以發展computer program 來計算. Computer simulation: The development of computer programs to solve math models.
100
8.2.4 Queue Application: A Simulated Car Wash
Analysis: 1) One wash station 2) 10 minutes for each car to get washed 3) At any time, at most 5 cars
waiting to be washed; any others:
turned away and not counted
101
carWash
• Minimal waiting time is 0 min.
• Maximal waiting time:10 min*5car= 50 min
car car car car car
queuearrival
departurefrom queue
to queue
Wash Station
102
Average waiting time =
sum of waiting times / number of cars In a given minute,
a departure is processed before an arrival.
103
如果一台車到達時, 剛好沒有車正在洗
(no car is waiting), 那這台車就會立即進入 wash station. 如果有車正在洗,他必須等待. Sentinel (結束訊號) is 999.
105
Time Event Waiting Time 8 Arrival 0 (arri 8) 11 Arrival (arri 11) 11 Arrival (arri 11) 13 Arrival (arri 13) 14 Arrival (arri 14) 16 Arrival (arri 16) 16 Arrival (Overflow)
18 Departure 18 - 11 = 7 7 (arri 11,deq 18) 20 Arrival (arri 20) 28 Departure 17 (arri 11) 38 Departure 25 (arri 13) 48 Departure 34 (arri 14) 58 Departure 42 (arri 16) 68 Departure 48 (arri 20)
Average waiting time = 173.0 minutes / 7 cars = 24.7 minutes per car 本表為本程式輸出
106
Exercise: Given the following arrival times, determine the average waiting time: 4, 8, 12, 16, 23, 999 (the sentinel)
109
/** process * * @param nextArrivalTime下一輛車的到達時間
* the time when the next arrival will occur. * * @throws IllegalArgumentException –
* If nextArrivalTime is less than the current time. */ public void process (int nextArrivalTime)
110
/** finishUp * wash所有尚未 wash的車子 */ public void finishUp() /* getResults * returns 所有 arrival與 departures 紀錄 * 及 average waiting time.
*/ public LinkedList<String> getResults()
111
Fields? First, we’ll decide what variables
will be needed, and then choose the fields from them.
114
為何單獨設計 Car class? 為日後維修方便 We have a Car class for the sake of later modifications to the problem. For example, the cost of a wash might
depend on the number of axles.
115
Car class• /* Car • * 初始化 Car object • * 為指定的下次到達時間• */ • public Car (int nextArrivalTime)
/* getArrivalTime• /* 記錄 the just dequeued car 的 arrival time. • * @return the arrival time of this car • */• public int getArrivalTime()
117
To get the sum of the waiting times:
int currentTime, waitingTime; waitingTime = currentTime – car.getArrivalTime();
計算車子進 wash station前的 waiting time.
119
// time of next arriving car to the queue int nextArrivalTime;
// time of next departing car from the queue
// it is 10000 if no car being washed // so next event will be an arrival int nextDepartureTime;
120
Finally, // to store the: // // arrivals, // departures, and // average waiting time LinkedList<String> results;
122
Fields (Data structure): PureQueue<Car> carQueue; LinkedList<String> results; int currentTime, waitingTime, sumOfWaitingTimes, numberOfCars, nextDepartureTime;//10000 if no car is being washed
123
public CarWash() { carQueue<Car> = new LinkedListPureQueue<Car>(); results = new LinkedList<String>(); results.add (“Time Event Waiting Time”); currentTime = 0; waitingTime = 0; numberOfCars = 0; sumOfWaitingTimes = 0; nextDepartureTime = 10000; } // constructor
124
public void process (int nextArrivalTime) { if (nextArrivalTime < currentTime) throw new IllegalArgumentException(); while (nextArrivalTime >= nextDepartureTime) processDeparture(); processArrival (nextArrivalTime); }
125
protected void processArrival (int nextArrivalTime){ currentTime = nextArrivalTime; results.add (Integer.toString (currentTime) + “\tArrival”);
if (carQueue.size() == 5) results.add (“ (Overflow)\n”); else{ /* not overflow */ numberOfCars++; if/*no car being wash*/(nextDepartureTime == 10000) nextDepartureTime = currentTime + /*wash time*/10; else /* wait in the queue */ carQueue.enqueue (new Car (nextArrivalTime)); results.add ("\n"); }/*else*/ } /*end of processArrival*/
126
protected void processDeparture() { currentTime = nextDepartureTime; results.add (Integer.toString (currentTime) + “\tDeparture\t\t” + Integer.toString (waitingTime) + "\n"); if (!carQueue.isEmpty()) { /* carQueue is not empty */ Car car = carQueue.dequeue(); waitingTime = currentTime – car.getArrivalTime(); sumOfWaitingTimes += waitingTime; nextDepartureTime = currentTime + /*wash time*/ 10; }
else { /* carQueue is empty */ waitingTime = 0; nextDepartureTime = 10000; } //else } // end of processDeparture
127
public class Car{protected int arrivalTime;public Car(){}//default constructor,
//for the sake of sub-classses of Carpublic Car (int nextArrivalTime){
arrivalTime=nextArrivalTime;}// constructor with int parameter
public int getArrivalTime(){return arrivalTime;
}/*getArrivalTime*/ }/*Car*/
128
arrival times 不一定要從 file讀進來, Instead 相反的, we will read in:
int meanArrivalTime; // the average time between arrivals
Then, using
double randomDouble = random.nextDouble( );
to calculate
int timeTillNext = (int)Math.round (-meanArrivalTime *
Math.log (1 - randomDouble) );
129
Exercise: Assume that meanArrivalTime is 3. If Math.log (1 – randomDouble) = –0.6
and currentTime = 25,
When will the next arrival occur?