Abstract Data Types - PowerPoint PPT Presentation

1 / 48
About This Presentation
Title:

Abstract Data Types

Description:

Build a structure to hold: a list of items in the queue. a ... (car (cdr (filter prime? (enumerate-interval 10000 1000000)))) Requires a lot of time and space ... – PowerPoint PPT presentation

Number of Views:77
Avg rating:3.0/5.0
Slides: 49
Provided by: duaneb3
Category:
Tags: abstract | data | types

less

Transcript and Presenter's Notes

Title: Abstract Data Types


1
Lecture 15
Abstract Data Types Streams (We will only start
this topic)
2
Wed Lecture and Friday Midterm
  • Notice Wed lecture will be rehearsal for
    midterm
  • Exam on Friday starts at 9AM

3
Last lecture
  • The environment modela new model to explain the
    semantics of our language
  • New model provides notion of state
  • Allows us to introduce mutation

4
Stack Data Abstraction
Last in, First out.
Insert
Delete
5
Stack Data Abstraction
  • constructor (make-stack) returns an empty
    stack
  • selectors (top stack) returns current top
    element from a stack
  • operations (insert stack elem) returns a new
    stack with the element added to the top of
    the stack (push)
  • (delete stack) returns a new stack with the
    top element removed from the stack (pop)
  • (empty-stack? stack) returns t if no elements,
    f otherwise
  • contract
  • (delete stack) require (not (empty-stack? stack))
  • (top stack) require (not (empty-stack? stack))
  • ensure (equal? (delete (insert stack elem))
    stack)
  • ensure (equal? (top (insert stack elem)) elem)

6
Stack Implementation Strategy
  • implement a stack as a list

d
b
a
  • we will insert and delete items at the front of
    the stack

7
Functional Stack Implementation
  • (define (make-stack) nil)
  • (define (empty-stack? stack) (null? stack))
  • (define (insert stack elem) (cons elem stack))
  • (define (delete stack)
  • (if (empty-stack? stack)
  • (error "stack underflow delete")
  • (cdr stack)))
  • (define (top stack)
  • (if (empty-stack? stack)
  • (error "stack underflow top")
  • (car stack)))

