Lecture Notes for Merge Sort - Recursive Sorting | CS 245, Study notes of Data Structures and Algorithms

Material Type: Notes; Professor: Galles; Class: Data Struct & Algorithms; Subject: Computer Science; University: University of San Francisco (CA); Term: Intersession 2009;

Typology: Study notes

Pre 2010

Uploaded on 07/30/2009

koofers-user-p5x
koofers-user-p5x 🇺🇸

4

(1)

10 documents

1 / 10

Toggle sidebar

This page cannot be seen from the preview

Don't miss anything!

bg1
CS245-2009S-11 Sorting in Θ(nlg n)1
11-0: Merge Sort Recursive Sorting
Base Case:
A list of length 1 or length 0 is already sorted
Recursive Case:
Split the list in half
Recursively sort two halves
Merge sorted halves together
Example: 5 1 8 2 6 4 3 7 11-1: Merging
Merge lists into a new temporary list, T
Maintain three pointers (indices) i, j, and n
iis index of left hand list
jis index of right hand list
nis index of temporary list T
If A[i]< A[j]
T[n] = A[i], increment nand i
else
T[n] = A[j], increment nand j
Example: 1 2 5 8 and 3 4 6 7
11-2: Θ() for Merge Sort T(0) = c1for some constant c1
T(1) = c2for some constant c2
T(n) = nc3+ 2T(n/2) for some constant c3
T(n) = nc3+ 2T(n/2)
11-3: Θ() for Merge Sort T(0) = c1for some constant c1
T(1) = c2for some constant c2
T(n) = nc3+ 2T(n/2) for some constant c3
T(n) = nc3+ 2T(n/2)
=nc3+ 2(n/2c3+ 2T(n/4))
= 2nc3+ 4T(n/4)
11-4: Θ() for Merge Sort T(0) = c1for some constant c1
T(1) = c2for some constant c2
T(n) = nc3+ 2T(n/2) for some constant c3
T(n) = nc3+ 2T(n/2)
=nc3+ 2(n/2c3+ 2T(n/4))
= 2nc3+ 4T(n/4)
= 2nc3+ 4(n/4c3+ 2T(n/8))
= 3nc3+ 8T(n/8))
11-5: Θ() for Merge Sort T(0) = c1for some constant c1
T(1) = c2for some constant c2
T(n) = nc3+ 2T(n/2) for some constant c3
pf3
pf4
pf5
pf8
pf9
pfa

Partial preview of the text

Download Lecture Notes for Merge Sort - Recursive Sorting | CS 245 and more Study notes Data Structures and Algorithms in PDF only on Docsity!

11-0: Merge Sort – Recursive Sorting

  • Base Case:
    • A list of length 1 or length 0 is already sorted
  • Recursive Case:
    • Split the list in half
    • Recursively sort two halves
    • Merge sorted halves together

Example: 5 1 8 2 6 4 3 7 11-1: Merging

  • Merge lists into a new temporary list, T
  • Maintain three pointers (indices) i, j, and n
    • i is index of left hand list
    • j is index of right hand list
    • n is index of temporary list T
  • If A[i] < A[j]
    • T [n] = A[i], increment n and i
  • else
    • T [n] = A[j], increment n and j

Example: 1 2 5 8 and 3 4 6 7

11-2: Θ() for Merge Sort

T (0) = c 1 for some constant c 1 T (1) = c 2 for some constant c 2 T (n) = nc 3 + 2T (n/2) for some constant c 3 T (n) = nc 3 + 2T (n/2)

11-3: Θ() for Merge Sort

T (0) = c 1 for some constant c 1 T (1) = c 2 for some constant c 2 T (n) = nc 3 + 2T (n/2) for some constant c 3 T (n) = nc 3 + 2T (n/2) = nc 3 + 2(n/ 2 c 3 + 2T (n/4)) = 2nc 3 + 4T (n/4)

11-4: Θ() for Merge Sort

T (0) = c 1 for some constant c 1 T (1) = c 2 for some constant c 2 T (n) = nc 3 + 2T (n/2) for some constant c 3 T (n) = nc 3 + 2T (n/2) = nc 3 + 2(n/ 2 c 3 + 2T (n/4)) = 2nc 3 + 4T (n/4) = 2nc 3 + 4(n/ 4 c 3 + 2T (n/8)) = 3nc 3 + 8T (n/8))

