Top Banner
Improving Pseudo-Code CS16: Introduction to Data Structures & Algorithms Spring 2020
42

Improving Pseudo-Codecs.brown.edu/courses/cs016/static/files/lectures/... · Lowest Common Ancestor ‣ Given two nodes u and v ‣ determine deepest node that is ancestor of both

Aug 22, 2020

Download

Documents

dariahiddleston
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: Improving Pseudo-Codecs.brown.edu/courses/cs016/static/files/lectures/... · Lowest Common Ancestor ‣ Given two nodes u and v ‣ determine deepest node that is ancestor of both

Improving Pseudo-CodeCS16: Introduction to Data Structures & Algorithms

Spring 2020

Page 2: Improving Pseudo-Codecs.brown.edu/courses/cs016/static/files/lectures/... · Lowest Common Ancestor ‣ Given two nodes u and v ‣ determine deepest node that is ancestor of both

CleanYour Code!‣ Errors per line is approximately constant‣ fewer lines → fewer errors overall

‣ Fewer lines are easier to grade‣ more likely to receive credit

‣ Clean code reflects clean thinking‣ and a better understanding of material

‣ Let’s see some examples

2

Page 3: Improving Pseudo-Codecs.brown.edu/courses/cs016/static/files/lectures/... · Lowest Common Ancestor ‣ Given two nodes u and v ‣ determine deepest node that is ancestor of both

Lowest Common Ancestor‣ Given two nodes u and v ‣ determine deepest node that is ancestor of both

3

A

B DC

G HE F

I J K

u v LCA(u, v)

C D A

J E B

G J A

G C C

3

Page 4: Improving Pseudo-Codecs.brown.edu/courses/cs016/static/files/lectures/... · Lowest Common Ancestor ‣ Given two nodes u and v ‣ determine deepest node that is ancestor of both

Lowest Common Ancestor

43 minActivity #1

Page 5: Improving Pseudo-Codecs.brown.edu/courses/cs016/static/files/lectures/... · Lowest Common Ancestor ‣ Given two nodes u and v ‣ determine deepest node that is ancestor of both

Lowest Common Ancestor

53 minActivity #1

Page 6: Improving Pseudo-Codecs.brown.edu/courses/cs016/static/files/lectures/... · Lowest Common Ancestor ‣ Given two nodes u and v ‣ determine deepest node that is ancestor of both

Lowest Common Ancestor

62 minActivity #1

Page 7: Improving Pseudo-Codecs.brown.edu/courses/cs016/static/files/lectures/... · Lowest Common Ancestor ‣ Given two nodes u and v ‣ determine deepest node that is ancestor of both

Lowest Common Ancestor

71 minActivity #1

Page 8: Improving Pseudo-Codecs.brown.edu/courses/cs016/static/files/lectures/... · Lowest Common Ancestor ‣ Given two nodes u and v ‣ determine deepest node that is ancestor of both

Lowest Common Ancestor

80 minActivity #1

Page 9: Improving Pseudo-Codecs.brown.edu/courses/cs016/static/files/lectures/... · Lowest Common Ancestor ‣ Given two nodes u and v ‣ determine deepest node that is ancestor of both

Ways to Improve Pseudo-Code‣ Clarify inputs and outputs with comments‣ good habit and makes methods easier to understand

‣ Make sure all necessary arguments are included as parameters

9

Page 10: Improving Pseudo-Codecs.brown.edu/courses/cs016/static/files/lectures/... · Lowest Common Ancestor ‣ Given two nodes u and v ‣ determine deepest node that is ancestor of both

Lowest Common Ancestor

10

function LCA(u, v):

lca = nulludepth = T.depth(u)vdepth = T.depth(v)if (T.isroot(u) == true) or (T.isroot(v) == true) then

lca = T.rootwhile (lca == null) do

if (u == v) thenlca = u

else if udepth > vdepth then u = T.parent(u)udepth = udepth – 1

else if vdepth > udepthv = T.parent(v)vdepth = vdepth – 1

elseu = T.parent(u); udepth = udepth - 1v = T.parent(v); vdepth = vdepth – 1

return lca

Inputs & outputs ?

