1 Abstract Data Types Queue + Dequeue Amortized analysis.
-
date post
22-Dec-2015 -
Category
Documents
-
view
237 -
download
3
Transcript of 1 Abstract Data Types Queue + Dequeue Amortized analysis.
26
Can one Implement A Queue with stacks?
S2
•You are given the STACK ABSTRACT data structure (1, 2 .. as many as you want)
•Can you use it to implement a queue
S1
5 4 17 21Q5 4 17 21
27
Implementation of Queue with stacks
size=5
13S1S2
inject(x,Q): push(x,S2); size ← size + 1
5 4 17 21
inject(2,Q)
28
Implementation with stacks
size=5
13S1S2
inject(x,Q): push(x,S2); size ← size + 1
5 4 17 21 2
inject(2,Q)
29
Implementation of a Queue with stacks
size=6
13S1S25 4 17 21 2
inject(2,Q)
inject(x,Q): push(x,S2); size ← size + 1
30
Pop
size=6
S1S2
pop(Q): if empty?(Q) error if empty?(S1) then move(S2, S1) pop( S1); size ← size -1
5 4 17 21 2
pop(Q)
13
31
Pop
size=6
S1S2
pop(Q): if empty?(Q) error if empty?(S1) then move(S2, S1) pop( S1); size ← size -1
5 4 17 21 2
pop(Q)
32
Pop
size=5
S1S2
pop(Q): if empty?(Q) error if empty?(S1) then move(S2, S1) pop( S1); size ← size -1
5 4 17 21 2
pop(Q)
pop(Q)
33
Pop
size=5
S1S2
pop(Q): if empty?(Q) error if empty?(S1) then move(S2, S1) pop( S1); size ← size -1
5 4 17 21
pop(Q)
pop(Q)
2
34
Pop
size=5
S1S2
pop(Q): if empty?(Q) error if empty?(S1) then move(S2, S1) pop( S1); size ← size -1
5 4 17
pop(Q)
pop(Q)
221
35
Pop
size=5
S1S2
pop(Q): if empty?(Q) error if empty?(S1) then move(S2, S1) pop( S1); size ← size -1
5 4
pop(Q)
pop(Q)
22117
36
Pop
size=5
S1S2
pop(Q): if empty?(Q) error if empty?(S1) then move(S2, S1) pop( S1); size ← size -1
5
pop(Q)
pop(Q)
221174
37
Pop
size=5
S1S2
pop(Q): if empty?(Q) error if empty?(S1) then move(S2, S1) pop( S1); size ← size -1
pop(Q)
pop(Q)
2211745
38
Pop
size=4
S1S2
pop(Q): if empty?(Q) error if empty?(S1) then move(S2, S1) pop( S1); size ← size -1
pop(Q)
pop(Q)
221174
41
Amortized Analysis
• How long it takes to perform m operations on the worst case ?
• O(nm)
• Is this tight ?
43
Amortized complexity
THM: If we start with an empty queue and perform m operations then it takes O(m) time
Proof:• No element moves from S2 to S1• Entrance at S1, exit at S2.
• Every element:1. Enters S1 exactly once2. Moves from S1 to S2 at most once3. Exits S2 at most once
#ops per element ≤ 3 • m operations #elements ≤ m work ≤ 3 m
S2S15 42217
47
Potential based Proof (on your own)
Consider2( ) | |D S
Recall that: Amortized(op) = actual(op) + ΔΦ
This is O(1) if a move does not occur
Say we move S2:Then the actual time is |S2| + O(1)
ΔΦ = -|S2|
So the amortized time is O(1)
Think of Φ as accumulation of easy operations covering for future potential “damage”
49
Double ended queue (deque)
• Push(x,D) : Insert x as the first in D• Pop(D) : Delete the first element of D• Inject(x,D): Insert x as the last in D• Eject(D): Delete the last element of D• Size(D)• Empty?(D)• Make-deque()
52
Push
push(x,D): n = new node n.element ←x n.next ← head.next (head.next).prev ← n head.next ← n n.prev← head size ← size + 1
5
head
size=1
tail
53
push(x,D): n = new node n.element ←x n.next ← head.next (head.next).prev ← n head.next ← n n.prev← head size ← size + 1
5
head
size=1
tail
push(4,D)
4
54
push(x,D): n = new node n.element ←x n.next ← head.next (head.next).prev ← n head.next ← n n.prev← head size ← size + 1
5
head
size=1
tail
push(4,D)
4
55
push(x,D): n = new node n.element ←x n.next ← head.next (head.next).prev ← n head.next ← n n.prev← head size ← size + 1
5
head
size=1
tail
push(4,D)
4
56
push(x,D): n = new node n.element ←x n.next ← head.next (head.next).prev ← n head.next ← n n.prev← head size ← size + 1
5
head
size=2
tail
push(4,D)
4
61
Pop
size=6
S1S2
pop(D): if empty?(D) error if empty?(S1) then split(S2, S1) pop( S1)
2 13
5 4 17 21
pop(D)
62
Pop
size=5
S1S2
pop(D): if empty?(D) error if empty?(S1) then split(S2, S1) pop( S1)
13 5 4 17 21
pop(D)
pop(D)
63
Pop
size=4
S1S2
pop(D): if empty?(D) error if empty?(S1) then split(S2, S1) pop( S1)
5 4 17 21
pop(D)
pop(D)
64
Pop
5 4 17 21
size=4
S1S2
pop(D): if empty?(D) error if empty?(S1) then split(S2, S1) pop( S1)
pop(D)
65
Pop
5 4 17 21
size=4
S1S2
pop(D): if empty?(D) error if empty?(S1) then split(S2, S1) pop( S1)
pop(D)
66
Pop
17 21
size=4
S1S2
pop(D): if empty?(D) error if empty?(S1) then split(S2, S1) pop( S1)
pop(D)
5 4
67
Pop
17 21
size=4
S1S2
pop(D): if empty?(D) error if empty?(S1) then split(S2, S1) pop( S1)
pop(D)
4
68
Pop
17 21
size=3
S1S2
pop(D): if empty?(D) error if empty?(S1) then split(S2, S1) pop( S1)
pop(D)
4
77
split(S2, S1)
S3 ← make-stack() d ← size(S2) while (i ≤ ⌊d/2⌋) do x ← pop(S2) push(x,S3) i ← i+1 while (i ≤ ⌈d/2⌉) do x ← pop(S2) push(x,S1) i ← i+1 while (i ≤ ⌊d/2⌋) do x ← pop(S3) push(x,S2) i ← i+1
82
A better boundConsider
1 2( ) || | | ||D S S
This is O(1) if no splitting occursSay we split S1:Then the actual time is |S1| + O(1)
ΔΦ = -|S1| (S2 empty)
So the amortized time is O(1)
Recall that: Amortized(op) = actual(op) + ΔΦ
Think of Φ as accumulation of easy operations covering for future potential “damage”