Abstract Data Types EECS 214, Fall 2017 What is an ADT? An ADT - - PowerPoint PPT Presentation

abstract data types
SMART_READER_LITE
LIVE PREVIEW

Abstract Data Types EECS 214, Fall 2017 What is an ADT? An ADT - - PowerPoint PPT Presentation

Abstract Data Types EECS 214, Fall 2017 What is an ADT? An ADT defjnes: An ADT omits: How the values are concretely represented How the operations work 2 A set of (abstract) values A set of (abstract) operations on those values What


slide-1
SLIDE 1

Abstract Data Types

EECS 214, Fall 2017

slide-2
SLIDE 2

What is an ADT?

An ADT defjnes:

  • A set of (abstract) values
  • A set of (abstract) operations on those values

An ADT omits: How the values are concretely represented How the operations work

2

slide-3
SLIDE 3

What is an ADT?

An ADT defjnes:

  • A set of (abstract) values
  • A set of (abstract) operations on those values

An ADT omits:

  • How the values are concretely represented
  • How the operations work

2

slide-4
SLIDE 4

ADT: Stack

Looks like: |3 4 5 Signature: push(Stack, Element): Void pop(Stack): Element isEmpty(Stack): Bool

3

slide-5
SLIDE 5

ADT: Stack

Looks like: |3 4 5 Signature:

  • push(Stack, Element): Void
  • pop(Stack): Element
  • isEmpty(Stack): Bool

3

slide-6
SLIDE 6

ADT: Queue (FIFO)

Looks like: 3 4 5 Signature: enqueue(Queue, Element): Void dequeue(Queue): Element isEmpty(Queue): Bool

4

slide-7
SLIDE 7

ADT: Queue (FIFO)

Looks like: 3 4 5 Signature:

  • enqueue(Queue, Element): Void
  • dequeue(Queue): Element
  • isEmpty(Queue): Bool

4

slide-8
SLIDE 8

Stack versus Queue

Stack signature:

  • push(Stack, Element): Void
  • pop(Stack): Element
  • isEmpty(Stack): Bool

Queue signature:

  • enqueue(Queue, Element): Void
  • dequeue(Queue): Element
  • isEmpty(Queue): Bool

5

slide-9
SLIDE 9

Adding laws

{p} f(x) ⇒ y {q} means that if precondition p is true when we apply f to x then we will get y as a result, and postcondition q will be true afterward. Examples: a a a a a a

6

slide-10
SLIDE 10

Adding laws

{p} f(x) ⇒ y {q} means that if precondition p is true when we apply f to x then we will get y as a result, and postcondition q will be true afterward. Examples: {a = [2, 4, 6, 8]} a[2] ⇒ 6 {a = [2, 4, 6, 8]} {a = [2, 4, 6, 8]} a[2] = 0 {a = [2, 4, 0, 8]}

6

slide-11
SLIDE 11

ADT: Stack

Looks like: |3 4 5 Signature:

  • push(Stack, Element): Void
  • pop(Stack): Element
  • isEmpty(Stack): Bool

Laws: isEmpty(|) ⇒ ⊤ isEmpty(|e1 . . . ekek+1) ⇒ ⊥ {s = |e1 . . . ek} push(s, e) {s = |e1 . . . eke} {s = |e1 . . . ekek+1} pop(s) ⇒ ek+1 {s = |e1 . . . ek}

7

slide-12
SLIDE 12

ADT: Queue (FIFO)

Looks like: 3 4 5 Signature:

  • enqueue(Queue, Element): Void
  • dequeue(Queue): Element
  • isEmpty(Queue): Bool

Laws: isEmpty() ⇒ ⊤ isEmpty(e1 . . . ekek+1) ⇒ ⊥ {q = e1 . . . ek} enqueue(q, e) {q = e1 . . . eke} {q = e1e2 . . . ek} dequeue(q) ⇒ e1 {q = e2 . . . ek}

8

slide-13
SLIDE 13

Stack implementation: linked list

data 2 next head data 3 next data 4 next data 5 next

let s = new_stack() push(s, 2) push(s, 3) push(s, 4) push(s, 5) pop(s) pop(s)

9

slide-14
SLIDE 14

Stack implementation: linked list

data 2 next head data 3 next data 4 next data 5 next

let s = new_stack() push(s, 2) push(s, 3) push(s, 4) push(s, 5) pop(s) pop(s)

9

slide-15
SLIDE 15

Stack implementation: linked list

data 2 next head data 3 next data 4 next data 5 next

let s = new_stack() push(s, 2) push(s, 3) push(s, 4) push(s, 5) pop(s) pop(s)