Page 11: Improving Pseudo-Codecs.brown.edu/courses/cs016/static/files/lectures/... · Lowest Common Ancestor ‣ Given two nodes u and v ‣ determine deepest node that is ancestor of both

Lowest Common Ancestor

11

function LCA(u, v):// Input: two nodes u, v// Output: the lowest common ancestor of u and vlca = nulludepth = T.depth(u)vdepth = T.depth(v)if (T.isroot(u) == true) or (T.isroot(v) == true) then

lca = T.rootwhile (lca == null) do

if (u == v) thenlca = u

else if udepth > vdepth then u = T.parent(u)udepth = udepth – 1

else if vdepth > udepthv = T.parent(v)vdepth = vdepth – 1

elseu = T.parent(u); udepth = udepth - 1v = T.parent(v); vdepth = vdepth – 1

return lca

Page 12: Improving Pseudo-Codecs.brown.edu/courses/cs016/static/files/lectures/... · Lowest Common Ancestor ‣ Given two nodes u and v ‣ determine deepest node that is ancestor of both

Lowest Common Ancestor

12

function LCA(u, v):// Input: two nodes u, v// Output: the lowest common ancestor of u and vlca = nulludepth = T.depth(u)vdepth = T.depth(v)if (T.isroot(u) == true) or (T.isroot(v) == true) then

lca = T.rootwhile (lca == null) do

if (u == v) thenlca = u

else if udepth > vdepth then u = T.parent(u)udepth = udepth – 1

else if vdepth > udepthv = T.parent(v)vdepth = vdepth – 1

elseu = T.parent(u); udepth = udepth - 1v = T.parent(v); vdepth = vdepth – 1

return lca

Where does T come from?

Page 13: Improving Pseudo-Codecs.brown.edu/courses/cs016/static/files/lectures/... · Lowest Common Ancestor ‣ Given two nodes u and v ‣ determine deepest node that is ancestor of both

Lowest Common Ancestor

13

function LCA(u, v, T):// Input: two nodes u, v in a tree T// Output: the lowest common ancestor of u and vlca = nulludepth = T.depth(u)vdepth = T.depth(v)if (T.isroot(u) == true) or (T.isroot(v) == true) then

lca = T.rootwhile (lca == null) do

if (u == v) thenlca = u

else if udepth > vdepth then u = T.parent(u)udepth = udepth – 1

else if vdepth > udepthv = T.parent(v)vdepth = vdepth – 1

elseu = T.parent(u); udepth = udepth - 1v = T.parent(v); vdepth = vdepth – 1

return lca

Page 14: Improving Pseudo-Codecs.brown.edu/courses/cs016/static/files/lectures/... · Lowest Common Ancestor ‣ Given two nodes u and v ‣ determine deepest node that is ancestor of both

Ways to Improve Pseudo-Code‣ Get rid of unnecessary variables‣ Using vars for information that is elsewhere…‣ …leads to careless errors

‣ In example, no need for udepth and vdepth ‣ since Tree keeps track of node’s depth

14

Page 15: Improving Pseudo-Codecs.brown.edu/courses/cs016/static/files/lectures/... · Lowest Common Ancestor ‣ Given two nodes u and v ‣ determine deepest node that is ancestor of both

Lowest Common Ancestor

15

function LCA(u, v, T):// Input: two nodes u, v in a tree T// Output: the lowest common ancestor of u and vlca = nulludepth = T.depth(u)vdepth = T.depth(v)if (T.isroot(u) == true) or (T.isroot(v) == true) then

lca = T.rootwhile (lca == null) do

if (u == v) thenlca = u

else if udepth > vdepth then u = T.parent(u)udepth = udepth – 1

else if vdepth > udepthv = T.parent(v)vdepth = vdepth – 1

elseu = T.parent(u); udepth = udepth - 1v = T.parent(v); vdepth = vdepth – 1

return lca

〉 Needlessly complex

Page 16: Improving Pseudo-Codecs.brown.edu/courses/cs016/static/files/lectures/... · Lowest Common Ancestor ‣ Given two nodes u and v ‣ determine deepest node that is ancestor of both

Lowest Common Ancestor

16

