Presentation is loading. Please wait.

Presentation is loading. Please wait.

Quicksort This is probably the most popular sorting algorithm. It was invented by the English Scientist C.A.R. Hoare It is popular because it works well.

Similar presentations


Presentation on theme: "Quicksort This is probably the most popular sorting algorithm. It was invented by the English Scientist C.A.R. Hoare It is popular because it works well."— Presentation transcript:

1 Quicksort This is probably the most popular sorting algorithm. It was invented by the English Scientist C.A.R. Hoare It is popular because it works well in a variety of situations – it is a good general purpose algorithm

2 Quicksort The desirable features are It is in-place (uses only a small stack as auxiliary structure – if recursion is used the stack is implicit) It works in O(n log n) in the average case Drawbacks It is recursive – implementation is complicated without recursion it takes O(n 2 ) in the worst case It is fragile: a simple mistake in the implementation can go unnoticed and can cause it to perform badly

3 A Look at divide-and-conquer Approach Several recursive algorithms work by using recursive calls to sub-problems that are similar to the original but smaller in size Solve the sub-problems recursively And then combine the solution into a solution for the larger instance

4 A Look at divide-and-conquer Approach Divide-and-Conquer approach has three main steps Divide the problem into a number of smaller sub- problems Conquer the sub-problems either by calling the recursion for them or solving them with a straightforward approach if they are small enough Combine the solutions of the sub-problems into the solution for the large (original) problems

5 The Quicksort Idea (Employing Divide-and-Conquer) The basic idea of Quicksort published in 1962 is as follows: 1. Pick one item from the list and call it pivot 2. Partition the items in the list using the pivot. 3. Reorganize the list so that all the elements that are smaller than the pivot are in the left partition and all elements are greater than the pivot are in the right partition. 4. Use recursion to sort the partitions 1. Pick one item from the list and call it pivot 2. Partition the items in the list using the pivot. 3. Reorganize the list so that all the elements that are smaller than the pivot are in the left partition and all elements are greater than the pivot are in the right partition. 4. Use recursion to sort the partitions

6 Partitioning (Quicksort II) A key step in the Quicksort algorithm is partitioning the array We choose some (any) number p in the array to use as a pivot We partition the array into three parts: p numbers less than p numbers greater than or equal to p p

7 The Partition of the List The partition is the crucial part of Quicksort and it must rearrange the list to make the following conditions true after its execution 1. The element chosen as pivot, say list[i], is in its final place in the list 2. All the elements in list[first],...,list[i-1] are less than or equal to list[i] 3. All the elements in list[i+1],...,list[last] are greater than or equal to list[i] 1. The element chosen as pivot, say list[i], is in its final place in the list 2. All the elements in list[first],...,list[i-1] are less than or equal to list[i] 3. All the elements in list[i+1],...,list[last] are greater than or equal to list[i]

8 Quicksort Two phases Partition phase Divides the work into half Sort phase Conquers the halves!

9 Quicksort Partition Choose a pivot Find the position for the pivot so that all elements to the left are less all elements to the right are greater < pivot > pivot pivot

10 Quicksort Conquer Apply the same algorithm to each half < pivot> pivot pivot< p’ p’> p’< p”p”> p”

11 Defining partition() After calling the function quicksort(list, first, last) we expect that the list should look like something as above The split will be assigned the value of the index of the pivot used in the partition function partition 1: all items <= pivot partition 2: all items > pivot first split last

12 Building the partitions In the beginning we don't know which elements should be in partition 1 or 2. Our partition function should therefore assume two "empty" partitions and build them gradually To start with 2 empty partitions we can set lastSmall to be first and i to be first+1 elements yet to be processed first lastSmall i i last

13 Tracing the Partition Function 6 6 4 4 7 7 5 5 1 1 21 2 2 9 9 first(0) i(1) lastSmall(0) If the value at i is less than the pivot advance lastSmall pivot

14 Tracing the Partition Function 6 6 4 4 7 7 5 5 1 1 21 2 2 9 9 first(0) = pivot first(0) = pivot i(1) lastSmall(1) If value at i is less than the pivot advance lastSmall and swap value at I and lastSmall

15 Tracing the Partition Function 6 6 4 4 7 7 5 5 1 1 21 2 2 9 9 first(0) i(1) lastSmall(1) If value at i is less than the pivot advance lastSmall and swap value at i and lastSmall - so swap 4 with itself first(0) = pivot first(0) = pivot

16 Tracing the Partition Function 6 6 4 4 7 7 5 5 1 1 21 2 2 9 9 first(0) i(2) lastSmall(1) If value at i is greater than the pivot: Do nothing