8
Limitations in our Stack
  • Stack does not have identity
  • (define s (make-stack))
  • s gt ()
  • (insert s 'a) gt (a)
  • s gt ()
  • (set! s (insert s 'b))
  • s gt (b)

9
Mutable Stack Implementation
The stack will be a mutable data type.
  • The data type contains a list of elements as
    before.
  • Insert and delete mutate a stack object.
  • The first element of the list is special to
    distinguish
  • Stack objects from other lists defensive
    programming

10
Mutable Stack Data Abstraction
  • constructor (make-stack) returns an empty
    stack
  • queries (selectors) (top stack) returns
    current top element from a stack (empty-stack?
    stack) returns t if no elements, f otherwise
  • (stack? any) returns t if any is a
    stack, f otherwise
  • command (mutators, transformers) (insert!
    stack elem) modify the stack by adding
    elem to the top of the stack (push)
  • (delete! stack) modify the stack by removing
    the top element from the stack (pop)

stack? is really not part of the stack abstraction
11
Mutable Stack Implementation (1)
  • (define (make-stack) (cons 'stack nil))

(define (stack? stack) (and (pair? stack) (eq?
'stack (car stack))))
(define (empty-stack? stack) (null? (cdr
stack)))
(define (top stack) (if (empty-stack? stack)
(error "stack underflow top") (cadr
stack)))
12
Mutable Stack Implementation (2)
  • (define (insert! stack elem)
  • (set-cdr! stack (cons elem (cdr stack)))
  • stack))
  • (define (delete! stack)
  • (if (empty-stack? stack)
  • (error "stack underflow delete")
  • (set-cdr! stack (cddr stack)))
  • stack)

Here the mutators return the stack. May choose to
return a neutral value, eg. ok or nothing (more
later)
13
Mutatable vs. functional
  • The decision between a mutable stack and a
    functional stack is part of the contract
  • Changing this changes the abstraction!
  • The user should know if the object mutates or not
    in order to use the abstraction correctly
  • For example, if we write
  • (define stack1 stack2)
  • can stack1 later change because of changes to
    stack2 ?

14
A Queue
FIFO First In, First Out
15
A Queue
Insert
Insert
FIFO First In, First Out
Insert
x3
x2
Delete
16
A Queue Implementation
  • A queue is a list of elements
  • The front of the queue is the first element in
    the list
  • To insert an element at the tail of the queue,
    need to scan the entire list, then attach the new
    element at the rear

d
new
c
b
17
A Queue Implementation (Cont)
  • (define (make-queue) null)
  • (define (empty-queue? q) (null? q))
  • (define (front-queue q)
  • (if (empty-queue? q)
  • (error "front of empty queue" q)
  • (car q)))
  • (define (delete-queue q)
  • (if (empty-queue? q)
  • (error "delete of empty queue" q)
  • (cdr q)))
  • (define (insert-queue q elt)
  • (if (empty-queue? q)
  • (cons elt nil)
  • (cons (car q) (insert-queue (cdr q) elt))))

18
Complexity of the implementation
  • For a queue of length n
  • Time required -- number of cons, car, cdr calls?
  • Space required -- number of new cons cells?
  • front-queue, delete-queue
  • Time T(n) T(1) that is, constant in time
  • Space S(n) T(1) that is, constant in space
  • insert-queue
  • Time T(n) T (n) that is, linear in time
  • Space S(n) T(n) that is, linear in space

19
A more efficient implementation
  • In order to make both insert and delete efficient
  • we need constant time access to the front and the
    rear of the queue.
  • we can achieve this if we keep a pointer to the
    front and the rear of the queue.
  • A mutable implementation.

20
Mutable Queue Data Abstraction
  • constructor (make-queue) returns an empty
    queue
  • queries (selectors, assessors)
  • (front-queue q) returns the object at the
    front of the queue. If queue is empty
    signals error
  • (empty-queue? q) tests if the queue is empty
  • commands (mutators, transformers)
    (insert-queue! q elt) inserts the elt at the
    rear of the queue and returns ok
  • (delete-queue! q) removes the elt at the front
    of the queue and returns ok
  • additional query
  • (queue? q) tests if the object is a queue

21
Implementation
  • We attach a type tag as before.
  • Maintain queue identity
  • Build a structure to hold
  • a list of items in the queue
  • a pointer to the front of the queue
  • a pointer to the rear of the queue

22
Queue Helper Procedures
  • Hidden inside the abstraction
  • (define (front-ptr q) (cadr q))
  • (define (rear-ptr q) (cddr q))
  • (define (set-front-ptr! q item)
  • (set-car! (cdr q) item))
  • (define (set-rear-ptr! q item)
  • (set-cdr! (cdr q) item))

23
Queue implementation
  • (define (make-queue)
  • (cons 'queue (cons null null)))
  • (define (queue? q)
  • (and (pair? q) (eq? 'queue (car q))))
  • (define (empty-queue? q)
  • (if (not (queue? q))
  • (error "object not a queue" q)
  • (null? (front-ptr q))))
  • (define (front-queue q)
  • (if (empty-queue? q)
  • (error "front of empty queue" q)
  • (car (front-ptr q))))

24
Queue implementation Insert
  • (define (insert-queue! q elt)
  • (let ((new-pair (cons elt nil)))
  • (cond ((empty-queue? q)
  • (set-front-ptr! q new-pair)
  • (set-rear-ptr! q new-pair)
  • ok)
  • (else
  • (set-cdr! (rear-ptr q) new-pair)
  • (set-rear-ptr! q new-pair)
  • ok))))

25
Queue implementation - delete
  • (define (delete-queue! q)
  • (cond ((empty-queue? q)
  • (error "delete of empty queue" q))
  • (else
  • (set-front-ptr! q (cdr (front-ptr q)))
  • ok)))

26
Time and Space complexities ?
O(1)
27
Programming Styles Procedural vs.
Object-Oriented
  • Procedural programming - Organize system around
    procedures that operate on data
  • (do-something ltdatagt ltarggt ...)
  • (do-another-thing ltdatagt)
  • Object-based programming - Organize system
    around objects that receive messages
  • ((ltobjectgt 'do-something) ltarggt)
  • ((ltobjectgt 'do-another-thing) ... )
  • An object encapsulates data and operations
  • Message passing and returned procedures are
    the means to write object oriented code in scheme

28
Stacks in OO style
(define (make-stack) (let ((top-ptr '()))
(define (empty?) (null? top-ptr)) (define
(delete!) (if (null? top-ptr)
(error . . .) (set! top-ptr (cdr
top-ptr))) top-ptr ) (define (insert!
elmt) (set! top-ptr (cons elmt top-ptr))
top-ptr) (define (top) (if (null?
top-ptr) (error . . .) (car
top-ptr))) (define (dispatch op) (cond
((eq? op 'empty?) empty?) ((eq? op 'top)
top) ((eq? op 'insert!) insert!)
((eq? op 'delete!) delete!))) dispatch))
29
Stacks in OO style
(define s (make-stack)) ((s 'insert!) 'a)
gt ((s 'insert!) 'b) gt ((s 'top)) gt ((s
'delete!)) gt ((s 'top)) gt ((s 'delete!)) gt
(a)
(b a)
b
(a)
a
()
  • compare with message passing examples in OO we
    do not hide behind a functional layer eg.
  • (define (insert! s a) ((s insert!) a))
  • In OO programming languages the notation is eg.
  • s.insert(a)
  • s.delete()

30
Streams Motivation
(define (sum-primes a b) (define (iter count
accum) (cond ((gt count b) accum)
((prime? count) (iter ( count 1)
( count accum))) (else
(iter ( count 1) accum)))) (iter a 0))
(define (sum-primes a b) (accumulate
0 (filter prime?
(enumerate-interval a b))))
Second implementation consumes a lot of storage
31
Streams Motivation (Cont.)
(car (cdr (filter prime?
(enumerate-interval 10000 1000000))))
Requires a lot of time and space
How can we gain the efficiency of iteration, and
retain the elegance of sequence-operations?
Streams!
32
Remember normal order evaluation?
  • Normal (Lazy) Order Evaluation
  • go ahead and apply operator with unevaluated
    argument subexpressions
  • evaluate a subexpression only when value is
    needed
  • to print
  • by primitive procedure (that is, primitive
    procedures are "strict" in their arguments)
  • Compromise approach give programmer control
    between normal and applicative order.
  • Streams lists with delays

33
Streams interface
Constructors the-empty-stream (cons-stream x y)
Selectors (stream-car (cons-stream x y)) x
(stream-cdr (cons-stream x y)) y
Predicate (stream-null? x)
cons-stream treats its second argument as a
delayed object.
34
Streams via delay and force
(cons-stream ltagt ltbgt) is a special form
equivalent to (cons ltagt (delay ltbgt))
(define (stream-car stream) (car
stream)) (define (stream-cdr stream) (force (cdr
stream)))
35
delay and force
(delay ltexpgt) gt a promise to evaluate
exp (force ltdelayed objectgt) gt evaluate the
delayed object and return the result
(define x (delay ( 1 1))) x ? ltpromisegt (force
x) ? 2
(delay ltexpgt) is a special form. force is not a
special form.
36
What are these mysterious delay and force ?
delay is a special form such that (delay ltexpgt)
is equivalent to (lambda () ltexpgt) force is a
procedure that calls a procedure produced by
delay (define (force delayed-object)
(delayed-object))
37
Let us recall lists
(define (enumerate-interval low high) (if (gt
low high) () (cons low
(enumerate-interval ( low 1) high))))
(define int123 (enumerate-interval 1
3)) (enumerate-interval 1 3) (cons 1
(enumerate-interval 2 3)) (cons 1 (cons 2
(enumerate-interval 3 3))) (cons 1 (cons 2 (cons
3 (enumerate-interval 4 3))) (cons 1 (cons 2
(cons 3 ())))
38
Enumerating with streams
(define (stream-enumerate-interval low high)
(if (gt low high) the-empty-stream
(cons-stream low (stream-enumerate-i
nterval ( low 1) high))))
(define s (stream-enumerate-interval 1
3)) (stream-enumerate-interval 1 3) (cons-stream
1 (stream-enumerate-interval 2 3)) (cons 1 (delay
(stream-enumerate-interval 2 3))) (cons 1 (lambda
() (stream-enumerate-interval 2 3)))
39
(define s (stream-enumerate-interval 1 3)) GE

stream-enumerate-interval
GE
plow high b (if (gt low high) the-empty-stream (
cons-stream . . . )
(cons-stream 1 (str-enu-int ( low 1) high))
E1 (cons 1 (lambda () (str-enu-int ( low 1)
high)) E1
40
Calling stream-cdr
(define s1 (stream-cdr s)) (stream-cdr
s) (stream-cdr (cons 1 (lambda () (str-enu-int 2
3)))) (force (cdr (cons 1 (lambda () (str-enu-int
2 3))))) (force (lambda () (str-enu-int 2
3))) ((lambda () (str-enu-int 2 3))) (str-enu-int
2 3) (cons-stream 2 (str-enu-int 3 3)) (cons 2
(delay (str-enu-int 3 3))) (cons 2 (lambda ()
(str-enu-int 3 3)))
41
(define s1 (stream-cdr s)) GE(force (cdr s))
GE

str-enu-int
GE
s
E1
low 1
high 3
plow high b (if (gt low high) the-empty-stream (
cons-stream . . . )
1
p b(str-enu-int ( low 1) high)
42
stream-ref, stream-map
(define (stream-ref s n) (if ( n 0)
(stream-car s) (stream-ref (stream-cdr s)
(- n 1))))
(define (stream-map proc s) (if (stream-null?
s) the-empty-stream (cons-stream
(proc (stream-car s))
(stream-map proc (stream-cdr s)))) Also a version
with multiple stream arguments
43
Stream-filter
(define (stream-filter pred stream) (cond
((stream-null? stream) the-empty-stream)
((pred (stream-car stream)) (cons-stream
(stream-car stream)
(stream-filter pred
(stream-cdr stream)))) (else
(stream-filter pred (stream-cdr stream)))))
44
Applicative vs. Normal order evaluation.
(car (cdr (filter prime? (enu-int 10
1000000))))
(stream-car (stream-cdr (stream-filter
prime?(str-enu-int 10 1000000))))
  • Both return the second prime larger or equal to
    10 (which is 13)
  • With lists it takes about 1000000 operations
  • With streams about three.

45
How does it work? - I
(stream-car (stream-cdr (stream-filter
prime? (str-enu-int 10 1000))))
(stream-car (stream-cdr (stream-filter
prime? (cons 10 (delay (str-enu-int 11 1000))))))
(stream-car (stream-cdr (stream-filter
prime? (force (lambda () (str-enu-int 11
1000))))))
(stream-car (stream-cdr (stream-filter prime?
(cons 11 (delay (str-enu-int 12 1000))))))
46
How does it work? - II
(stream-car (stream-cdr (cons 11
(delay (stream-filter prime?
(stream-cdr (cons 11 (delay (str-enu-int 12
1000)))))))))
(stream-car (stream-filter prime?
(stream-cdr (cons 11 (delay (str-enu-int 12
1000))))))
(stream-car (stream-filter prime? (str-enu-int
12 1000)))
47
How does it work? - III
(stream-car (stream-filter prime? (cons 12
(delay (str-enu-int 13 1000)))))
(stream-car (stream-filter prime? (str-enu-int
13 1000)))
(stream-car (stream-filter prime? (cons
13 (delay (str-enu-int 14 1000)))))
(stream-car (cons 13 (delay (stream-filter
prime? (stream-cdr (cons 13 (delay
(str-enu-int 14 1000))))))))
13
48
Memoization
Suppose we have the following scenario (define
x (delay (very-hard-function a))) (force
x) (force x)
We need to call the hard function twice.
Scheme will automatically detect that this is the
second time we try to evaluate the function and
use the value we have evaluated before.
49
How is it done?
delay is actually defined as follows (delay
ltexpgt) translates to (memo-proc (lambda ()
ltexpgt)) (define (memo-proc proc) (let
((already-run? f) (result f))
(lambda () (if (not already-run?)
(begin (set! result (proc))
(set! already-run? true)
result) result))))
Write a Comment
User Comments (0)
About PowerShow.com