function LCA(u, v, T):// Input: two nodes u, v in a tree T// Output: the lowest common ancestor of u and vlca = nulludepth = T.depth(u)vdepth = T.depth(v)if (T.isroot(u) == true) or (T.isroot(v) == true) then

lca = T.rootwhile (lca == null) do

if (u == v) thenlca = u

else if T.depth(u) > T.depth(v) then u = T.parent(u)

else if T.depth(v) > T.depth(u)v = T.parent(v)

elseu = T.parent(u); udepth = udepth - 1v = T.parent(v); vdepth = vdepth – 1

return lca

Now irrelevant〉

Page 17: Improving Pseudo-Codecs.brown.edu/courses/cs016/static/files/lectures/... · Lowest Common Ancestor ‣ Given two nodes u and v ‣ determine deepest node that is ancestor of both

Lowest Common Ancestor

17

function LCA(u, v, T):// Input: two nodes u, v in a tree T// Output: the lowest common ancestor of u and vlca = null

if (T.isroot(u) == true) or (T.isroot(v) == true) then lca = T.root

while (lca == null) doif (u == v) then

lca = uelse if T.depth(u) > T.depth(v) then

u = T.parent(u)

else if T.depth(v) > T.depth(u)v = T.parent(v)

elseu = T.parent(u)v = T.parent(v)

return lca

Page 18: Improving Pseudo-Codecs.brown.edu/courses/cs016/static/files/lectures/... · Lowest Common Ancestor ‣ Given two nodes u and v ‣ determine deepest node that is ancestor of both

Ways to Improve Pseudo-Code‣ If method returns boolean‣ no need to check if returned value ==true

‣ Logical operators can be used on boolean returned valued‣ !T.isroot(u) is same as T.isroot(u)==false

18

Page 19: Improving Pseudo-Codecs.brown.edu/courses/cs016/static/files/lectures/... · Lowest Common Ancestor ‣ Given two nodes u and v ‣ determine deepest node that is ancestor of both

Lowest Common Ancestor

19

function LCA(u, v, T):// Input: two nodes u, v in a tree T// Output: the lowest common ancestor of u and vlca = null

if (T.isroot(u) == true) or (T.isroot(v) == true) then lca = T.root

while (lca == null) doif (u == v) then

lca = uelse if T.depth(u) > T.depth(v) then

u = T.parent(u)

else if T.depth(v) > T.depth(u)v = T.parent(v)

elseu = T.parent(u)v = T.parent(v)

return lca

Redundant equality checks

Page 20: Improving Pseudo-Codecs.brown.edu/courses/cs016/static/files/lectures/... · Lowest Common Ancestor ‣ Given two nodes u and v ‣ determine deepest node that is ancestor of both

Lowest Common Ancestor

20

function LCA(u, v, T):// Input: two nodes u, v in a tree T// Output: the lowest common ancestor of u and vlca = null

if T.isroot(u) or T.isroot(v) then lca = T.root

while (lca == null) doif (u == v) then

lca = uelse if T.depth(u) > T.depth(v) then

u = T.parent(u)

else if T.depth(v) > T.depth(u)v = T.parent(v)

elseu = T.parent(u)v = T.parent(v)

return lca

Page 21: Improving Pseudo-Codecs.brown.edu/courses/cs016/static/files/lectures/... · Lowest Common Ancestor ‣ Given two nodes u and v ‣ determine deepest node that is ancestor of both

Lowest Common Ancestor

21

function LCA(u, v, T):// Input: two nodes u, v in a tree T// Output: the lowest common ancestor of u and vlca = nullif T.isroot(u) or T.isroot(v) then

lca = T.rootwhile (lca == null) do

if (u == v) thenlca = u

else if T.depth(u) > T.depth(v) then u = T.parent(u)

else if T.depth(v) > T.depth(u)v = T.parent(v)

elseu = T.parent(u) v = T.parent(v)

return lca

Just removed whitespace

Page 22: Improving Pseudo-Codecs.brown.edu/courses/cs016/static/files/lectures/... · Lowest Common Ancestor ‣ Given two nodes u and v ‣ determine deepest node that is ancestor of both

