1 of 40

Discussion 4:

Trees & Mutability

CS 61A Summer 2019

DISC 104

2 of 40

Announcements

  • Midterm and Final will be held 6-9 PM PDT
  • Code Debugging
    • Please use Office Hours/Piazza first
    • If you're unable to find the help you need, then please send me an email/ask me in person

3 of 40

Deadlines

  • Typing-test
    • Phase 1/2 Due 7/12 @11:59PM
    • Phase 3 Due 7/23 @11:59PM
  • HW 3 Due 7/16 @11:59PM
  • Lab 4/5 Due 7/12 @11:59PM

4 of 40

Agenda

  • Trees
  • Mutability

5 of 40

Trees

6 of 40

Intro

Tree is a data structure

For now, we'll implement them using an ADT

7 of 40

Definitions

8 of 40

1

2

3

4

5

6

9 of 40

1

2

3

4

5

6

Nodes

10 of 40

1

2

3

4

5

6

Labels

11 of 40

1

2

3

4

5

6

Parent

Node

Child

Nodes

12 of 40

1

2

3

4

5

6

Parent

Node

Child

Nodes

13 of 40

1

2

3

4

5

6

Root

Branch

Branch

14 of 40

1

2

3

4

5

6

Root

Branch

Branch

Leaf

15 of 40

Depth = 2

Depth = 1

Depth = 0

1

2

3

4

5

6

Height = 2

16 of 40

ADT Tree

17 of 40

Constructor

def tree(label, branches=[]):

for branch in branches:

assert is_tree(branches)

return [label] + list(branches)

18 of 40

Selectors

def label(tree):

return tree[0]

def branches(tree):

return tree[1:]

#For convenience

def is_leaf(tree):

return not branches(tree)

19 of 40

Defining a tree

1

2

3

4

5

20 of 40

Defining a tree

1

2

3

4

5

t = tree(1, [

tree(2, [

tree(4),

tree(5)]),

tree(3)])

t = tree(1, [tree(2, [tree(4), tree(5)]), tree(3)])

21 of 40

Sanity Check

For each question, what is the result? Does it violate the abstraction barrier?

  • label(t)

  • t[0]

  • label(branches(t)[0])

  • is_leaf(t[1:][1])

  • [label(b) for b in branches(t)]

t = tree(1, [tree(2, [tree(4), tree(5)]), tree(3)])

22 of 40

Sanity Check

For each question, what is the result? Does it violate the abstraction barrier?

  • label(t)

1

  • t[0]

  • label(branches(t)[0])

  • is_leaf(t[1:][1])

  • [label(b) for b in branches(t)]

t = tree(1, [tree(2, [tree(4), tree(5)]), tree(3)])

23 of 40

Sanity Check

For each question, what is the result? Does it violate the abstraction barrier?

  • label(t)

1

  • T[0] #violation

1

  • label(branches(t)[0])

  • is_leaf(t[1:][1])

  • [label(b) for b in branches(t)]

t = tree(1, [tree(2, [tree(4), tree(5)]), tree(3)])

24 of 40

Sanity Check

For each question, what is the result? Does it violate the abstraction barrier?

  • label(t)

1

  • T[0] #violation

1

  • label(branches(t)[0])

2

  • is_leaf(t[1:][1])

  • [label(b) for b in branches(t)]

t = tree(1, [tree(2, [tree(4), tree(5)]), tree(3)])

25 of 40

Sanity Check

For each question, what is the result? Does it violate the abstraction barrier?

  • label(t)

1

  • T[0] #violation

1

  • label(branches(t)[0])

2

  • is_leaf(t[1:][1]) #violation

True

  • [label(b) for b in branches(t)]

t = tree(1, [tree(2, [tree(4), tree(5)]), tree(3)])

26 of 40

Sanity Check

For each question, what is the result? Does it violate the abstraction barrier?

  • label(t)

1

  • T[0] #violation

1

  • label(branches(t)[0])

2

  • is_leaf(t[1:][1]) #violation

True

  • [label(b) for b in branches(t)]

[2, 3]

t = tree(1, [tree(2, [tree(4), tree(5)]), tree(3)])

27 of 40

Box and Pointer Diagrams

28 of 40

Example

lst = [1, 2, [3, 4]]

1

2

3

4

lst

29 of 40

Mutation

30 of 40

Definition

We say that some objects are mutable if their contents or state can be changed over the course of program execution

>>> lst = [1, 2, 3, 4]

>>> lst[0]

1

>>> lst[0] = 3

>>> lst[0]

3

31 of 40

Examples

Mutable

Immutable

Lists

Dictionaries

Integers

Strings

Tuples

Tree ADT

32 of 40

Mutating Lists

33 of 40

.append(el)

Adds exactly one extra element to the list; uses pointer (b&pd) if the input doesn’t fit

>>> lst = [0]

>>> lst.append(1)

>>> lst

[0, 1]

>>> lst.append([2, 3])

>>> lst

[0, 1, [2, 3]]

34 of 40

.extend(seq)

Puts all elements from the sequence and adds it directly to the end of the original list

*takes in a sequence as an argument*

>>> lst = [1]

>>> lst.extend([2, 3, 4, 5])

>>> lst

[1, 2, 3, 4, 5]

35 of 40

Valid?

>>> lst = [1, 2]

>>> lst.append(3, 4)

>>> lst = [1, 2]

>>> lst.extend(3)

>>> lst = [1, 2]

>>> lst.append([3, 4])

36 of 40

Valid?

>>> lst = [1, 2]

>>> lst.append(3, 4)

>>> lst = [1, 2]

>>> lst.extend(3)

>>> lst = [1, 2]

>>> lst.append([3, 4])

37 of 40

Valid?

>>> lst = [1, 2]

>>> lst.append(3, 4)

>>> lst = [1, 2]

>>> lst.extend(3)

>>> lst = [1, 2]

>>> lst.append([3, 4])

38 of 40

Valid?

>>> lst = [1, 2]

>>> lst.append(3, 4)

>>> lst = [1, 2]

>>> lst.extend(3)

>>> lst = [1, 2]

>>> lst.append([3, 4])

39 of 40

A note on

+= and =+

"+=" and extend are the same thing (in terms of lists)

lst.extend([2, 3])

lst += [2, 3]

"=+" and extend ARE NOT the same thing (in terms of lists)

lst.extend([2, 3])

lst = lst + [2, 3]

40 of 40

Other useful mutation functions

.insert(i, elem)

  • inserts "elem" in index i

.remove(elem)

  • removes the first occurence of "elem" in list, otherwise errors

.pop(i)

  • Removes and returns the element at index i (if no index provided, pop the last element)