17 Tracing the Partition Function 6 6 4 4 7 7 5 5 1 1 21 2 2 9 9 first(0) i(3) lastSmall(1) If value at i is less than the pivot advance lastSmall and swap i and lastSmall

18 Tracing the Partition Function 6 6 4 4 7 7 5 5 1 1 21 2 2 9 9 first(0) i(3) lastSmall(2) If value at i is less than the pivot advance lastSmall and swap i and lastSmall

19 Tracing the Partition Function 6 6 4 4 5 5 7 7 1 1 21 2 2 9 9 first(0) i(3) lastSmall(2) If value at i is less than the pivot advance lastSmall and swap i and lastSmall. Swap 5 and 7

20 Tracing the Partition Function 6 6 4 4 5 5 7 7 1 1 21 2 2 9 9 first(0) i(4) lastSmall(2)

21 Tracing the Partition Function 6 6 4 4 5 5 7 7 1 1 21 2 2 9 9 first(0) i(4) lastSmall(3) If value at i is less than the pivot advance lastSmall and swap i and lastSmall. Swap 1 and 7

22 Tracing the Partition Function 6 6 4 4 5 5 1 1 7 7 21 2 2 9 9 first(0) i(4) lastSmall(3)

23 Tracing the Partition Function 6 6 4 4 5 5 1 1 7 7 21 2 2 9 9 first(0) i(5) lastSmall(3) If value at I is not less than the pivot do nothing – advance i

24 Tracing the Partition Function 6 6 4 4 5 5 1 1 7 7 21 2 2 9 9 first(0) i(6) lastSmall(3) If value at i is less than the pivot advance lastSmall and swap i and lastSmall

25 Tracing the Partition Function 6 6 4 4 5 5 1 1 7 7 21 2 2 9 9 first(0) i(6) lastSmall(4) If value at i is less than the pivot advance lastSmall and swap i and lastSmall - 2 and 7

26 Tracing the Partition Function 6 6 4 4 5 5 1 1 2 2 21 7 7 9 9 first(0) i(7) lastSmall(4)

27 Tracing the Partition Function 6 6 4 4 5 5 1 1 2 2 21 7 7 9 9 first(0) i(7) lastSmall(4)

28 Tracing the Partition Function 6 6 4 4 5 5 1 1 2 2 21 7 7 9 9 first(0) pivot first(0) pivot lastSmall(4) The final step is to swap the pivot and lastsmall

29 Tracing the Partition Function 2 2 4 4 5 5 1 1 6 6 21 7 7 9 9 first(0) pivot first(0) pivot lastSmall(4) The final step is to swap the pivot and lastsmall and split the array at lastsmall

30 Tracing the Partition Function 2 2 4 4 5 5 1 1 6 6 21 7 7 9 9 Split –(4) The final step is to swap the pivot and lastsmall and split the array at lastsmall

31 Partition function for Quicksort public int partition (int list[], int first, int last) { int lastSmall(first); for (int i=first+1; i<=last; i++) if (list[i] <= list[first]) { ++lastSmall; swap(list,lastSmall,i); } swap(list,first,lastSmall); return lastSmall; }// position of the pivot returned public int partition (int list[], int first, int last) { int lastSmall(first); for (int i=first+1; i<=last; i++) if (list[i] <= list[first]) { ++lastSmall; swap(list,lastSmall,i); } swap(list,first,lastSmall); return lastSmall; }// position of the pivot returned

32 Quicksort(0,3) 2 2 4 4 5 5 1 1 6 6 21 7 7 9 9 split(4) The rest of the sort is done in the next slides for those who would like to trace the whole sort.

33 Quicksort(0,3) 2 2 4 4 5 5 1 1 6 6 21 7 7 9 9 first(0) i(1) lastSmall(0) If value at i is less than the pivot Advance lastSmall and swap i and lastSmall

34 Quicksort(0,3) 2 2 4 4 5 5 1 1 6 6 21 7 7 9 9 first(0) i(2) lastSmall(0)

35 Quicksort(0,3) 2 2 4 4 5 5 1 1 6 6 21 7 7 9 9 first(0) i(3) lastSmall(0) If value at i is less than the pivot advance lastSmall and swap i and lastSmall

36 Quicksort(0,3) 2 2 4 4 5 5 1 1 6 6 21 7 7 9 9 first(0) i(3) lastSmall(1) The 1 is less than lastSmall so we swap the 1 and the 4

37 Quicksort(0,3) 2 2 1 1 5 5 4 4 6 6 21 7 7 9 9 first(0) i(3) lastSmall(1)

