Data Structures: Ordered List, Recursion & Dynamic Programming in CS 1520 Lec 9, Study notes of Data Structures and Algorithms

Various topics related to data structures, including the implementation of an ordered list using a singly-linked list, recursion, and dynamic programming. Students will learn how to complete methods for an orderedlist class, write recursive code for a countdown function, and implement a recursive and dynamic programming solution for the fibonacci sequence.

Typology: Study notes

2012/2013

Uploaded on 04/30/2013

jut
jut 🇮🇳

4.5

(63)

77 documents

1 / 4

Toggle sidebar

This page cannot be seen from the preview

Don't miss anything!

bg1
1. The textbook’s ordered list ADT uses a singly-linked list implementation. I added the
_size
,
_tail
,
_current
,
_previous
, and
_currentIndex
attributes:
data next data next data next data next data next
_head
_currentIndex
_tail
_current
_size
_previous
4
3
'm' 'w''a' 'y''c'
OrderedList Object
a) The
search(targetItem)
method searches for
targetItem
in the list. It returns
True
if
targetItem
is in the list;
otherwise it returns
False
. Additionally, it has the side-effects of setting
_current
,
_previous
, and
_currentIndex
. Complete the
search(targetItem)
method code:
class OrderedList:
def search(self, targetItem):
b) Complete the
add(item)
method including a check of it’s precondition(s)?
def add(self, item):
Data Structures (CS 1520) Lecture 9 Name:_________________
L
ecture 9
- Page
1
Docsity.com
pf3
pf4

Partial preview of the text

Download Data Structures: Ordered List, Recursion & Dynamic Programming in CS 1520 Lec 9 and more Study notes Data Structures and Algorithms in PDF only on Docsity!

1. The textbook’s ordered list ADT uses a singly-linked list implementation. I added the _size, _tail, _current,

_previous, and _currentIndex attributes:

data next data next data next data next data next

_head

_currentIndex

_tail

_current

_size

_previous

'a' 'c' 'm' 'w' 'y'

OrderedList Object

a) The search(targetItem) method searches for targetItem in the list. It returns True if targetItem is in the list;

otherwise it returns False. Additionally, it has the side-effects of setting _current, _previous, and

_currentIndex. Complete the search(targetItem) method code:

class OrderedList:

def search(self, targetItem):

b) Complete the add(item) method including a check of it’s precondition(s)?

def add(self, item):

2. A recursive function is one that calls itself. Complete the recursive code for the countDown function that is

passed a starting value and proceeds to count down to zero and prints “Blast Off!!!”.

Hint: The countDown function, like most recursive functions, solves a problem by splitting the problem into one or

more simpler problems of the same type. For example, countDown(10) prints the first value (i.e, 10) and then

solves the simpler problem of counting down from 9. To prevent “infinite recursion”, if-statement(s) are used to check

for trivial base case (s) of the problem that can be solved without recursion. Here, when we reach a countDown(0)

problem we can just print “Blast Off!!!”.

Enter count down start: 10

Count Down: 10 9 8 7 6 5 4 3 2 1

Blast Off!!!

Program Output:

""" File: countDown.py

def main(): start = eval(input("Enter count down start: ")) print( "\nCount Down:") countDown(start)

def countDown(count):

main()

a) Trace the function call countDown(5) on paper by drawing the run-time stack and showing the output.

b) What do you think will happen if your call countDown(-1)?

c) Why is there a limit on the depth of recursion?

c) On my office computer, the call to fib(40) takes 22 seconds, the call to fib(41) takes 35 seconds, and the call to

fib(42) takes 56 seconds. How long would you expect fib(43) to take?

d) How long would you guess calculating fib(100) would take on my office computer?

e) Why do you suppose this recursive fib function is so slow?

f) What is the computational complexity? O ( )

g) How might we speed up the calculation of the Fibonacci series?

4. A VERY POWERFUL concept in Computer Science is dynamic programming. Dynamic programming solutions

eliminate the redundancy of divide-and-conquer algorithms by calculating the solutions to smaller problems first,

storing their answers, and looking up their answers if later needed instead of recalculating them.

We can use a list to store the answers to smaller problems of the Fibonacci sequence.

To transform from the recursive view of the problem to the dynamic programming solution you can do the following

steps:

1) Store the solution to smallest problems (i.e., the base cases) in a list

2) Loop (no recursion) from the base cases up to the biggest problem of interest. On each iteration of the loop we:

 solve the next bigger problem by looking up the solution to previously solved smaller problem(s)

 store the solution to this next bigger problem for later usage so we never have to recalculate it

a) Complete the dynamic programming code:

def fib(n): """Dynamic programming solution to find the nth number in the Fibonacci seq."""

List to hold the solutions to the smaller problems

fibonacci = []

Step 1: Store base case solutions

fibonacci.append( ) fibonacci.append( )

Step 2: Loop from base cases to biggest problem of interest

for position in range( ):

fibonacci.append( )

return nth number in the Fibonacci sequence

return

Running the above code to calculate fib(100) would only take a fraction of a second.

b) One tradeoff of simple dynamic programming implementations is that they can require more memory since we

store solutions to all smaller problems. Often, we can reduce the amount of storage needed if the next larger problem

(and all the larger problems) don’t really need the solution to the really small problems, but just the larger of the

smaller problems. In fibonacci when calculating the next value in the sequence how many of the previous solutions are

needed?