1 CSCD 326 Data Structures I Sorting. 2 Quicksort Overview A recursive sorting algorithm which...

31
1 CSCD 326 Data Structures I Sorting
  • date post

    21-Dec-2015
  • Category

    Documents

  • view

    226
  • download

    0

Transcript of 1 CSCD 326 Data Structures I Sorting. 2 Quicksort Overview A recursive sorting algorithm which...

Page 1: 1 CSCD 326 Data Structures I Sorting. 2 Quicksort Overview A recursive sorting algorithm which divides an array into two smaller partitions. All small.

1

CSCD 326 Data Structures ISorting

Page 2: 1 CSCD 326 Data Structures I Sorting. 2 Quicksort Overview A recursive sorting algorithm which divides an array into two smaller partitions. All small.

2

Quicksort

Overview

A recursive sorting algorithm which divides an array into two smaller partitions.

All small elements in one partition and large elements in another

Calls itself recursively with each partition - a divide and conquer algorithm

Requires use of an array since random access is necessary.

Page 3: 1 CSCD 326 Data Structures I Sorting. 2 Quicksort Overview A recursive sorting algorithm which divides an array into two smaller partitions. All small.

3

Quicksort

Partitioning Scheme

Choose the median element in the array as the "pivot" element (ideally).

All elements smaller than the pivot go into the part of the array below the pivot.

All elements larger than the pivot go into the part of the array above the pivot.

Page 4: 1 CSCD 326 Data Structures I Sorting. 2 Quicksort Overview A recursive sorting algorithm which divides an array into two smaller partitions. All small.

4

Quicksort

Choosing the "pivot":

Finding the true median element is more time consuming than quicksort itself so -

Choose (guess) the pivot element quickly.

Commonly used methods are to choose the first or the middle element as pivot.

More on pivot choosing in the analysis section.

Page 5: 1 CSCD 326 Data Structures I Sorting. 2 Quicksort Overview A recursive sorting algorithm which divides an array into two smaller partitions. All small.

5

Partition Method

