37
IMPROVING PSEUDOCODE CS16: Introduction to Data Structures & Algorithms Thursday, February 26, 2015 1

IMPROVING PSEUDOCODE CS16: Introduction to Data Structures & Algorithms Thursday, February 26, 2015 1

Embed Size (px)

Citation preview

1

IMPROVING PSEUDOCODE

CS16: Introduction to Data Structures & Algorithms

Thursday, February 26, 2015

2

Clean Your Code

• Errors per line ~ constant• Fewer lines fewer errors overall

• Fewer lines are easier to grade• More likely to receive credit

• Cleaner code reflects cleaner thinking and a better understanding of the material

• Let’s work through an example…

Thursday, February 26, 2015

3

Lowest Common Ancestor (LCA)

Problem: Given two nodes u and v, determine the deepest node that’s an ancestor of both.

Thursday, February 26, 2015

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

4Thursday, February 26, 2015

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 = uelseif 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

5Thursday, February 26, 2015

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 = uelseif 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

What are the inputs? The output?

6Thursday, February 26, 2015

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 = uelseif 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

7Thursday, February 26, 2015

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 = uelseif 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?

8Thursday, February 26, 2015

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 = uelseif 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

9

Ways to improve psuedocode

• Clarify your input and output with comments

• This is a good habit to get into and makes methods easily understandable for somebody who has never seen them before

• Make sure all necessary arguments are included as parameters

Thursday, February 26, 2015

10Thursday, February 26, 2015

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 = uelseif 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

11Thursday, February 26, 2015

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 = uelseif 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

Now irrelevant

12

Ways to improve psuedocode

• Get rid of unnecessary variables• Using variables for information which can be accurately found elsewhere leaves room for careless errors• In this example there is no need for udepth and vdepth when the tree keeps track of the node’s depth

Thursday, February 26, 2015

13Thursday, February 26, 2015

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) thenlca = uelseif 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

14Thursday, February 26, 2015

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) thenlca = uelseif 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

15Thursday, February 26, 2015

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) thenlca = uelseif 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

16Thursday, February 26, 2015

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) thenlca = uelseif 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

17Thursday, February 26, 2015

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 = uelseif 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

Just removing some whitespace to fit on slides

18

Ways to improve psuedocode

• If a method returns a boolean, there is no need to check if return value == true

• Logical operators can be used on boolean return values • !T.isroot(u)equals T.isroot(u)==false

Thursday, February 26, 2015

19Thursday, February 26, 2015

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 = uelseif 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!

20Thursday, February 26, 2015

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) thenlca = uelseif 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!

21Thursday, February 26, 2015

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) thenlca = ureturn lcaelseif 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

22

Ways to improve psuedocode

• As soon as you know you’ve found the answer, return it!• This avoids going through unnecessary code

Thursday, February 26, 2015

23Thursday, February 26, 2015

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) thenlca = ureturn lcaelseif 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

Condition is irrelevant

24Thursday, February 26, 2015

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) thenlca = ureturn lcaelseif 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)

lca is no longer used

25Thursday, February 26, 2015

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 uelseif 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)

26Thursday, February 26, 2015

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 uelseif 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)

27

Ways to improve psuedocode

• If a variable is only used for the purpose of returning something, simply return the value

• This avoids having to keep track of an unnecessary variable and makes your code shorter and clearer

Thursday, February 26, 2015

28Thursday, February 26, 2015

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 uelseif 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)

29Thursday, February 26, 2015

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 uelseu = T.parent(u)v = T.parent(v)

30

Ways to improve psuedocode

• If you know you will not enter a conditional after one iteration through a while loop, attempt to use two separate while loops to simplify• In this example, if u is at a lower depth than v, the algorithm will not allow u to get to a higher depth than v. Therefore, it is unnecessary to continue checking both of these within one while loop

Thursday, February 26, 2015

31Thursday, February 26, 2015

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 uelseu = T.parent(u)v = T.parent(v)

32Thursday, February 26, 2015

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 uelseu = T.parent(u)v = T.parent(v)

33Thursday, February 26, 2015

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 uelseu = T.parent(u)v = T.parent(v)

Can be simplified!

34

Ways to improve psuedocode

• Avoid unnecessary conditional checks• In this example, after the two while loops, u and v have the same depth. If either is a root, they both are the same root

• Try to be as concise as possible!

Thursday, February 26, 2015

35Thursday, February 26, 2015

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 uelseu = T.parent(u)v = T.parent(v)

Condense into a single loop!

36Thursday, February 26, 2015

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 a clunky 19 lines to an elegant 8 line beauty!

37

Improve psuedocode – yes you can!

• Now that you have seen how easily psuedocode can be simplified, you are expected to be making similar improvements to your own psuedocode

• Good psuedocode is BOTH accurate and concise

Thursday, February 26, 2015