Ways to Improve Pseudo-Code‣ As soon as you found answer, return it‣ This avoids going through unnecessary code

22

Page 23: Improving Pseudo-Codecs.brown.edu/courses/cs016/static/files/lectures/... · Lowest Common Ancestor ‣ Given two nodes u and v ‣ determine deepest node that is ancestor of both

Lowest Common Ancestor

23

function LCA(u, v, T):// Input: two nodes u, v in a tree T// Output: the lowest common ancestor of u and vlca = nullif T.isroot(u) or T.isroot(v) then

lca = T.rootwhile (lca == null) do

if (u == v) thenlca = u

else if T.depth(u) > T.depth(v) then u = T.parent(u)

else if T.depth(v) > T.depth(u)v = T.parent(v)

elseu = T.parent(u)v = T.parent(v)

return lca

It’s the answer. Return it!

Page 24: Improving Pseudo-Codecs.brown.edu/courses/cs016/static/files/lectures/... · Lowest Common Ancestor ‣ Given two nodes u and v ‣ determine deepest node that is ancestor of both

Lowest Common Ancestor

24

function LCA(u, v, T):// Input: two nodes u, v in a tree T// Output: the lowest common ancestor of u and vlca = nullif T.isroot(u) or T.isroot(v) then

lca = T.rootreturn lca

while (lca == null) doif (u == v) then

lca = uelse if T.depth(u) > T.depth(v) then

u = T.parent(u)else if T.depth(v) > T.depth(u)

v = T.parent(v)else

u = T.parent(u)v = T.parent(v)

return lca

It’s the answer. Return it!

Page 25: Improving Pseudo-Codecs.brown.edu/courses/cs016/static/files/lectures/... · Lowest Common Ancestor ‣ Given two nodes u and v ‣ determine deepest node that is ancestor of both

Lowest Common Ancestor

25

function LCA(u, v, T):// Input: two nodes u, v in a tree T// Output: the lowest common ancestor of u and vlca = nullif T.isroot(u) or T.isroot(v) then

lca = T.rootreturn lca

while (lca == null) doif (u == v) then

lca = ureturn lca

else if T.depth(u) > T.depth(v) then u = T.parent(u)

else if T.depth(v) > T.depth(u)v = T.parent(v)

elseu = T.parent(u)v = T.parent(v)

return lca

Page 26: Improving Pseudo-Codecs.brown.edu/courses/cs016/static/files/lectures/... · Lowest Common Ancestor ‣ Given two nodes u and v ‣ determine deepest node that is ancestor of both

Ways to Improve Pseudo-Code‣ If variable is only used to return something‣ simply return it

‣ Avoids keeping track of unnecessary variables‣ and makes code shorter and cleaner

26

Page 27: Improving Pseudo-Codecs.brown.edu/courses/cs016/static/files/lectures/... · Lowest Common Ancestor ‣ Given two nodes u and v ‣ determine deepest node that is ancestor of both

Lowest Common Ancestor

27

function LCA(u, v, T):// Input: two nodes u, v in a tree T// Output: the lowest common ancestor of u and vlca = nullif T.isroot(u) or T.isroot(v) then

lca = T.rootreturn lca

while (lca == null) doif (u == v) then

lca = ureturn lca

else if T.depth(u) > T.depth(v) then u = T.parent(u)

else if T.depth(v) > T.depth(u)v = T.parent(v)

elseu = T.parent(u)v = T.parent(v)

return lca

Condition is irrelevant

Page 28: Improving Pseudo-Codecs.brown.edu/courses/cs016/static/files/lectures/... · Lowest Common Ancestor ‣ Given two nodes u and v ‣ determine deepest node that is ancestor of both

Lowest Common Ancestor

28

function LCA(u, v, T):// Input: two nodes u, v in a tree T// Output: the lowest common ancestor of u and vlca = nullif T.isroot(u) or T.isroot(v) then

lca = T.rootreturn lca

repeatif (u == v) then

lca = ureturn lca

else if T.depth(u) > T.depth(v) then u = T.parent(u)

else if T.depth(v) > T.depth(u)v = T.parent(v)

elseu = T.parent(u)v = T.parent(v)

lca is no longer used