private static int partition(Comparable[] theArray, int first, int last) {// ---------------------------------------------------------// Partitions an array for quicksort.// Precondition: theArray[first..last] is an array; first <= last.// Postcondition: Returns the index of the pivot element of theArray [first..last].// Upon completion of the method, this will be the index value lastS1 such that// S1 = theArray[first..lastS1-1] < pivot// theArray[lastS1] == pivot// S2 = theArray[lastS1+1..last] >= pivot// Calls: choosePivot.// --------------------------------------------------------- // tempItem is used to swap elements in the array Comparable tempItem; // place pivot in theArray[first] // choosePivot(theArray, first, last); Comparable pivot = theArray[first]; // reference pivot

// initially, everything but pivot is in unknown int lastS1 = first; // index of last item in S1

Page 6: 1 CSCD 326 Data Structures I Sorting. 2 Quicksort Overview A recursive sorting algorithm which divides an array into two smaller partitions. All small.

6

Partition Method (2) // move one item at a time until unknown region is empty for (int firstUnknown = first + 1; firstUnknown <= last; ++firstUnknown) { // Invariant: theArray[first+1..lastS1] < pivot // theArray[lastS1+1..firstUnknown-1] >= pivot

// move item from unknown to proper region if (theArray[firstUnknown].compareTo(pivot) < 0) { // item from unknown belongs in S1 ++lastS1; tempItem = theArray[firstUnknown]; theArray[firstUnknown] = theArray[lastS1]; theArray[lastS1] = tempItem; } // end if // else item from unknown belongs in S2 } // end for // place pivot in proper position and mark its location tempItem = theArray[first]; theArray[first] = theArray[lastS1]; theArray[lastS1] = tempItem; return lastS1;} // end partition

Page 7: 1 CSCD 326 Data Structures I Sorting. 2 Quicksort Overview A recursive sorting algorithm which divides an array into two smaller partitions. All small.

7

Partition Trace

9 15 13 20 5 0 7 10 3 2[0] [1] [2] [3] [4] [5] [6] [7] [8] [9]firstUnknown = 1

lastS1 = 0

S1 S2 Unknown firstUnknownlastS1

9pivot

9 15 13 20 5 0 7 10 3 2[0] [1] [2] [3] [4] [5] [6] [7] [8] [9]firstUnknown = 2

lastS1 = 0

9 15 13 20 5 0 7 10 3 2[0] [1] [2] [3] [4] [5] [6] [7] [8] [9]firstUnknown = 3

lastS1 = 0

9 15 13 20 5 0 7 10 3 2[0] [1] [2] [3] [4] [5] [6] [7] [8] [9]firstUnknown = 4

lastS1 = 0

9 5 13 20 15 0 7 10 3 2[0] [1] [2] [3] [4] [5] [6] [7] [8] [9]firstUnknown = 5

lastS1 = 1

Page 8: 1 CSCD 326 Data Structures I Sorting. 2 Quicksort Overview A recursive sorting algorithm which divides an array into two smaller partitions. All small.

8

Partition Trace (2)

[0] [1] [2] [3] [4] [5] [6] [7] [8] [9]firstUnknown = 6

S1 S2 Unknown firstUnknownlastS1

9pivot

[0] [1] [2] [3] [4] [5] [6] [7] [8] [9]firstUnknown = 7lastS1 = 3

[0] [1] [2] [3] [4] [5] [6] [7] [8] [9]firstUnknown = 8lastS1 = 3

[0] [1] [2] [3] [4] [5] [6] [7] [8] [9]firstUnknown = 9lastS1 = 4

[0] [1] [2] [3] [4] [5] [6] [7] [8] [9]State uponloop exit

9 5 0 20 15 13 7 10 3 2lastS1 = 2

9 5 0 7 15 13 20 10 3 2

9 5 0 7 15 13 20 10 3 2

9 5 0 7 3 13 20 10 15 2

9 5 0 7 3 2 20 10 15 13

Page 9: 1 CSCD 326 Data Structures I Sorting. 2 Quicksort Overview A recursive sorting algorithm which divides an array into two smaller partitions. All small.

9

Partition Trace (3)

[0] [1] [2] [3] [4] [5] [6] [7] [8] [9]final state 2 5 0 7 3 9 20 10 15 13

lastS1 (5) returned from partition

Page 10: 1 CSCD 326 Data Structures I Sorting. 2 Quicksort Overview A recursive sorting algorithm which divides an array into two smaller partitions. All small.

10

Quicksort Method

void quickSort( Comparable [] array, int first, int last){ if (first < last) { //move small stuff left, big stuff right, return // index of pivot value //NOTE: pivot value is in final resting place int pivotIndex = partition(array, first, last); //sort left side of array quickSort(array, first, pivotIndex – 1); //sort right side of array quickSort(array, pivotIndex + 1, last); } //end if} //end quickSort method

Page 11: 1 CSCD 326 Data Structures I Sorting. 2 Quicksort Overview A recursive sorting algorithm which divides an array into two smaller partitions. All small.

11

Quicksort Trace

9 15 13 20 5 0 7 10 3 2[0] [1] [2] [3] [4] [5] [6] [7] [8] [9]

Original Array

2 5 0 7 3 9 20 10 15 13[0] [1] [2] [3] [4] [5] [6] [7] [8] [9]

first = 0 last = 9pivot = 5

0 2 5 7 3 9 20 10 15 13

[0] [1] [2] [3] [4] [5] [6] [7] [8] [9]

0 2 3 5 7 9 20 10 15 13

[0] [1] [2] [3] [4] [5] [6] [7] [8] [9]

first = 0 last = 4pivot = 1

first = 2 last = 4pivot = 3

0 2 3 5 7 9 13 10 15 20[0] [1] [2] [3] [4] [5] [6] [7] [8] [9]first = 6 last = 9

pivot = 9

0 2 3 5 7 9 10 13 15 20first = 6 last = 8pivot = 7

[0] [1] [2] [3] [4] [5] [6] [7] [8] [9]

Page 12: 1 CSCD 326 Data Structures I Sorting. 2 Quicksort Overview A recursive sorting algorithm which divides an array into two smaller partitions. All small.

12

Quicksort Analysis

Best Case Assumptions:

All array elements are in random order.

We can choose a perfect median value.

thus the array is cut exactly in half on each recursive call.

Partition takes O(n) time since the loop runs from the second to the last element.

for (int firstUnknown = first + 1; firstUnknown <= last; ++firstUnknown)

Page 13: 1 CSCD 326 Data Structures I Sorting. 2 Quicksort Overview A recursive sorting algorithm which divides an array into two smaller partitions. All small.

13

Quicksort Analysis (2)

Determine the total number of calls to quickSort.

A call to quicksort with an array partition size (n) of 1 (first == last) generates no further recursive calls.

Each call to quicksort cuts the array size in half so partition deals with 1/2 the previous number of elements.

n = 8

n = 4n = 4

n = 2n = 2

n = 1 n = 1 n = 1 n = 1 n = 1 n = 1 n = 1 n = 1

n = 2 n = 2

Page 14: 1 CSCD 326 Data Structures I Sorting. 2 Quicksort Overview A recursive sorting algorithm which divides an array into two smaller partitions. All small.

14

Quicksort Analysis (3)

Find the growth rate function f(n):

On each level of this tree the partition call(s) deal with a sum total of n elements.

So the question becomes: how many levels are there in the tree?

Since the number of elements is cut in half on each level there are log2n + 1 levels.

So f(n) = n ( log2n + 1 ) = n log2n + n

The time complexity of quickSort is O(nlog2n)

Page 15: 1 CSCD 326 Data Structures I Sorting. 2 Quicksort Overview A recursive sorting algorithm which divides an array into two smaller partitions. All small.

15

Quicksort Analysis (4)

Worst case:

data is already sorted. the first (rather than middle) element is chosen as the pivot.only one element (the first) gets partitioned offeach call to partition has to deal with one less element and there are n recursive callsf(n) = n + (n-1) + (n-2) + (n-3) + . . .+ 1 = n(n+1)/2 = n2/2 + n/2The time complexity becomes O(n2) which is the same as bubblesort or insertion sort.

Page 16: 1 CSCD 326 Data Structures I Sorting. 2 Quicksort Overview A recursive sorting algorithm which divides an array into two smaller partitions. All small.

16

Quicksort Analysis (4)

Worst case:

Insertion sort has a time complexity which approaches O(n) for nearly sorted (or small arrays) while quicksort approaches O(n2)

Thus, insertion sort is better than quicksort for small or nearly sorted arrays.

A variation on quicksort uses the best qualities of both quicksort and insertion sort.

It uses quicksort down to a partition size of 10 and then finishes with insertion sort.

Page 17: 1 CSCD 326 Data Structures I Sorting. 2 Quicksort Overview A recursive sorting algorithm which divides an array into two smaller partitions. All small.

17

Quicksort - improving worst case

Better median candidate choices (for method choosePivot()) -- find the middle value of first, middle, and last element of the array and place it at the beginning of the array:

int Middle = (Low+High)/2;If(theArray[ Middle ] < theArray[ Low ]) Swap( theArray[ Low ], theArray[ Middle]);if( theArray[ High ] < theArray[ Low ] ) Swap( theArray[ Low ], theArray[ High ] );if( theArray[ High ] < theArray[ Middle ] ) Swap( theArray[ Middle ], theArray[ High ] );

Page 18: 1 CSCD 326 Data Structures I Sorting. 2 Quicksort Overview A recursive sorting algorithm which divides an array into two smaller partitions. All small.

18

Merge Sort

Based on the idea of merging two already sorted lists:

The first items in each list are compared - the smaller is added to output list and replaced by next input item from the same list.When one list is empty all remaining items in the other list are added to output.Can be done with disk files when insufficient memory is available for a memory sort ORCan serve as the basis for a divide and conquer recursive sorting algorithm with O(nlog2n) time complexity.

Page 19: 1 CSCD 326 Data Structures I Sorting. 2 Quicksort Overview A recursive sorting algorithm which divides an array into two smaller partitions. All small.

19

Merge Sort - General Description

Recursively divide list in half until each piece is of size one:

then merge adjacent one element lists into a sorted two element list.

each sorted part is merged with adjacent parts to give a larger sorted list.

eventually the final two pieces are merged to give a sorted version of the original list.

Page 20: 1 CSCD 326 Data Structures I Sorting. 2 Quicksort Overview A recursive sorting algorithm which divides an array into two smaller partitions. All small.

20

merge - methodprivate static void merge(Comparable[ ] theArray, int first, int mid, int last) {// ---------------------------------------------------------// Merges two sorted array segments theArray[first..mid] and // theArray[mid+1..last] into one sorted array.// Precondition: first <= mid <= last. The subarrays theArray[first..mid] and // theArray[mid+1..last] are each sorted in increasing order.// Postcondition: theArray[first..last] is sorted.// Implementation note: This method merges the two subarrays into a temporary array // and copies the result into the original array anArray.// --------------------------------------------------------- int maxSize = theArray.length; // temporary array Comparable[ ] tempArray = new Comparable[maxSize];

// initialize the local indexes to indicate the subarrays int first1 = first; // beginning of first subarray int last1 = mid; // end of first subarray int first2 = mid + 1; // beginning of second subarray int last2 = last; // end of second subarray

Page 21: 1 CSCD 326 Data Structures I Sorting. 2 Quicksort Overview A recursive sorting algorithm which divides an array into two smaller partitions. All small.

21

merge - method (2) // while both subarrays are not empty, copy the // smaller item into the temporary array int index = first1; // next available location in tempArray while ((first1 <= last1) && (first2 <= last2)) { // Invariant: tempArray[first1..index-1] is in order if (theArray[first1].compareTo(theArray[first2])<0) { tempArray[index] = theArray[first1]; first1++; } else { tempArray[index] = theArray[first2]; first2++; } // end if index++; } // end while

Page 22: 1 CSCD 326 Data Structures I Sorting. 2 Quicksort Overview A recursive sorting algorithm which divides an array into two smaller partitions. All small.

22

merge - method (3) // finish off the nonempty subarray // finish off the first subarray, if necessary while (first1 <= last1) { // Invariant: tempArray[first1..index-1] is in order tempArray[index] = theArray[first1]; first1++; index++; } // end while

// finish off the second subarray, if necessary while (first2 <= last2) { // Invariant: tempArray[first1..index-1] is in order tempArray[index] = theArray[first2]; first2++; index++; } // end while

// copy the result back into the original array for (index = first; index <= last; ++index) { theArray[index] = tempArray[index]; } // end for} // end merge

Page 23: 1 CSCD 326 Data Structures I Sorting. 2 Quicksort Overview A recursive sorting algorithm which divides an array into two smaller partitions. All small.

23

mergeSort -methodpublic static void mergeSort(Comparable[ ] theArray, int first, int last) {// ---------------------------------------------------------// Sorts the items in an array into ascending order. // Precondition: theArray[first..last] is an array.// Postcondition: theArray[first..last] is sorted in ascending order.// Calls: merge.// --------------------------------------------------------- if (first < last) { // sort each half int mid = (first + last)/2; // index of midpoint // sort left half theArray[first..mid] mergeSort(theArray, first, mid); // sort right half theArray[mid+1..last] mergeSort(theArray, mid+1, last); // merge the two halves merge(theArray, first, mid, last); } // end if} // end mergesort

Page 24: 1 CSCD 326 Data Structures I Sorting. 2 Quicksort Overview A recursive sorting algorithm which divides an array into two smaller partitions. All small.

24

mergeSort -methodpublic static void mergeSort(Comparable[ ] theArray, int first, int last) {// ---------------------------------------------------------// Sorts the items in an array into ascending order. // Precondition: theArray[first..last] is an array.// Postcondition: theArray[first..last] is sorted in ascending order.// Calls: merge.// --------------------------------------------------------- if (first < last) { // sort each half int mid = (first + last)/2; // index of midpoint // sort left half theArray[first..mid] mergeSort(theArray, first, mid); // sort right half theArray[mid+1..last] mergeSort(theArray, mid+1, last); // merge the two halves merge(theArray, first, mid, last); } // end if} // end mergesort

Page 25: 1 CSCD 326 Data Structures I Sorting. 2 Quicksort Overview A recursive sorting algorithm which divides an array into two smaller partitions. All small.

25

mergeSort -driver

public static void main(String[ ] args) { Integer[ ] values = new Integer[10]; values[0] = new Integer(9); values[1] = new Integer(15); values[2] = new Integer(13); values[3] = new Integer(20); values[4] = new Integer(5); values[5] = new Integer(0); values[6] = new Integer(7); values[7] = new Integer(10); values[8] = new Integer(3); values[9] = new Integer(2); mergeSort(values, 0, values.length -1);}

Page 26: 1 CSCD 326 Data Structures I Sorting. 2 Quicksort Overview A recursive sorting algorithm which divides an array into two smaller partitions. All small.

26

mergeSort Trace

9 15 13 20 5 0 7 10 3 2[0] [1] [2] [3] [4] [5] [6] [7] [8] [9]

Original arraymergeSort 0 to 9

9 15 13 20 5 0 7 10 3 2[0] [1] [2] [3] [4] [5] [6] [7] [8] [9]

mergeSort 0 to 4

9 15 13 20 5 0 7 10 3 2[0] [1] [2] [3] [4] [5] [6] [7] [8] [9]

mergeSort 0 to 2

9 15 13 20 5 0 7 10 3 2[0] [1] [2] [3] [4] [5] [6] [7] [8] [9]

mergeSort 0 to 1

[0] [1] [2] [3] [4] [5] [6] [7] [8] [9][0] [1] [2] [3] [4] [5] [6] [7] [8] [9]

9 15 13 20 5 0 7 10 3 2merge0-0 with 1- 1

terminal calls: mergeSort 0 to 0 and mergeSort 1 to 1

terminal call: mergeSort 2 to 2

merge0-1 with 2- 2

[0] [1] [2] [3] [4] [5] [6] [7] [8] [9][0] [1] [2] [3] [4] [5] [6] [7] [8] [9]

9 13 15 20 5 0 7 10 3 2

Page 27: 1 CSCD 326 Data Structures I Sorting. 2 Quicksort Overview A recursive sorting algorithm which divides an array into two smaller partitions. All small.

27

mergeSort - trace (2)

mergeSort 3 to 4[0] [1] [2] [3] [4] [5] [6] [7] [8] [9][0] [1] [2] [3] [4] [5] [6] [7] [8] [9]

9 13 15 20 5 0 7 10 3 2

[0] [1] [2] [3] [4] [5] [6] [7] [8] [9][0] [1] [2] [3] [4] [5] [6] [7] [8] [9]

9 13 15 5 20 0 7 10 3 2

terminal calls: mergeSort 3 to 3 and mergeSort 4 to 4merge3-3 with 4- 4

[0] [1] [2] [3] [4] [5] [6] [7] [8] [9][0] [1] [2] [3] [4] [5] [6] [7] [8] [9]

5 9 13 15 20 0 7 10 3 2merge0-2 with 3- 4

mergeSort 5 to 9[0] [1] [2] [3] [4] [5] [6] [7] [8] [9][0] [1] [2] [3] [4] [5] [6] [7] [8] [9]

5 9 13 15 20 0 7 10 3 2

mergeSort 5 to 7[0] [1] [2] [3] [4] [5] [6] [7] [8] [9][0] [1] [2] [3] [4] [5] [6] [7] [8] [9]

5 9 13 15 20 0 7 10 3 2

mergeSort 5 to 6[0] [1] [2] [3] [4] [5] [6] [7] [8] [9][0] [1] [2] [3] [4] [5] [6] [7] [8] [9]

5 9 13 15 20 0 7 10 3 2

terminal calls: mergeSort 5 to 5 and mergeSort 6 to 6

Page 28: 1 CSCD 326 Data Structures I Sorting. 2 Quicksort Overview A recursive sorting algorithm which divides an array into two smaller partitions. All small.

28

mergeSort - trace (3)[0] [1] [2] [3] [4] [5] [6] [7] [8] [9][0] [1] [2] [3] [4] [5] [6] [7] [8] [9]

5 9 13 15 20 0 7 10 3 2merge5-5 with 6- 6

terminal call: mergeSort 7 to 7[0] [1] [2] [3] [4] [5] [6] [7] [8] [9][0] [1] [2] [3] [4] [5] [6] [7] [8] [9]

5 9 13 15 20 0 7 10 3 2merge5-6 with 7- 7

[0] [1] [2] [3] [4] [5] [6] [7] [8] [9][0] [1] [2] [3] [4] [5] [6] [7] [8] [9]

5 9 13 15 20 0 7 10 3 2mergeSort 8 to 9

terminal calls: mergeSort 8 to 8 and mergeSort 9 to 9[0] [1] [2] [3] [4] [5] [6] [7] [8] [9][0] [1] [2] [3] [4] [5] [6] [7] [8] [9]

5 9 13 15 20 0 7 10 2 3merge8-8 with 9- 9

[0] [1] [2] [3] [4] [5] [6] [7] [8] [9][0] [1] [2] [3] [4] [5] [6] [7] [8] [9]

5 9 13 15 20 0 2 3 7 10merge5-7 with 8- 9

[0] [1] [2] [3] [4] [5] [6] [7] [8] [9][0] [1] [2] [3] [4] [5] [6] [7] [8] [9]

0 2 3 5 7 9 10 13 15 20merge0-4 with 5- 9

Page 29: 1 CSCD 326 Data Structures I Sorting. 2 Quicksort Overview A recursive sorting algorithm which divides an array into two smaller partitions. All small.

29

Mergesort - Queue based

Data elements to be merged will be kept in linked lists rather than in arrays

Each data element is initially placed in a one node linked list

A Queue of these one node lists is built

Process:

The first two lists are removed from the queue, merged, and the merged list added to the queue.

When the queue contains only a single list (the product of the final merge) - the entire list is sorted.

Page 30: 1 CSCD 326 Data Structures I Sorting. 2 Quicksort Overview A recursive sorting algorithm which divides an array into two smaller partitions. All small.

30

Q-based MergeSort algorithm

Algorithm Pseudocode:break entire list into one element linked lists

enqueue each one onto the list Queue(listQ)

repeat

list1 = ListQ.dequeue( )

list2 = ListQ.dequeue( )

NewList = Merge( List1, List2 )

ListQ.enqueue( NewList )

until only one list remains on the ListQ

Page 31: 1 CSCD 326 Data Structures I Sorting. 2 Quicksort Overview A recursive sorting algorithm which divides an array into two smaller partitions. All small.

31

Q-Based MergeSort -trace

ListQ - start

B 0

X 0

A 0

F 0

ListQ - step 1

X 0A

B 0

F 0

ListQ - step 2

F 0

X 0A

B

X 0A B F

ListQ - final