11-5: Θ() for Merge Sort

T (0) = c 1 for some constant c 1 T (1) = c 2 for some constant c 2 T (n) = nc 3 + 2T (n/2) for some constant c 3

T (n) = nc 3 + 2T (n/2) = nc 3 + 2(n/ 2 c 3 + 2T (n/4)) = 2nc 3 + 4T (n/4) = 2nc 3 + 4(n/ 4 c 3 + 2T (n/8)) = 3nc 3 + 8T (n/8)) = 3nc 3 + 8(n/ 8 c 3 + 2T (n/16)) = 4nc 3 + 16T (n/16)

11-6: Θ() for Merge Sort

T (0) = c 1 for some constant c 1 T (1) = c 2 for some constant c 2 T (n) = nc 3 + 2T (n/2) for some constant c 3 T (n) = nc 3 + 2T (n/2) = nc 3 + 2(n/ 2 c 3 + 2T (n/4)) = 2nc 3 + 4T (n/4) = 2nc 3 + 4(n/ 4 c 3 + 2T (n/8)) = 3nc 3 + 8T (n/8)) = 3nc 3 + 8(n/ 8 c 3 + 2T (n/16)) = 4nc 3 + 16T (n/16) = 5nc 3 + 32T (n/32)

11-7: Θ() for Merge Sort

T (0) = c 1 for some constant c 1 T (1) = c 2 for some constant c 2 T (n) = nc 3 + 2T (n/2) for some constant c 3 T (n) = nc 3 + 2T (n/2) = nc 3 + 2(n/ 2 c 3 + 2T (n/4)) = 2nc 3 + 4T (n/4) = 2nc 3 + 4(n/ 4 c 3 + 2T (n/8)) = 3nc 3 + 8T (n/8)) = 3nc 3 + 8(n/ 8 c 3 + 2T (n/16)) = 4nc 3 + 16T (n/16) = 5nc 3 + 32T (n/32) = knc 3 + 2kT (n/ 2 k) 11-8: Θ() for Merge Sort

T (0) = c 1 T (1) = c 2 T (n) = knc 3 + 2kT (n/ 2 k) Pick a value for k such that n/ 2 k^ = 1: n/ 2 k^ = 1 n = 2 k lg n = k T (n) = (lg n)nc 3 + 2lg^ nT (n/ 2 lg^ n) = c 3 n lg n + nT (n/n) = c 3 n lg n + nT (1) = c 3 n lg n + c 2 n ∈ O(n lg n)

11-9: Θ() for Merge Sort

T(n)

11-10: Θ() for Merge Sort

c*n

c(n/2) c(n/2)

c(n/4) c(n/4) c(n/4) c(n/4)

c*n

c*n

c*n

c*n

lg n levels

... (^) ... (^) ... ...

Total time = c*n lg n Θ(n lg n)

11-15: Divide & Conquer Merge Sort:

  • Divide the list two parts
    • No work required – just calculate midpoint
  • Recursively sort two parts
  • Combine sorted lists into one list
    • Some work required – need to merge lists

11-16: Divide & Conquer Quick Sort:

  • Divide the list two parts
    • Some work required – Small elements in left sublist, large elements in right sublist
  • Recursively sort two parts
  • Combine sorted lists into one list
    • No work required!

11-17: Quick Sort

  • Pick a pivot element
  • Reorder the list:
    • All elements < pivot
    • Pivot element
    • All elements > pivot
  • Recursively sort elements < pivot
  • Recursively sort elements > pivot

Example: 3 7 2 8 1 4 6 11-18: Quick Sort - Partitioning Basic Idea:

  • Swap pivot elememt out of the way (we’ll swap it back later)
  • Maintain two pointers, i and j
    • i points to the beginning of the list
    • j points to the end of the list
  • Move i and j in to the middle of the list – ensuring that all elements to the left of i are < the pivot, and all elememnts to the right of j are greater than the pivot
  • Swap pivot element back to middle of list

11-19: Quick Sort - Partitioning Pseudocode:

  • Pick a pivot index
  • Swap A[pivotindex] and A[high]
  • Set i ← low, j ← high− 1
  • while (i <= j)
    • while A[i] < A[pivot], increment i
    • while A[j] > A[pivot], decrement i
    • swap A[i] and A[j]
    • increment i, decrement j
  • swap A[i] and A[pivot]