38 Quicksort(0,3) 2 2 1 1 5 5 4 4 6 6 21 7 7 9 9 first(0) i(3) lastSmall(1) We have come to the end of the first partition, so lastSmall is the new pivot and we swap first which is 2 and lastSmall (1)

39 Quicksort(0,3) 1 1 2 2 5 5 4 4 6 6 21 7 7 9 9 split(1) We have now split at index 1 and must do the same partition algorithm to the 1(even though there is only one element in the partition)

40 Quicksort(0,0) 1 1 2 2 5 5 4 4 6 6 21 7 7 9 9

41 Quicksort(2,3) 1 1 2 2 5 5 4 4 6 6 21 7 7 9 9 first(2) i(3) lastSmall(2) If value at i is less than the pivot advance lastSmall and swap i and lastSmall

42 Quicksort(2,3) 1 1 2 2 5 5 4 4 6 6 21 7 7 9 9 first(2) i(3) lastSmall(3)

43 Quicksort(2,3) 1 1 2 2 5 5 4 4 6 6 21 7 7 9 9 first(2) i(3) lastSmall(3)

44 Quicksort(2,3) 1 1 2 2 5 5 4 4 6 6 21 7 7 9 9 first(2) lastSmall(3)

45 Quicksort(2,3) 1 1 2 2 4 4 5 5 6 6 21 7 7 9 9 first(2) lastSmall(3) If value at i is less than the pivot advance lastSmall and swap i and lastSmall

46 Quicksort(2,3) 1 1 2 2 4 4 5 5 6 6 21 7 7 9 9 split(3)

47 Quicksort(2,2) 1 1 2 2 4 4 5 5 6 6 21 7 7 9 9

48 Quicksort(4,3) Page 48 1 1 2 2 4 4 5 5 6 6 21 7 7 9 9

49 Quicksort(5,7) 1 1 2 2 4 4 5 5 6 6 21 7 7 9 9 first(5) i(6) lastSmall(5)

50 Quicksort(5,7) 1 1 2 2 4 4 5 5 6 6 21 7 7 9 9 first(5) i(6) lastSmall(6)

51 Quicksort(5,7) 1 1 2 2 4 4 5 5 6 6 21 7 7 9 9 first(5) i(6) lastSmall(6)

52 Quicksort(5,7) 1 1 2 2 4 4 5 5 6 6 21 7 7 9 9 first(5) i(7) lastSmall(6)

53 Quicksort(5,7) 1 1 2 2 4 4 5 5 6 6 21 7 7 9 9 first(5) i(7) lastSmall(7)

54 Quicksort(5,7) 1 1 2 2 4 4 5 5 6 6 21 7 7 9 9 first(5) i(7) lastSmall(7)

55 Quicksort(5,7) 1 1 2 2 4 4 5 5 6 6 21 7 7 9 9 first(5) lastSmall(6)

56 Quicksort(5,7) 1 1 2 2 4 4 5 5 6 6 9 9 7 7 21 first(5) lastSmall(7)

57 Quicksort(5,7) 1 1 2 2 4 4 5 5 6 6 9 9 7 7 21 split(7)

58 Quicksort(5,6) 1 1 2 2 4 4 5 5 6 6 9 9 7 7 21 first(5) i(6) lastSmall(5)

59 Quicksort(5,6) 1 1 2 2 4 4 5 5 6 6 9 9 7 7 21 first(5) i(6) lastSmall(6)

60 Quicksort(5,6) 1 1 2 2 4 4 5 5 6 6 9 9 7 7 21 first(5) i(6) lastSmall(6)

61 Quicksort(5,6) 1 1 2 2 4 4 5 5 6 6 9 9 7 7 21 first(5) lastSmall(6)

62 Quicksort(5,6) 1 1 2 2 4 4 5 5 6 6 7 7 9 9 21 first(5) lastSmall(6)

63 Quicksort(5,6) 1 1 2 2 4 4 5 5 6 6 7 7 9 9 21 split(6)

64 Quicksort(5,5) 1 1 2 2 4 4 5 5 6 6 7 7 9 9 21

65 Quicksort(7,6) 1 1 2 2 4 4 5 5 6 6 7 7 9 9 21

66 Quicksort(8,7) 1 1 2 2 4 4 5 5 6 6 7 7 9 9 21

67 Quicksort(8,7) 1 1 2 2 4 4 5 5 6 6 7 7 9 9 21

