Project 2 Solutions

  1. Let f(n) = n (n + 1) / 2. Of the following possibilities, state which are true about f and of those, which one best describes the asymptotic class of f ? (Be sure to argue your answers.)

    a. Θ(n2) b. O(n2) c. Ω(n2)
    d. Θ(n (n + 1) / 2)     e. O(n (n + 1) / 2)     f. Ω(n (n + 1) / 2)    
    g. Θ(n3) h. O(n3) i. Ω(n3)
    j. Θ(n log n) k. O(n log n) l. Ω(n log n)
    m. Θ(n) n. O(n) o. Ω(n)

    Answer: all are true except for
       g,i : because n2 ≤ O(n3) but NOT ≥ Ω(n3)
       j,k : because n2 ≥ Ω(n log n) but NOT ≤ O(n log n)
       m,n : because n2 ≥ Ω(n) but NOT ≤ O(n)
    The best representative of Θ(n (n + 1) / 2) is (IMO) n2 because it is the simplest.

  2. Which of these statements are best supported by data obtained using search_spy (argue your answer):

    1. fsu::g_lower_bound has asymptotic runtime Θ(log n).
    2. fsu::g_lower_bound has asymptotic runtime O(log n) but not Ω(log n).
    3. seq::g_lower_bound has asymptotic runtime Θ(n).
    4. seq::g_lower_bound has asymptotic runtime O(n) but not Ω(n).

    Answer: a and d.
       a and not b because the data for the fsu:: versions indicates that all searches require about log n comparisons
       d and not c because the data for alt:: versions indicate some searches require very few comparisons while others require almost n comparisons.

  3. State an asymptotic runtime for each sort algorithm that is best supported by data gathered with sort_spy. Argue your answer using collected data, and also discuss characteristics of the algorithm body that support your answer.

       g_selection_sort = Θ(n2)
       g_insertion_sort ≤ O(n2)
       g_heap_sort ≤ O(n log n)
       List::Sort ≤ O(n log n)

    Note: These are the best you could do with the data at this time. However, there is a theoretical result all comparison sorts can have worst-case runtime better ≥ Ω(n log n), which leads to these more precise statements:

       g_selection_sort = Θ(n2)
       g_insertion_sort ≤ O(n2)
       g_heap_sort = Θ(n log n)
       List::Sort = Θ(n log n)

  4. Describe two scenarios, one under which the namespace fsu search algorithms are appropriate and one under which the namespace seq versions are appropriate.

    Because the fsu:: and seq:: algorithms have the same assumptions on the data - namely that it is sorted - whenever we can use the fsu:: versions we are better off because they are much faster. So the only situation where we would "choose" the seq:: versions is when we are forced to because the iterators defining the search range are not powerful enough to work with the fsu:: versions. In other words, when the iterators are not random access iterators. The classic case for this is List::Iterator - which are bidirectional iterators but do not have a bracket operator and "pointer" arithmetic.

    Short answer: when the data is in a List (not an array, Deque, or Vector)