11-20: Θ() for Quick Sort

  • Coming up with a recurrence relation for quicksort is harder than mergesort
  • How the problem is divided depends upon the data
    • Break list into:

size 0 , size n − 1 size 1 , size n − 2

... size ⌊(n − 1)/ 2 ⌋, size ⌈(n − 1)/ 2 ⌉ ... size n − 2 , size 1 size n − 1 , size 0

T (n) = T (n − k) + (

∑k− 1 i=0 (n^ −^ i)c^3 ) +^ kc^2 = T (n − n) + (

∑n− 1 i=0 (n^ −^ i)c^3 ) +^ kc^2 = T (0) + (

∑n− 1 i=0 (n^ −^ i)c^3 ) +^ kc^2 = T (0) + (

∑n− 1 i=0 ic^3 ) +^ kc^2 = c 1 + c 3 n(n + 1)/2 + kc 2 ∈ Θ(n^2 ) 11-28: Θ() for Quick Sort

T(n)

11-29: Θ() for Quick Sort

c*n

T(n-1) T(0)

11-30: Θ() for Quick Sort

c*n

c*(n-1) c

T(n-2) T(0)

11-31: Θ() for Quick Sort

c*n

c*(n-1) c

c*(n-2) c

T(n-3) T(0)

11-32: Θ() for Quick Sort

c*n

c*(n-1) c

c*n

c*(n-1)+c

n

levels

c(n-2) c2 c(n-2)+c

c(n-3) c2 c(n-3)+c

c*(n-k)+c

11-33: Θ() for Quick Sort

c*n

c*(n-1) c

c*n

c*(n-1)+c

n

levels

Total time = cn(n+1)/2 + nc

c(n-2) c2 c(n-2)+c

c(n-3) c2 c(n-3)+c

Θ(n )^2

c*(n-k)+c

11-34: Θ() for Quick Sort

Best case performance occurs when break list into size ⌊(n − 1)/ 2 ⌋ and size ⌈(n − 1)/ 2 ⌉ T (0) = c 1 for some constant c 1 T (1) = c 2 for some constant c 2 T (n) = nc 3 + 2T (n/2) for some constant c 3

This is the same as Merge Sort: Θ(n lg n) 11-35: Quick Sort? If Quicksort is Θ(n^2 ) on some lists, why is it called quick?

  • Most lists give running time of Θ(n lg n): The average case running time (assuming all permutations are equall likely) is Θ(n lg n) - We could prove this by finding the running time for each permutation of a list of length n, and averaging them - Math required to do this is a little beyond the prerequisites for this class) - Consider what happens when the list is always partitioned into a list of length n/ 9 and a list of lenth 8 n/ 9 (recursion tree, on whiteboard) - Consider what happenswhen the list is always partitioned into a list of length n/k and a list of length (k − 1)n/k, for any k

11-36: Quick Sort?

If Quicksort is Θ(n^2 ) on some lists, why is it called quick?

  • Most lists give running time of Θ(n lg n)
    • Average case running time is Θ(n lg n)
  • Constants are very small
    • Constants don’t matter when complexity is different
    • Constants do matter when complexity is the same
  • We can modify heapsort so that it does not use extra space
  • Build a heap out of the original array, with two differences:
    • Consider element 0 to be the root of the tree
      • for element i, children are at 2i +1 and 2i+2, and parent is at (i − 1)/ 2
      • (examples)
    • Max-heap instead of a standard min-heap
      • For each subtree, element stored at root ≥ element stored in that subtree (instead of ≤, as in a standard heap)

11-42: Heap Sort

  • Build a heap out of the original array, with two differences:
    • Consider element 0 to be the root of the tree
      • for element i, children are at 2i +1 and 2i+2, and parent is at (i − 1)/ 2
      • (examples)
    • Max-heap instead of a standard min-heap
      • For each subtree, element stored at root ≥ element stored in that subtree (instead of ≤, as in a standard heap)
  • Repeatedly remove the largest element, and insert it in the back of the heap

Example: 3 1 7 2 5 4 11-43: Θ() for Heap Sort

  • Building the heap takes time Θ(n)
  • Each of the n RemoveMax calls takes time O(lg n)
  • Total time: Ø(n lg n) (also Θ(n lg n))