68 public static void quickSort(Integer a[], int first, int last) { // PreCondtion: in an array to be sorted from //a[first]..a[last] if (first >= last) return; // PostCondition: we have an empty array or all //partitions have completed // call method to do the partition int split = partition(a, first, last); quickSort(a, first, split - 1); // recursive sort left quickSort(a, split + 1, last); // recursive sort right // post condition: a is sorted }

69 private static int partition(Integer a[], int first, int last) { int lastSmall = first; // place lastmall at index 0 for (int i = first + 1; i <= last; i++) { // if element in i is less than pivot if (a[i].compareTo(a[first]) <= 0) { lastSmall++; // increment last small and call swap swapElements(a, lastSmall, i); } } // put pivot in proper position swapElements(a, first, lastSmall); return lastSmall; }

70 Quicksort - Analysis Partition Check every item onceO(n) Conquer Divide data in halfO(log 2 n) Total ProductO(n log n) Same as Heapsort quicksort is generally faster Fewer comparisons Details later But there’s a catch …………….

71 Quicksort - The truth! What happens if we use quicksort on data that’s already sorted (or nearly sorted) We’d certainly expect it to perform well!

72 Quicksort - The truth! Sorted data 123456789 pivot < pivot ? > pivot

73 Quicksort - The truth! Sorted data Each partition produces a problem of size 0 and one of size n-1! Number of partitions? 123456789 > pivot 23456789 pivot

74 Quicksort - The truth! Sorted data Each partition produces a problem of size 0 and one of size n-1! Number of partitions? n each needing time O(n) Total nO(n) or O(n 2 ) ? Quicksort is as bad as bubble or insertion sort 123456789 > pivot 23456789 pivot

75 Best case Analysis of Quicksort Page 75 The best thing that could happen to quicksort is if the pivot divides the list exactly in two halves each time (as below) 4 4 1 1 3 3 2 2 6 6 5 5 7 7 2 2 1 1 3 3 4 4 6 6 5 5 7n 7n 7n 7n 1 1 2 2 3 3 5 5 6 6 7 n-1 1 1 3 3 5 5 7 n-3

76 Quicksort - The truth!  Quicksort’s O(n log n) behaviour  Depends on the partitions being nearly equal  there are O( log n ) of them  On average, this will nearly be the case  and quicksort is generally O(n log n)  Can we do anything to ensure O(n log n) time?  In general, no But we can improve our chances!!

77 Quicksort - Choice of the pivot Any pivot will work … Choose a different pivot … so that the partitions are equal then we will see O(n log n) time 123456789 pivot < pivot > pivot

78 Quicksort - Median-of-3 pivot Take 3 positions and choose the median say … First, middle, last median is 5 perfect division of sorted data every time! O(n log n) time çSince sorted (or nearly sorted) data is common, median-of-3 is a good strategy especially if you think your data may be sorted! 123456789

79 Quicksort - Random pivot Choose a pivot randomly Different position for every partition ç On average, sorted data is divided evenly ç O(n log n) time Key requirement Pivot choice must take O(1) time

80 Quicksort - Guaranteed O(n log n)? Never Guaranteed!! Any pivot selection strategy could lead to O(n 2 ) time Here median-of-3 chooses 2 One partition of 1 and One partition of 7 Next it chooses 4 One of 1 and One of 5 149625783 124965783

81 Worst case for quicksort In the worst case, recursion may be n levels deep (for an array of size n ) But the partitioning work done at each level is still n O(n) * O(n) = O(n 2 ) So worst case for Quicksort is O(n 2 ) When does this happen? When the array is sorted to begin with!

82 Final comments Quicksort is the fastest known sorting algorithm For optimum efficiency, the pivot must be chosen carefully “Median of three” is a good technique for choosing the pivot However, no matter what you do, there will be some cases where Quicksort runs in O(n 2 ) time

83 The recurrence for quicksort (assuming we're successful in always dividing the list in two parts of equal size) gives us a function that it is equivalent to O(n log n) FOR THE AVERAGE CASE AVERAGE CASE

84 http://www.sorting-algorithms.com/ We examine sorting algorithms on 4 different initial conditions. These visualizations are intended to: Show how each algorithm operates. Show that there is no best sorting algorithm. Show the advantages and disadvantages of each algorithm. Show that worse-case asymptotic behavior is not the deciding factor in choosing an algorithm. Show that the initial condition (input order and key distribution) affects performance as much as the algorithm choice. The ideal sorting algorithm would have the following properties: Stable: Equal keys aren't reordered. Operates in place, requiring O(1) extra space. Worst-case O(n·lg(n)) key comparisons. Worst-case O(n) swaps. Adaptive: Speeds up to O(n) when data is nearly sorted or when there are few unique keys. There is no algorithm that has all of these properties, and so the choice of sorting algorithm depends on the application.


Download ppt "Quicksort This is probably the most popular sorting algorithm. It was invented by the English Scientist C.A.R. Hoare It is popular because it works well."

Similar presentations


Ads by Google