Page 29: Improving Pseudo-Codecs.brown.edu/courses/cs016/static/files/lectures/... · Lowest Common Ancestor ‣ Given two nodes u and v ‣ determine deepest node that is ancestor of both

Lowest Common Ancestor

29

function LCA(u, v, T):// Input: two nodes u, v in a tree T// Output: the lowest common ancestor of u and v

if T.isroot(u) or T.isroot(v) then

return T.rootrepeat

if (u == v) then

return uelse if T.depth(u) > T.depth(v) then

u = T.parent(u)else if T.depth(v) > T.depth(u)

v = T.parent(v)else

u = T.parent(u)v = T.parent(v)

Page 30: Improving Pseudo-Codecs.brown.edu/courses/cs016/static/files/lectures/... · Lowest Common Ancestor ‣ Given two nodes u and v ‣ determine deepest node that is ancestor of both

Lowest Common Ancestor

30

function LCA(u, v, T):// Input: two nodes u, v in a tree T// Output: the lowest common ancestor of u and vif T.isroot(u) or T.isroot(v) then

return T.rootrepeat

if (u == v) thenreturn u

else if T.depth(u) > T.depth(v) then u = T.parent(u)

else if T.depth(v) > T.depth(u)v = T.parent(v)

elseu = T.parent(u)v = T.parent(v)

Page 31: Improving Pseudo-Codecs.brown.edu/courses/cs016/static/files/lectures/... · Lowest Common Ancestor ‣ Given two nodes u and v ‣ determine deepest node that is ancestor of both

Ways to Improve Pseudo-Code‣ If you never enter a conditional in a while loop, ‣ try to use two while loops to simplify

‣ If u is at lower depth than v, algorithm will not allow u to get to a higher depth than v‣ so unnecessary to check both within one

while loop

31

Page 32: Improving Pseudo-Codecs.brown.edu/courses/cs016/static/files/lectures/... · Lowest Common Ancestor ‣ Given two nodes u and v ‣ determine deepest node that is ancestor of both

Lowest Common Ancestor

32

function LCA(u, v, T):// Input: two nodes u, v in a tree T// Output: the lowest common ancestor of u and vif T.isroot(u) or T.isroot(v) then

return T.rootrepeat

if (u == v) thenreturn u

else if T.depth(u) > T.depth(v) then u = T.parent(u)

else if T.depth(v) > T.depth(u)v = T.parent(v)

elseu = T.parent(u); udepth = udepth - 1v = T.parent(v); vdepth = vdepth – 1

Only one of these

conditionals will ever be

true

Page 33: Improving Pseudo-Codecs.brown.edu/courses/cs016/static/files/lectures/... · Lowest Common Ancestor ‣ Given two nodes u and v ‣ determine deepest node that is ancestor of both

Lowest Common Ancestor

33

function LCA(u, v, T):// Input: two nodes u, v in a tree T// Output: the lowest common ancestor of u and vwhile T.depth(u) > T.depth(v)

u = T.parent(u)while T.depth(v) > T.depth(u)

v = T.parent(v)if T.isroot(u) or T.isroot(v) then

return T.rootrepeat

if (u == v) thenreturn u

elseu = T.parent(u)v = T.parent(v)

Page 34: Improving Pseudo-Codecs.brown.edu/courses/cs016/static/files/lectures/... · Lowest Common Ancestor ‣ Given two nodes u and v ‣ determine deepest node that is ancestor of both

Ways to Improve Pseudo-Code‣ Avoid unnecessary conditional checks‣ In example, after the two while loops, ‣ u and v have same depth ‣ if either is root, they both are the same root

‣ Try to be as concise as possible!

34

Page 35: Improving Pseudo-Codecs.brown.edu/courses/cs016/static/files/lectures/... · Lowest Common Ancestor ‣ Given two nodes u and v ‣ determine deepest node that is ancestor of both

Lowest Common Ancestor

35

function LCA(u, v, T):// Input: two nodes u, v in a tree T// Output: the lowest common ancestor of u and vwhile T.depth(u) > T.depth(v)

u = T.parent(u)while T.depth(v) > T.depth(u)

v = T.parent(v)if T.isroot(u) or T.isroot(v) then