9

slide-16
SLIDE 16

Stack implementation: linked list

data 2 next head data 3 next data 4 next data 5 next

let s = new_stack() push(s, 2) push(s, 3) push(s, 4) push(s, 5) pop(s) pop(s)

9

slide-17
SLIDE 17

Stack implementation: linked list

data 2 next head data 3 next data 4 next data 5 next

let s = new_stack() push(s, 2) push(s, 3) push(s, 4) push(s, 5) pop(s) pop(s)

9

slide-18
SLIDE 18

Stack implementation: linked list

data 2 next head data 3 next data 4 next data 5 next

let s = new_stack() push(s, 2) push(s, 3) push(s, 4) push(s, 5) pop(s) pop(s)

9

slide-19
SLIDE 19

Stack implementation: linked list

data 2 next head data 3 next data 4 next data 5 next

let s = new_stack() push(s, 2) push(s, 3) push(s, 4) push(s, 5) pop(s) pop(s)

9

slide-20
SLIDE 20

Stack implementation: array

data len 0

let s = new_stack() 2 push(s, 2) 2 3 push(s, 3) 2 3 4 push(s, 4) 2 3 4 5 push(s, 5) push(s, 6)

10

slide-21
SLIDE 21

Stack implementation: array

data len 1

let s = new_stack() 2 push(s, 2) 2 3 push(s, 3) 2 3 4 push(s, 4) 2 3 4 5 push(s, 5) push(s, 6)

10

slide-22
SLIDE 22

Stack implementation: array

data len 2

let s = new_stack() 2 push(s, 2) 2 3 push(s, 3) 2 3 4 push(s, 4) 2 3 4 5 push(s, 5) push(s, 6)

10

slide-23
SLIDE 23

Stack implementation: array

data len 3

let s = new_stack() 2 push(s, 2) 2 3 push(s, 3) 2 3 4 push(s, 4) 2 3 4 5 push(s, 5) push(s, 6)

10

slide-24
SLIDE 24

Stack implementation: array

data len 4

let s = new_stack() 2 push(s, 2) 2 3 push(s, 3) 2 3 4 push(s, 4) 2 3 4 5 push(s, 5) push(s, 6)

10

slide-25
SLIDE 25

Stack implementation: array

data len 4

let s = new_stack() 2 push(s, 2) 2 3 push(s, 3) 2 3 4 push(s, 4) 2 3 4 5 push(s, 5) push(s, 6)

10

slide-26
SLIDE 26

ADT: Stack

Looks like: |3 4 5 Signature:

  • push(Stack, Element): Void — O(1)
  • pop(Stack): Element — O(1)
  • isEmpty(Stack): Bool — O(1)

Laws: isEmpty(|) ⇒ ⊤ isEmpty(|e1 . . . ekek+1) ⇒ ⊥ {s = |e1 . . . ek} push(s, e) {s = |e1 . . . eke} {s = |e1 . . . ekek+1} pop(s) ⇒ ek+1 {s = |e1 . . . ek}

11

slide-27
SLIDE 27

Trade-ofgs: linked list stack versus array stack

  • Linked list stack only fjlls up when memory fjlls up,

whereas array stack has a fjxed size (or must reallocate)

  • Array stack has better constant factors: cache locality and

no (or rare) allocation

  • Array stack space usage is tighter; linked list is smoother

12

slide-28
SLIDE 28

ADT: Queue (FIFO)

Looks like: 3 4 5 Signature:

  • enqueue(Queue, Element): Void — O(1)
  • dequeue(Queue): Element — O(1)
  • isEmpty(Queue): Bool — O(1)

Laws: isEmpty() ⇒ ⊤ isEmpty(e1 . . . ekek+1) ⇒ ⊥ {q = e1 . . . ek} enqueue(q, e) {q = e1 . . . eke} {q = e1e2 . . . ek} dequeue(q) ⇒ e1 {q = e2 . . . ek}

13

slide-29
SLIDE 29

Queue implementation: linked list?

head data 2 next data 3 next data 4 next data 5 next

let q = new_queue() enqueue(q, 2) enqueue(q, 3) enqueue(q, 4) enqueue(q, 5) dequeue(q) — n ?

14

slide-30
SLIDE 30

Queue implementation: linked list?

head data 2 next data 3 next data 4 next data 5 next

let q = new_queue() enqueue(q, 2) enqueue(q, 3) enqueue(q, 4) enqueue(q, 5) dequeue(q) — n ?

14

slide-31
SLIDE 31

Queue implementation: linked list?

head data 2 next data 3 next data 4 next data 5 next

