1.09k likes | 1.24k Views
Abstract Data Types Stack, Queue Amortized analysis. ADT is an interface. It defines the type of the data stored operations, what each operation does (not how) parameters of each operation. ADT. Application. חוזה בין מתכנת האפליקציה ומיישם מבנה הנתונים. ממשק. Implementation of the
E N D
ADT is an interface • It defines • the type of the data stored • operations, what each operation does (not how) • parameters of each operation
ADT Application חוזה בין מתכנת האפליקציה ומיישם מבנה הנתונים ממשק Implementation of the Data structure
Example: Stacks • Push(x,S) : Insert element x into S • Pop(S) : Delete the last element inserted into S • Empty?(S): Return yes if S is empty • Top(S): Return the last element inserted into S • Size(S) • Make-stack()
push push push The Stack Data Abstraction
push The Stack Data Abstraction push push Last in, First out. push pop
A stack application InfixPostfix (2+ 3) * 5 2 3 + 5 * ( (5 * (7 / 3) ) – (2 * 7) ) 5 7 3 / * 2 7 *- • Evaluate an expression in postfix or Reverse Polish Notation
A stack application 2 3 + 5 * 3 2
A stack application 2 3 + 5 * 5 5
A stack application 2 3 + 5 * 25
Pseudo-code S ← make-stack() while ( not eof ) do B ← read the next data; if B is an operand thenpush(B,S) else X ← pop(S) Y ← pop(S) Z ← Apply the operation B on X and Y push(Z,S) return(top(S))
Implementation • We will be interested in algorithms to implement the ADT.. • And their efficiency..
Using an array t 12 1 3 A A[2] A[1] A[N-1] A[0] The stack is represented by the array A and variable t 3 1 12
Using an array t 12 1 3 A A[2] A[1] A[N-1] A[0] The stack is represented by the array A and variable t make-stack(): Allocates the array A, which is of some fixed size N, sets t ← -1
Operations t 12 1 3 A A[2] A[1] A[N-1] A[0] size(S): return (t+1) empty?(S): return (t < 0) top(S): ifempty?(S) then error else return A[t]
Pop t 12 1 3 A A[2] A[1] A[N-1] A[0] pop(S): ifempty?(S) then error else e ←A[t] t ← t – 1 return (e) pop(S)
Pop t 12 1 3 A A[2] A[1] A[N-1] A[0] pop(S): ifempty?(S) then error else e ←A[t] t ← t – 1 return (e) pop(S)
Push t 12 1 3 A A[2] A[1] A[N-1] A[0] push(x,S): ifsize(S) = N then error else t ←t+1 A[t] ← x push(5,S)
Push t 12 1 5 A A[2] A[1] A[N-1] A[0] push(x,S): ifsize(S) = N then error else t ←t+1 A[t] ← x push(5,S)
x x.next x.element Implementation with lists top size=3 5 1 12
Implementation with lists top size=3 5 1 12 make-stack(): top ← null size ← 0
Operations top size=3 5 1 12 size(S): return (size) empty?(S): return (top = null) top(S): ifempty?(S) then error else return top.element
Pop top size=3 5 1 12 pop(S): ifempty?(S) then error else e ←top.element top ← top.next size ← size-1 return (e) pop(S)
Pop top size=2 5 1 12 pop(S): ifempty?(S) then error else e ←top.element top ← top.next size ← size-1 return (e) pop(S)
Garbage collection top size=2 5 1 pop(S): ifempty?(S) then error else e ←top.element top ← top.next size ← size-1 return (e) pop(S)
Push top size=2 5 1 push(x,S): n = new node n.element ←x n.next ← top top ← n size ← size + 1 push(5,S)
Push top size=2 5 1 5 push(x,S): n = new node n.element ←x n.next ← top top ← n size ← size + 1 push(5,S)
Push top size=2 5 1 5 push(x,S): n = new node n.element ←x n.next ← top top ← n size ← size + 1 push(5,S)
Push top size=3 5 1 5 push(x,S): n = new node n.element ←x n.next ← top top ← n size ← size + 1 push(5,S)
Analysis • Bound the running time of an operation on the worst-case • As a function of the “size”, n, of the data structure • T(n) < 4n+7 • Too detailed, we are just interested in the order of growth
Big-O - קיים cו- כך ש: דוגמא:
cg(n) f(n) n0 Big-O
More examples • 4n O(n2) • 4n2 O(n2) • 2n O(n10) • 10 O(1) • 100n3+10n O(n3) • log2(n) O(log10(n))
The running time of our stack and queue operations • Each operation takes O(1) time
Stacks via extendable arrays • We do not want our implementation using arrays to be limited to only N elements • When the array is full we will double its size
Push t 12 1 A A[1] A[N-1] A[0] push(x,S): ifsize(S) = N then allocate a new array of size 2N copy the old array to the new one t ←t+1 A[t] ← x
Push t 12 1 3 3 4 5 7 3 2 8 1 A A[1] A[N-1] A[0] push(x,S): ifsize(S) = N then allocate a new array of size 2N copy the old array to the new one t ←t+1 A[t] ← x push(5,S)
Push t 12 1 3 3 4 5 7 3 2 8 1 A A[1] A[0] push(x,S): ifsize(S) = N then allocate a new array of size 2N copy the old array to the new one t ←t+1 A[t] ← x push(5,S)
Push 12 1 3 3 4 5 7 3 2 8 1 t 12 1 3 3 4 5 7 3 2 8 1 A A[1] A[0] push(x,S): ifsize(S) = N then allocate a new array of size 2N copy the old array to the new one t ←t+1 A[t] ← x push(5,S)
Push t 12 1 3 3 4 5 7 3 2 8 1 A A[1] A[2N-1] A[0] push(x,S): ifsize(S) = N then allocate a new array of size 2N copy the old array to the new one t ←t+1 A[t] ← x push(5,S)
Push t 12 1 3 3 4 5 7 3 2 8 1 5 A A[1] A[2N-1] A[0] push(x,S): ifsize(S) = N then allocate a new array of size 2N copy the old array to the new one t ←t+1 A[t] ← x push(5,S)
Analysis • An operation may take O(n) worst case time ! • But that cannot happen often..
Amortized Analysis • How long it takes to do m operations ? • Well, O(nm) • Yes, but can it really take that long ?
x x
x x x x x
x x x x x x
x x x x x x x x x x x
x x x x x x x x x x x x