return T.rootrepeat

if (u == v) thenreturn u

elseu = T.parent(u)v = T.parent(v)

Page 36: Improving Pseudo-Codecs.brown.edu/courses/cs016/static/files/lectures/... · Lowest Common Ancestor ‣ Given two nodes u and v ‣ determine deepest node that is ancestor of both

Lowest Common Ancestor

36

function LCA(u, v, T):// Input: two nodes u, v in a tree T// Output: the lowest common ancestor of u and vwhile T.depth(u) > T.depth(v)

u = T.parent(u)while T.depth(v) > T.depth(u)

v = T.parent(v)if T.isroot(u) or T.isroot(v) or u == v then

return urepeat

if (u == v) thenreturn u

elseu = T.parent(u)v = T.parent(v)

Page 37: Improving Pseudo-Codecs.brown.edu/courses/cs016/static/files/lectures/... · Lowest Common Ancestor ‣ Given two nodes u and v ‣ determine deepest node that is ancestor of both

Ways to Improve Pseudo-Code‣ After the two while loops, ‣ u and v have same depth ‣ if either is root, then they both are root

‣ Try to be as concise as possible!

37

Page 38: Improving Pseudo-Codecs.brown.edu/courses/cs016/static/files/lectures/... · Lowest Common Ancestor ‣ Given two nodes u and v ‣ determine deepest node that is ancestor of both

Lowest Common Ancestor

38

function LCA(u, v, T):// Input: two nodes u, v in a tree T// Output: the lowest common ancestor of u and vwhile T.depth(u) > T.depth(v)

u = T.parent(u)while T.depth(v) > T.depth(u)

v = T.parent(v)if T.isroot(u) or T.isroot(v) or u == v then

return urepeat

if (u == v) thenreturn u

elseu = T.parent(u)v = T.parent(v)

Can be simplified

Page 39: Improving Pseudo-Codecs.brown.edu/courses/cs016/static/files/lectures/... · Lowest Common Ancestor ‣ Given two nodes u and v ‣ determine deepest node that is ancestor of both

Lowest Common Ancestor

39

function LCA(u, v, T):// Input: two nodes u, v in a tree T// Output: the lowest common ancestor of u and vwhile T.depth(u) > T.depth(v)

u = T.parent(u)while T.depth(v) > T.depth(u)

v = T.parent(v)if u == v then

return urepeat

if (u == v) thenreturn u

elseu = T.parent(u)v = T.parent(v)

Page 40: Improving Pseudo-Codecs.brown.edu/courses/cs016/static/files/lectures/... · Lowest Common Ancestor ‣ Given two nodes u and v ‣ determine deepest node that is ancestor of both

Lowest Common Ancestor

40

function LCA(u, v, T):// Input: two nodes u, v in a tree T// Output: the lowest common ancestor of u and vwhile T.depth(u) > T.depth(v)

u = T.parent(u)while T.depth(v) > T.depth(u)

v = T.parent(v)if u == v then

return urepeat

if (u == v) thenreturn u

elseu = T.parent(u)v = T.parent(v)

Condense into a single loop〉

Page 41: Improving Pseudo-Codecs.brown.edu/courses/cs016/static/files/lectures/... · Lowest Common Ancestor ‣ Given two nodes u and v ‣ determine deepest node that is ancestor of both

Lowest Common Ancestor

41

function LCA(u, v, T):// Input: two nodes u, v in a tree T// Output: the lowest common ancestor of u and vwhile T.depth(u) > T.depth(v)

u = T.parent(u)while T.depth(v) > T.depth(u)

v = T.parent(v)while u != v then

u = T.parent(u)v = T.parent(v)

return u

From clunky 19 lines to elegant 8 lines!

Page 42: Improving Pseudo-Codecs.brown.edu/courses/cs016/static/files/lectures/... · Lowest Common Ancestor ‣ Given two nodes u and v ‣ determine deepest node that is ancestor of both

Improve Pseudo-Code‣ Now that you have seen how easily pseudocode

can be simplified… ‣ …you are expected to make similar improvements to

your pseudo-code

‣ Good pseudo-code is both accurate & concise

42