let q = new_queue() enqueue(q, 2) enqueue(q, 3) enqueue(q, 4) enqueue(q, 5) dequeue(q) — n ?

14

slide-32
SLIDE 32

Queue implementation: linked list?

head data 2 next data 3 next data 4 next data 5 next

let q = new_queue() enqueue(q, 2) enqueue(q, 3) enqueue(q, 4) enqueue(q, 5) dequeue(q) — n ?

14

slide-33
SLIDE 33

Queue implementation: linked list?

head data 2 next data 3 next data 4 next data 5 next

let q = new_queue() enqueue(q, 2) enqueue(q, 3) enqueue(q, 4) enqueue(q, 5) dequeue(q) — n ?

14

slide-34
SLIDE 34

Queue implementation: linked list?

head data 2 next data 3 next data 4 next data 5 next

let q = new_queue() enqueue(q, 2) enqueue(q, 3) enqueue(q, 4) enqueue(q, 5) dequeue(q) — n ?

14

slide-35
SLIDE 35

Queue implementation: linked list?

head data 2 next data 3 next data 4 next data 5 next

let q = new_queue() enqueue(q, 2) enqueue(q, 3) enqueue(q, 4) enqueue(q, 5) dequeue(q) — O(n)?

14

slide-36
SLIDE 36

Queue implementation: array?

data len 0

let q = new_queue() 2 enqueue(q, 2) 2 3 enqueue(q, 3) 2 3 4 enqueue(q, 4) 2 3 4 5 enqueue(q, 5) 3 4 5 s.dequeue() — n ???

15

slide-37
SLIDE 37

Queue implementation: array?

data len 1

let q = new_queue() 2 enqueue(q, 2) 2 3 enqueue(q, 3) 2 3 4 enqueue(q, 4) 2 3 4 5 enqueue(q, 5) 3 4 5 s.dequeue() — n ???

15

slide-38
SLIDE 38

Queue implementation: array?

data len 2

let q = new_queue() 2 enqueue(q, 2) 2 3 enqueue(q, 3) 2 3 4 enqueue(q, 4) 2 3 4 5 enqueue(q, 5) 3 4 5 s.dequeue() — n ???

15

slide-39
SLIDE 39

Queue implementation: array?

data len 3

let q = new_queue() 2 enqueue(q, 2) 2 3 enqueue(q, 3) 2 3 4 enqueue(q, 4) 2 3 4 5 enqueue(q, 5) 3 4 5 s.dequeue() — n ???

15

slide-40
SLIDE 40

Queue implementation: array?

data len 4

let q = new_queue() 2 enqueue(q, 2) 2 3 enqueue(q, 3) 2 3 4 enqueue(q, 4) 2 3 4 5 enqueue(q, 5) 3 4 5 s.dequeue() — n ???

15

slide-41
SLIDE 41

Queue implementation: array?

data len 4

let q = new_queue() 2 enqueue(q, 2) 2 3 enqueue(q, 3) 2 3 4 enqueue(q, 4) 2 3 4 5 enqueue(q, 5) 3 4 5 s.dequeue() — n ???

15

slide-42
SLIDE 42

Queue implementation: array?

data len 4

let q = new_queue() 2 enqueue(q, 2) 2 3 enqueue(q, 3) 2 3 4 enqueue(q, 4) 2 3 4 5 enqueue(q, 5) 3 4 5 s.dequeue() — O(n)???

15

slide-43
SLIDE 43

Queue impl.: linked list with tail pointer

head tail data 5 next data 4 next data 3 next data 2 next

let q = new_queue() enqueue(q, 2) enqueue(q, 3) enqueue(q, 4) enqueue(q, 5) dequeue(q) dequeue(q)

16

slide-44
SLIDE 44

Queue impl.: linked list with tail pointer

head tail data 5 next data 4 next data 3 next data 2 next

let q = new_queue() enqueue(q, 2) enqueue(q, 3) enqueue(q, 4) enqueue(q, 5) dequeue(q) dequeue(q)

16

slide-45
SLIDE 45

Queue impl.: linked list with tail pointer

head tail data 5 next data 4 next data 3 next data 2 next

let q = new_queue() enqueue(q, 2) enqueue(q, 3) enqueue(q, 4) enqueue(q, 5) dequeue(q) dequeue(q)

16

slide-46
SLIDE 46

Queue impl.: linked list with tail pointer

head tail data 5 next data 4 next data 3 next data 2 next

let q = new_queue() enqueue(q, 2) enqueue(q, 3) enqueue(q, 4) enqueue(q, 5) dequeue(q) dequeue(q)

16

