Mergesort and Quicksort Chapter 8 Kruse Sorting algorithms

  • Slides: 51
Download presentation
Mergesort and Quicksort Chapter 8 Kruse

Mergesort and Quicksort Chapter 8 Kruse

Sorting algorithms • Insertion, selection and bubble sort have quadratic worst-case performance • The

Sorting algorithms • Insertion, selection and bubble sort have quadratic worst-case performance • The faster comparison based algorithm ? O(nlogn) • Mergesort and Quicksort

Merge Sort • Apply divide-and-conquer to sorting problem • Problem: Given n elements, sort

Merge Sort • Apply divide-and-conquer to sorting problem • Problem: Given n elements, sort elements into non -decreasing order • Divide-and-Conquer: – If n=1 terminate (every one-element list is already sorted) – If n>1, partition elements into two or more subcollections; sort each; combine into a single sorted list • How do we partition?

Partitioning • • Let’s try to achieve balanced partitioning A gets n/2 elements, B

Partitioning • • Let’s try to achieve balanced partitioning A gets n/2 elements, B gets rest half Sort A and B recursively Combine sorted A and B using a process called merge, which combines two sorted lists into one

Example • Partition into lists of size n/2 [10, 4, 6, 3, 8, 2,

Example • Partition into lists of size n/2 [10, 4, 6, 3, 8, 2, 5, 7] [10, 4, 6, 3] [8, 2, 5, 7] [6, 3] [8, 2] [5, 7] [4] [10] [3][6] [2][8] [5][7] [10, 4]

Example Cont’d • Merge [2, 3, 4, 5, 6, 7, 8, 10 ] [3,

Example Cont’d • Merge [2, 3, 4, 5, 6, 7, 8, 10 ] [3, 4, 6, 10] [2, 5, 7, 8] [3, 6] [2, 8] [5, 7] [4] [10] [3][6] [2][8] [5][7] [4, 10]

Method merge. Sort() void merge. Sort(int numbers[], int temp[], int array_size) { m_sort(numbers, temp,

Method merge. Sort() void merge. Sort(int numbers[], int temp[], int array_size) { m_sort(numbers, temp, 0, array_size - 1); } void m_sort(int numbers[], int temp[], int left, int right) { int mid; if (right > left) { mid = (right + left) / 2; m_sort(numbers, temp, left, mid); m_sort(numbers, temp, mid+1, right); merge(numbers, temp, left, mid+1, right); } }

void merge(int numbers[], int temp[], int left, int mid, int right){ int i, left_end,

void merge(int numbers[], int temp[], int left, int mid, int right){ int i, left_end, num_elements, tmp_pos; left_end = mid - 1; tmp_pos = left; num_elements = right - left + 1; while ((left <= left_end) && (mid <= right)) { //merge two half using temp array if (numbers[left] <= numbers[mid]) { temp[tmp_pos] = numbers[left]; tmp_pos = tmp_pos + 1; left = left +1; } else { temp[tmp_pos] = numbers[mid]; tmp_pos = tmp_pos + 1; mid = mid + 1; } } while (left <= left_end){ temp[tmp_pos] = numbers[left]; left = left + 1; tmp_pos = tmp_pos + 1; } while (mid <= right) { temp[tmp_pos] = numbers[mid]; mid = mid + 1; tmp_pos = tmp_pos + 1; } for (i = 0; i <= num_elements; i++) { //copy array back to original array numbers[right] = temp[right]; right = right - 1; } }

Merge Function

Merge Function

Quicksort Algorithm • Quicksort is a divide-and-conquer sorting algorithm in which division is dynamically

Quicksort Algorithm • Quicksort is a divide-and-conquer sorting algorithm in which division is dynamically carried out The three steps of Quicksort are as follows: Divide: Rearrange the elements and split the array into two subarrays and an element in between such that so that each element in the left subarray is less than or equal the middle element and each element in the right subarray is greater than the middle element. Conquer: Recursively sort the two subarrays.

Quicksort Algorithm Given an array of n elements (e. g. , integers): • If

Quicksort Algorithm Given an array of n elements (e. g. , integers): • If array only contains one element, return • Else – pick one element to use as pivot. – Partition elements into two sub-arrays: • Elements less than or equal to pivot • Elements greater than pivot – Quicksort two sub-arrays – Return results

Example We are given array of n integers to sort: 40 20 10 80

Example We are given array of n integers to sort: 40 20 10 80 60 50 7 30 100

Pick Pivot Element There a number of ways to pick the pivot element. In

Pick Pivot Element There a number of ways to pick the pivot element. In this example, we will use the first element in the array: 40 20 10 80 60 50 7 30 100

Partitioning Array Given a pivot, partition the elements of the array such that the

Partitioning Array Given a pivot, partition the elements of the array such that the resulting array consists of: 1. One sub-array that contains elements >= pivot 2. Another sub-array that contains elements < pivot The sub-arrays are stored in the original data array. Partitioning loops through, swapping elements below/above pivot.

pivot_index = 0 40 20 10 [0] [1] [2] [3] [4] [5] too_big_index 80

pivot_index = 0 40 20 10 [0] [1] [2] [3] [4] [5] too_big_index 80 60 50 7 30 100 [6] [7] [8] too_small_index

1. While data[too_big_index] <= data[pivot_index ] ++too_big_index pivot_index = 0 40 20 10 [0]

1. While data[too_big_index] <= data[pivot_index ] ++too_big_index pivot_index = 0 40 20 10 [0] [1] [2] [3] [4] [5] too_big_index 80 60 50 7 30 100 [6] [7] [8] too_small_index

1. While data[too_big_index] <= data[pivot_index ] ++too_big_index pivot_index = 0 40 20 10 [0]

1. While data[too_big_index] <= data[pivot_index ] ++too_big_index pivot_index = 0 40 20 10 [0] [1] [2] [3] [4] [5] too_big_index 80 60 50 7 30 100 [6] [7] [8] too_small_index

1. While data[too_big_index] <= data[pivot_index ] ++too_big_index pivot_index = 0 40 20 10 80

1. While data[too_big_index] <= data[pivot_index ] ++too_big_index pivot_index = 0 40 20 10 80 60 [0] [1] [2] [3] [4] [5] too_big_index 50 7 30 100 [6] [7] [8] too_small_index

1. While data[too_big_index] <= data[pivot_index ] ++too_big_index 2. While data[too_small_index] > data[pivot_index t] --too_small_index

1. While data[too_big_index] <= data[pivot_index ] ++too_big_index 2. While data[too_small_index] > data[pivot_index t] --too_small_index pivot_index = 0 40 20 10 80 60 [0] [1] [2] [3] [4] [5] too_big_index 50 7 30 100 [6] [7] [8] too_small_index

1. While data[too_big_index] <= data[pivot_index ] ++too_big_index 2. While data[too_small_index] > data[pivot_index ] --too_small_index

1. While data[too_big_index] <= data[pivot_index ] ++too_big_index 2. While data[too_small_index] > data[pivot_index ] --too_small_index pivot_index = 0 40 20 10 80 60 [0] [1] [2] [3] [4] [5] too_big_index 50 7 30 100 [6] [7] [8] too_small_index

1. While data[too_big_index] <= data[pivot_index ] ++too_big_index 2. While data[too_small_index] > data[pivot_index ] --too_small_index

1. While data[too_big_index] <= data[pivot_index ] ++too_big_index 2. While data[too_small_index] > data[pivot_index ] --too_small_index 3. If too_big_index < too_small_index swap data[too_big_index] and data[too_small_index] pivot_index = 0 40 20 10 80 60 [0] [1] [2] [3] [4] [5] too_big_index 50 7 30 100 [6] [7] [8] too_small_index

1. While data[too_big_index] <= data[pivot_index ] ++too_big_index 2. While data[too_small_index] > data[pivot_index ] --too_small_index

1. While data[too_big_index] <= data[pivot_index ] ++too_big_index 2. While data[too_small_index] > data[pivot_index ] --too_small_index 3. If too_big_index < too_small_index swap data[too_big_index] and data[too_small_index] pivot_index = 0 40 20 10 30 60 [0] [1] [2] [3] [4] [5] too_big_index 50 7 80 100 [6] [7] [8] too_small_index

1. While data[too_big_index] <= data[pivot_index ] ++too_big_index 2. While data[too_small_index] > data[pivot_index ] --too_small_index

1. While data[too_big_index] <= data[pivot_index ] ++too_big_index 2. While data[too_small_index] > data[pivot_index ] --too_small_index 3. If too_big_index < too_small_index swap data[too_big_index] and data[too_small_index] 4. While too_small_index > too_big_index, go to 1. pivot_index = 0 40 20 10 30 60 [0] [1] [2] [3] [4] [5] too_big_index 50 7 80 100 [6] [7] [8] too_small_index

1. While data[too_big_index] <= data[pivot_index ] ++too_big_index 2. While data[too_small_index] > data[pivot_index ] --too_small_index

1. While data[too_big_index] <= data[pivot_index ] ++too_big_index 2. While data[too_small_index] > data[pivot_index ] --too_small_index 3. If too_big_index < too_small_index swap data[too_big_index] and data[too_small_index] 4. While too_small_index > too_big_index, go to 1. pivot_index = 0 40 20 10 30 60 [0] [1] [2] [3] [4] [5] too_big_index 50 7 80 100 [6] [7] [8] too_small_index

1. While data[too_big_index] <= data[pivot_index ] ++too_big_index 2. While data[too_small_index] > data[pivot_index ] --too_small_index

1. While data[too_big_index] <= data[pivot_index ] ++too_big_index 2. While data[too_small_index] > data[pivot_index ] --too_small_index 3. If too_big_index < too_small_index swap data[too_big_index] and data[too_small_index] 4. While too_small_index > too_big_index, go to 1. pivot_index = 0 40 20 10 30 60 [0] [1] [2] [3] [4] [5] too_big_index 50 7 80 100 [6] [7] [8] too_small_index

1. While data[too_big_index] <= data[pivot_index ] ++too_big_index 2. While data[too_small_index] > data[pivot_index ] --too_small_index

1. While data[too_big_index] <= data[pivot_index ] ++too_big_index 2. While data[too_small_index] > data[pivot_index ] --too_small_index 3. If too_big_index < too_small_index swap data[too_big_index] and data[too_small_index] 4. While too_small_index > too_big_index, go to 1. pivot_index = 0 40 20 10 30 60 [0] [1] [2] [3] [4] [5] too_big_index 50 7 80 100 [6] [7] [8] too_small_index

1. While data[too_big_index] <= data[pivot_index ] ++too_big_index 2. While data[too_small_index] > data[pivot_index ] --too_small_index

1. While data[too_big_index] <= data[pivot_index ] ++too_big_index 2. While data[too_small_index] > data[pivot_index ] --too_small_index 3. If too_big_index < too_small_index swap data[too_big_index] and data[too_small_index] 4. While too_small_index > too_big_index, go to 1. pivot_index = 0 40 20 10 30 60 [0] [1] [2] [3] [4] [5] too_big_index 50 7 80 100 [6] [7] [8] too_small_index

1. While data[too_big_index] <= data[pivot_index ] ++too_big_index 2. While data[too_small_index] > data[pivot_index ] --too_small_index

1. While data[too_big_index] <= data[pivot_index ] ++too_big_index 2. While data[too_small_index] > data[pivot_index ] --too_small_index 3. If too_big_index < too_small_index swap data[too_big_index] and data[too_small_index] 4. While too_small_index > too_big_index, go to 1. pivot_index = 0 40 20 10 30 60 [0] [1] [2] [3] [4] [5] too_big_index 50 7 80 100 [6] [7] [8] too_small_index

1. While data[too_big_index] <= data[pivot_index ] ++too_big_index 2. While data[too_small_index] > data[pivot_index ] --too_small_index

1. While data[too_big_index] <= data[pivot_index ] ++too_big_index 2. While data[too_small_index] > data[pivot_index ] --too_small_index 3. If too_big_index < too_small_index swap data[too_big_index] and data[too_small_index] 4. While too_small_index > too_big_index, go to 1. pivot_index = 0 40 20 10 30 7 [0] [1] [2] [3] [4] [5] too_big_index 50 60 80 100 [6] [7] [8] too_small_index

1. While data[too_big_index] <= data[pivot_index ] ++too_big_index 2. While data[too_small_index] > data[pivot_index ] --too_small_index

1. While data[too_big_index] <= data[pivot_index ] ++too_big_index 2. While data[too_small_index] > data[pivot_index ] --too_small_index 3. If too_big_index < too_small_index swap data[too_big_index] and data[too_small_index] 4. While too_small_index > too_big_index, go to 1. pivot_index = 0 40 20 10 30 7 [0] [1] [2] [3] [4] [5] too_big_index 50 60 80 100 [6] [7] [8] too_small_index

1. While data[too_big_index] <= data[pivot_index ] ++too_big_index 2. While data[too_small_index] > data[pivot_index ] --too_small_index

1. While data[too_big_index] <= data[pivot_index ] ++too_big_index 2. While data[too_small_index] > data[pivot_index ] --too_small_index 3. If too_big_index < too_small_index swap data[too_big_index] and data[too_small_index] 4. While too_small_index > too_big_index, go to 1. pivot_index = 0 40 20 10 30 7 [0] [1] [2] [3] [4] [5] too_big_index 50 60 80 100 [6] [7] [8] too_small_index

1. While data[too_big_index] <= data[pivot_index ] ++too_big_index 2. While data[too_small_index] > data[pivot_index ] --too_small_index

1. While data[too_big_index] <= data[pivot_index ] ++too_big_index 2. While data[too_small_index] > data[pivot_index ] --too_small_index 3. If too_big_index < too_small_index swap data[too_big_index] and data[too_small_index] 4. While too_small_index > too_big_index, go to 1. pivot_index = 0 40 20 10 30 7 [0] [1] [2] [3] [4] [5] too_big_index 50 60 80 100 [6] [7] [8] too_small_index

1. While data[too_big_index] <= data[pivot_index ] ++too_big_index 2. While data[too_small_index] > data[pivot_index ] --too_small_index

1. While data[too_big_index] <= data[pivot_index ] ++too_big_index 2. While data[too_small_index] > data[pivot_index ] --too_small_index 3. If too_big_index < too_small_index swap data[too_big_index] and data[too_small_index] 4. While too_small_index > too_big_index, go to 1. pivot_index = 0 40 20 10 30 7 [0] [1] [2] [3] [4] [5] too_big_index 50 60 80 100 [6] [7] [8] too_small_index

1. While data[too_big_index] <= data pivot_index ] ++too_big_index 2. While data[too_small_index] > data[pivot_index ]

1. While data[too_big_index] <= data pivot_index ] ++too_big_index 2. While data[too_small_index] > data[pivot_index ] --too_small_index 3. If too_big_index < too_small_index swap data[too_big_index] and data[too_small_index] 4. While too_small_index > too_big_index, go to 1. pivot_index = 0 40 20 10 30 7 [0] [1] [2] [3] [4] [5] too_big_index 50 60 80 100 [6] [7] [8] too_small_index

1. While data[too_big_index] <= data[pivot_index ] ++too_big_index 2. While data[too_small_index] > data[pivot_index ] --too_small_index

1. While data[too_big_index] <= data[pivot_index ] ++too_big_index 2. While data[too_small_index] > data[pivot_index ] --too_small_index 3. If too_big_index < too_small_index swap data[too_big_index] and data[too_small_index] 4. While too_small_index > too_big_index, go to 1. pivot_index = 0 40 20 10 30 7 [0] [1] [2] [3] [4] [5] too_big_index 50 60 80 100 [6] [7] [8] too_small_index

1. While data[too_big_index] <= data[pivot_index ] ++too_big_index 2. While data[too_small_index] > data[pivot_index ] --too_small_index

1. While data[too_big_index] <= data[pivot_index ] ++too_big_index 2. While data[too_small_index] > data[pivot_index ] --too_small_index 3. If too_big_index < too_small_index swap data[too_big_index] and data[too_small_index] 4. While too_small_index > too_big_index, go to 1. pivot_index = 0 40 20 10 30 7 [0] [1] [2] [3] [4] [5] too_big_index 50 60 80 100 [6] [7] [8] too_small_index

1. While data[too_big_index] <= data[pivot_index ] ++too_big_index 2. While data[too_small_index] > data[pivot_index ] --too_small_index

1. While data[too_big_index] <= data[pivot_index ] ++too_big_index 2. While data[too_small_index] > data[pivot_index ] --too_small_index 3. If too_big_index < too_small_index swap data[too_big_index] and data[too_small_index] 4. While too_small_index > too_big_index, go to 1. pivot_index = 0 40 20 10 30 7 [0] [1] [2] [3] [4] [5] too_big_index 50 60 80 100 [6] [7] [8] too_small_index

1. While data[too_big_index] <= data[pivot_index ] ++too_big_index 2. While data[too_small_index] > data[pivot_index ] --too_small_index

1. While data[too_big_index] <= data[pivot_index ] ++too_big_index 2. While data[too_small_index] > data[pivot_index ] --too_small_index 3. If too_big_index < too_small_index swap data[too_big_index] and data[too_small_index] 4. While too_small_index > too_big_index, go to 1. 5. Swap data[too_small_index] and data[pivot_index] pivot_index = 0 40 20 10 30 7 [0] [1] [2] [3] [4] [5] too_big_index 50 60 80 100 [6] [7] [8] too_small_index

1. While data[too_big_index] <= data[pivot_index ] ++too_big_index 2. While data[too_small_index] > data[pivot_index ] --too_small_index

1. While data[too_big_index] <= data[pivot_index ] ++too_big_index 2. While data[too_small_index] > data[pivot_index ] --too_small_index 3. If too_big_index < too_small_index swap data[too_big_index] and data[too_small_index] 4. While too_small_index > too_big_index, go to 1. 5. Swap data[too_small_index] and data[pivot_index] pivot_index = 4 7 [0] 20 10 30 40 50 [1] [2] [3] [4] [5] too_big_index 60 80 100 [6] [7] [8] too_small_index

Partition Result 7 [0] 20 10 30 40 50 [1] [2] [3] [4] [5]

Partition Result 7 [0] 20 10 30 40 50 [1] [2] [3] [4] [5] <= data[pivot] 60 80 100 [6] [7] [8] > data[pivot]

Recursion: Quicksort Sub-arrays 7 [0] 20 10 30 40 50 [1] [2] [3] [4]

Recursion: Quicksort Sub-arrays 7 [0] 20 10 30 40 50 [1] [2] [3] [4] [5] <= data[pivot] 60 80 100 [6] [7] [8] > data[pivot]

Quicksort: Worst Case • Assume first element is chosen as pivot. • Assume we

Quicksort: Worst Case • Assume first element is chosen as pivot. • Assume we get array that is already in order: pivot_index = 0 2 [0] 4 10 12 13 50 [1] [2] [3] [4] [5] too_big_index 57 63 100 [6] [7] [8] too_small_index

1. While data[too_big_index] <= data[pivot_index ] ++too_big_index 2. While data[too_small_index] > data[pivot_index ] --too_small_index

1. While data[too_big_index] <= data[pivot_index ] ++too_big_index 2. While data[too_small_index] > data[pivot_index ] --too_small_index 3. If too_big_index < too_small_index swap data[too_big_index] and data[too_small_index] 4. While too_small_index > too_big_index, go to 1. 5. Swap data[too_small_index] and data[pivot_index] pivot_index = 0 2 [0] 4 10 12 13 50 [1] [2] [3] [4] [5] too_big_index 57 63 100 [6] [7] [8] too_small_index

1. While data[too_big_index] <= data[pivot_index ] ++too_big_index 2. While data[too_small_index] > data[pivot_index ] --too_small_index

1. While data[too_big_index] <= data[pivot_index ] ++too_big_index 2. While data[too_small_index] > data[pivot_index ] --too_small_index 3. If too_big_index < too_small_index swap data[too_big_index] and data[too_small_index] 4. While too_small_index > too_big_index, go to 1. 5. Swap data[too_small_index] and data[pivot_index] pivot_index = 0 2 [0] 4 10 12 13 50 [1] [2] [3] [4] [5] too_big_index 57 63 100 [6] [7] [8] too_small_index

1. While data[too_big_index] <= data[pivot_index ] ++too_big_index 2. While data[too_small_index] > data[pivot_index ] --too_small_index

1. While data[too_big_index] <= data[pivot_index ] ++too_big_index 2. While data[too_small_index] > data[pivot_index ] --too_small_index 3. If too_big_index < too_small_index swap data[too_big_index] and data[too_small_index] 4. While too_small_index > too_big_index, go to 1. 5. Swap data[too_small_index] and data[pivot_index] pivot_index = 0 2 [0] 4 10 12 13 50 [1] [2] [3] [4] [5] too_big_index 57 63 100 [6] [7] [8] too_small_index

1. While data[too_big_index] <= data[pivot_index ] ++too_big_index 2. While data[too_small_index] > data[pivot_index ] --too_small_index

1. While data[too_big_index] <= data[pivot_index ] ++too_big_index 2. While data[too_small_index] > data[pivot_index ] --too_small_index 3. If too_big_index < too_small_index swap data[too_big_index] and data[too_small_index] 4. While too_small_index > too_big_index, go to 1. 5. Swap data[too_small_index] and data[pivot_index] pivot_index = 0 2 [0] 4 10 12 13 50 [1] [2] [3] [4] [5] too_big_index 57 63 100 [6] [7] [8] too_small_index

1. While data[too_big_index] <= data[pivot_index ] ++too_big_index 2. While data[too_small_index] > data[pivot_index ] --too_small_index

1. While data[too_big_index] <= data[pivot_index ] ++too_big_index 2. While data[too_small_index] > data[pivot_index ] --too_small_index 3. If too_big_index < too_small_index swap data[too_big_index] and data[too_small_index] 4. While too_small_index > too_big_index, go to 1. 5. Swap data[too_small_index] and data[pivot_index] pivot_index = 0 2 [0] 4 10 12 13 50 [1] [2] [3] [4] [5] too_big_index 57 63 100 [6] [7] [8] too_small_index

1. While data[too_big_index] <= data[pivot_index ] ++too_big_index 2. While data[too_small_index] > data[pivot_index ] --too_small_index

1. While data[too_big_index] <= data[pivot_index ] ++too_big_index 2. While data[too_small_index] > data[pivot_index ] --too_small_index 3. If too_big_index < too_small_index swap data[too_big_index] and data[too_small_index] 4. While too_small_index > too_big_index, go to 1. 5. Swap data[too_small_index] and data[pivot_index] pivot_index = 0 2 [0] 4 10 12 13 50 [1] [2] [3] [4] [5] too_big_index 57 63 100 [6] [7] [8] too_small_index

1. While data[too_big_index] <= data[pivot_index ] ++too_big_index 2. While data[too_small_index] > data[pivot_index ] --too_small_index

1. While data[too_big_index] <= data[pivot_index ] ++too_big_index 2. While data[too_small_index] > data[pivot_index ] --too_small_index 3. If too_big_index < too_small_index swap data[too_big_index] and data[too_small_index] 4. While too_small_index > too_big_index, go to 1. 5. Swap data[too_small_index] and data[pivot_index] pivot_index = 0 2 [0] <= data[pivot] 4 10 12 13 50 [1] [2] [3] [4] [5] > data[pivot] 57 63 100 [6] [7] [8]

Improved Pivot Selection Pick median value of three elements from data array: data[0], data[n/2],

Improved Pivot Selection Pick median value of three elements from data array: data[0], data[n/2], and data[n-1]. Use this median value as pivot.