slide-47
SLIDE 47

Queue impl.: linked list with tail pointer

head tail data 5 next data 4 next data 3 next data 2 next

let q = new_queue() enqueue(q, 2) enqueue(q, 3) enqueue(q, 4) enqueue(q, 5) dequeue(q) dequeue(q)

16

slide-48
SLIDE 48

Queue impl.: linked list with tail pointer

head tail data 5 next data 4 next data 3 next data 2 next

let q = new_queue() enqueue(q, 2) enqueue(q, 3) enqueue(q, 4) enqueue(q, 5) dequeue(q) dequeue(q)

16

slide-49
SLIDE 49

Queue impl.: linked list with tail pointer

head tail data 5 next data 4 next data 3 next data 2 next

let q = new_queue() enqueue(q, 2) enqueue(q, 3) enqueue(q, 4) enqueue(q, 5) dequeue(q) dequeue(q)

16

slide-50
SLIDE 50

Queue implementation: ring bufger

data start 0 len 0

let q = new_queue() 2 enqueue(q, 2) 2 3 enqueue(q, 3) 2 3 4 enqueue(q, 4) 2 3 4 5 enqueue(q, 5) 3 4 5 dequeue(q) 4 5 dequeue(q) 4 5 6 7 8 9 . . . 4 5 6 7 8 9 enqueue(q, 0) 5 6 7 8 9 dequeue(q)

17

slide-51
SLIDE 51

Queue implementation: ring bufger

data start 0 len 1

let q = new_queue() 2 enqueue(q, 2) 2 3 enqueue(q, 3) 2 3 4 enqueue(q, 4) 2 3 4 5 enqueue(q, 5) 3 4 5 dequeue(q) 4 5 dequeue(q) 4 5 6 7 8 9 . . . 4 5 6 7 8 9 enqueue(q, 0) 5 6 7 8 9 dequeue(q)

17

slide-52
SLIDE 52

Queue implementation: ring bufger

data start 0 len 2

let q = new_queue() 2 enqueue(q, 2) 2 3 enqueue(q, 3) 2 3 4 enqueue(q, 4) 2 3 4 5 enqueue(q, 5) 3 4 5 dequeue(q) 4 5 dequeue(q) 4 5 6 7 8 9 . . . 4 5 6 7 8 9 enqueue(q, 0) 5 6 7 8 9 dequeue(q)

17

slide-53
SLIDE 53

Queue implementation: ring bufger

data start 0 len 3

let q = new_queue() 2 enqueue(q, 2) 2 3 enqueue(q, 3) 2 3 4 enqueue(q, 4) 2 3 4 5 enqueue(q, 5) 3 4 5 dequeue(q) 4 5 dequeue(q) 4 5 6 7 8 9 . . . 4 5 6 7 8 9 enqueue(q, 0) 5 6 7 8 9 dequeue(q)

17

slide-54
SLIDE 54

Queue implementation: ring bufger

data start 0 len 4

let q = new_queue() 2 enqueue(q, 2) 2 3 enqueue(q, 3) 2 3 4 enqueue(q, 4) 2 3 4 5 enqueue(q, 5) 3 4 5 dequeue(q) 4 5 dequeue(q) 4 5 6 7 8 9 . . . 4 5 6 7 8 9 enqueue(q, 0) 5 6 7 8 9 dequeue(q)

17

slide-55
SLIDE 55

Queue implementation: ring bufger

data start 1 len 3

let q = new_queue() 2 enqueue(q, 2) 2 3 enqueue(q, 3) 2 3 4 enqueue(q, 4) 2 3 4 5 enqueue(q, 5) 3 4 5 dequeue(q) 4 5 dequeue(q) 4 5 6 7 8 9 . . . 4 5 6 7 8 9 enqueue(q, 0) 5 6 7 8 9 dequeue(q)

17

slide-56
SLIDE 56

Queue implementation: ring bufger

data start 2 len 2

let q = new_queue() 2 enqueue(q, 2) 2 3 enqueue(q, 3) 2 3 4 enqueue(q, 4) 2 3 4 5 enqueue(q, 5) 3 4 5 dequeue(q) 4 5 dequeue(q) 4 5 6 7 8 9 . . . 4 5 6 7 8 9 enqueue(q, 0) 5 6 7 8 9 dequeue(q)

17

slide-57
SLIDE 57

Queue implementation: ring bufger

data start 2 len 6

let q = new_queue() 2 enqueue(q, 2) 2 3 enqueue(q, 3) 2 3 4 enqueue(q, 4) 2 3 4 5 enqueue(q, 5) 3 4 5 dequeue(q) 4 5 dequeue(q) 4 5 6 7 8 9 . . . 4 5 6 7 8 9 enqueue(q, 0) 5 6 7 8 9 dequeue(q)

17

slide-58
SLIDE 58

Queue implementation: ring bufger

data start 2 len 7

let q = new_queue() 2 enqueue(q, 2) 2 3 enqueue(q, 3) 2 3 4 enqueue(q, 4) 2 3 4 5 enqueue(q, 5) 3 4 5 dequeue(q) 4 5 dequeue(q) 4 5 6 7 8 9 . . . 4 5 6 7 8 9 enqueue(q, 0) 5 6 7 8 9 dequeue(q)

17

slide-59
SLIDE 59

Queue implementation: ring bufger

data start 3 len 6

let q = new_queue() 2 enqueue(q, 2) 2 3 enqueue(q, 3) 2 3 4 enqueue(q, 4) 2 3 4 5 enqueue(q, 5) 3 4 5 dequeue(q) 4 5 dequeue(q) 4 5 6 7 8 9 . . . 4 5 6 7 8 9 enqueue(q, 0) 5 6 7 8 9 dequeue(q)

17

slide-60
SLIDE 60

Trade-ofgs: linked list queue versus ring bufger

Basically the same as for the stack implementations:

  • Ring bufger has better constant factors and uses less

space (potentially)

  • Linked list doesn’t fjll up

18

slide-61
SLIDE 61

Ring bufger in DSSL2

slide-62
SLIDE 62

Representation

# A QueueOf[X] is # queue(VectorOf[X or False], Natural, Natural) # Interpretation: # - `data` contains the elements of the queue, # - `start` is the index of the first element, and # - `size` is the number of elements. defstruct queue(data, start, size) let F = False let QUEUE0 = queue([F; 8], 0, 0)) let QUEUE1 = queue([3, F, F, F, F, F], 0, 1) let QUEUE2 = queue([3, 4, F, F, F, F], 0, 2) let QUEUE3 = queue([F, F, 5, 6, 7, F], 2, 3) let QUEUE4 = queue([9, 10, F, F, 7, 8], 4, 4)

20

slide-63
SLIDE 63

Representation

# A QueueOf[X] is # queue(VectorOf[X or False], Natural, Natural) # Interpretation: # - `data` contains the elements of the queue, # - `start` is the index of the first element, and # - `size` is the number of elements. defstruct queue(data, start, size) let F = False let QUEUE0 = queue([F; 8], 0, 0)) let QUEUE1 = queue([3, F, F, F, F, F], 0, 1) let QUEUE2 = queue([3, 4, F, F, F, F], 0, 2) let QUEUE3 = queue([F, F, 5, 6, 7, F], 2, 3) let QUEUE4 = queue([9, 10, F, F, 7, 8], 4, 4)

20

slide-64
SLIDE 64

Creating a new queue

# new_queue : Natural -> QueueOf[X] def new_queue(capacity): queue([ False; capacity ], 0, 0)

21

slide-65
SLIDE 65

Finding out the size and capacity

# queue_size : QueueOf[X] -> Natural def queue_size(q): q.size # queue_capacity : QueueOf[X] -> Natural def queue_capacity(q): len(q.data) # queue_empty? : QueueOf[X] -> Bool def queue_empty?(q): queue_size(q) == 0 # queue_full? : QueueOf[X] -> Bool def queue_full?(q): queue_size(q) == queue_capacity(q)

22

slide-66
SLIDE 66

Finding out the size and capacity

# queue_size : QueueOf[X] -> Natural def queue_size(q): q.size # queue_capacity : QueueOf[X] -> Natural def queue_capacity(q): len(q.data) # queue_empty? : QueueOf[X] -> Bool def queue_empty?(q): queue_size(q) == 0 # queue_full? : QueueOf[X] -> Bool def queue_full?(q): queue_size(q) == queue_capacity(q)

22

slide-67
SLIDE 67

Enqueueing

# enqueue! : QueueOf[X] X -> Void def enqueue!(q, element): if queue_full?(q): error('enqueue!: queue is full') let cap = queue_capacity(q) q.data[(q.size + q.start) % cap] = element q.size = q.size + 1

23

slide-68
SLIDE 68

Dequeueing

# dequeue! : QueueOf[X] -> X def dequeue!(q): if queue_empty?(q): error('dequeue!: queue is empty') let result = q.data[q.start] q.data[q.start] = False q.size = q.size - 1 q.start = (q.start + 1) % queue_capacity(q) result

24

slide-69
SLIDE 69

Next time: BSTs and the Dictionary ADT