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

Slides:



Advertisements
Similar presentations
Algorithms Analysis Lecture 6 Quicksort. Quick Sort Divide and Conquer.
Advertisements

Analysis of Algorithms CS 477/677 Instructor: Monica Nicolescu Lecture 6.
Quicksort Quicksort     29  9.
Analysis of Quicksort. Quicksort Algorithm Given an array of n elements (e.g., integers): If array only contains one element, return Else –pick one element.
QuickSort The content for these slides was originally created by Gerard Harrison. Ported to C# by Mike Panitz.
Sorting Algorithms and Average Case Time Complexity
Updated QuickSort Problem From a given set of n integers, find the missing integer from 0 to n using O(n) queries of type: “what is bit[j]
Introduction to Algorithms Rabie A. Ramadan rabieramadan.org 4 Some of the sides are exported from different sources.
Quicksort Divide-and-Conquer. Quicksort Algorithm Given an array S of n elements (e.g., integers): If array only contains one element, return it. Else.
Sorting Chapter 9.
Fundamentals of Algorithms MCS - 2 Lecture # 16. Quick Sort.
Sorting21 Recursive sorting algorithms Oh no, not again!
General Computer Science for Engineers CISC 106 James Atlas Computer and Information Sciences 10/23/2009.
Quicksort. 2 Introduction * Fastest known sorting algorithm in practice * Average case: O(N log N) * Worst case: O(N 2 ) n But, the worst case seldom.
Quicksort.
Quicksort.
S: Application of quicksort on an array of ints: partitioning.
Mergesort and Quicksort Chapter 8 Kruse and Ryba.
Recursive Quicksort Data Structures in Java with JUnit ©Rick Mercer.
Sorting. Introduction Common problem: sort a list of values, starting from lowest to highest. List of exam scores Words of dictionary in alphabetical.
Computer Science 101 Fast Searching and Sorting. Improving Efficiency We got a better best case by tweaking the selection sort and the bubble sort We.
Order Statistics. Order statistics Given an input of n values and an integer i, we wish to find the i’th largest value. There are i-1 elements smaller.
Examples of Recursion Data Structures in Java with JUnit ©Rick Mercer.
Sorting part 2 Dr. Bernard Chen Ph.D. University of Central Arkansas Fall 2008.
Divide-and-Conquer The most-well known algorithm design strategy: 1. Divide instance of problem into two or more smaller instances 2.Solve smaller instances.
Lecture No. 04,05 Sorting.  A process that organizes a collection of data into either ascending or descending order.  Can be used as a first step for.
Computer Science 101 Fast Algorithms. What Is Really Fast? n O(log 2 n) O(n) O(n 2 )O(2 n )
Quicksort Data Structures and Algorithms CS 244 Brent M. Dingle, Ph.D. Game Design and Development Program Department of Mathematics, Statistics, and Computer.
Sorting divide and conquer. Divide-and-conquer  a recursive design technique  solve small problem directly  divide large problem into two subproblems,
Review 1 Insertion Sort Insertion Sort Algorithm Time Complexity Best case Average case Worst case Examples.
Nothing is particularly hard if you divide it into small jobs. Henry Ford Nothing is particularly hard if you divide it into small jobs. Henry Ford.
Quicksort Quicksort is a well-known sorting algorithm that, in the worst case, it makes Θ(n 2 ) comparisons. Typically, quicksort is significantly faster.
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.
Sorting part 2 Dr. Bernard Chen Ph.D. University of Central Arkansas Fall 2008.
Concepts of Algorithms CSC-244 Unit 17 & 18 Divide-and-conquer Algorithms Quick Sort Shahid Iqbal Lone Computer College Qassim University K.S.A.
Computer Sciences Department1. Sorting algorithm 4 Computer Sciences Department3.
Algorithm Design Techniques, Greedy Method – Knapsack Problem, Job Sequencing, Divide and Conquer Method – Quick Sort, Finding Maximum and Minimum, Dynamic.
Sorting.
CSCI 104 Sorting Algorithms
Sorting Chapter 13 presents several common algorithms for sorting an array of integers. Two slow but simple algorithms are Selectionsort and Insertionsort.
Data Structures in Java with JUnit ©Rick Mercer
Quicksort
Chapter 7 Sorting Spring 14
Quicksort "There's nothing in your head the sorting hat can't see. So try me on and I will tell you where you ought to be." -The Sorting Hat, Harry Potter.
Divide and Conquer – and an Example QuickSort
Quicksort 1.
Sorting Chapter 13 Nyhoff, ADTs, Data Structures and Problem Solving with C++, Second Edition, © 2005 Pearson Education, Inc. All rights reserved
Quicksort and Mergesort
CSS 342 Data Structures, Algorithms, and Discrete Mathematics I
Chapter 4: Divide and Conquer
Quick Sort (11.2) CSE 2011 Winter November 2018.
Unit-2 Divide and Conquer
Outline In this topic we will look at quicksort:
Subject Name : Data Structure Using C Unit Title : Sorting Methods
QuickSort Previous slides based on ones by Ethan Apter & Marty Stepp
Sub-Quadratic Sorting Algorithms
Sorting Chapter 13 presents several common algorithms for sorting an array of integers. Two slow but simple algorithms are Selectionsort and Insertionsort.
Chapter 4.

Quicksort.
Algorithms CSCI 235, Spring 2019 Lecture 20 Order Statistics II
Quicksort.
Sorting.
Recursive Algorithms 1 Building a Ruler: drawRuler()
CSE 332: Parallel Algorithms
Design and Analysis of Algorithms
Quicksort.
Data Structures and Algorithms CS 244
Chapter 11 Sets, and Selection
Presentation transcript:

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

Quicksort Example 2

Quicksort void quicksort(int list[],int start,int end) { int pivot,i,j,k, newPos; if( start < end) { k = (start+end)/2; swap (&list[start], &list[k]) pivot = list[start]; //il pivot è l'elemento centrale i = start; j = end; newPos = start; while(i <= j) { if (list[i] <= pivot){ newPos++; swap(&list[i], &list[newPos]); } i++;} list[start] = list [newPos]; list[newPos] = pivot; quicksort(list,m,j-1); quicksort(list,j+1,end); } Initial call: qsort(A, 0, n-1); 3

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

Pick Pivot Element There are 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 In very early versions of quicksort, the leftmost element of the partition would often be chosen as the pivot element. Unfortunately, this causes worst-case behavior on already sorted arrays, which is a rather common use-case. The problem was easily solved by choosing either a random index for the pivot, choosing the middle index of the partition or (especially for longer partitions) choosing the median of the first, middle and last element of the partition for the pivot (in this case the media between 40-60-100).

Partitioning Array Given a pivot, partition the elements of the array such that the resulting array consists of: One sub-array that contains elements >= pivot 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.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Quicksort Analysis Assume that keys are random, uniformly distributed. What is best case running time?

Quicksort Analysis Assume that keys are random, uniformly distributed. What is best case running time? Recursion: Partition splits array in two sub-arrays of size n/2 Quicksort each sub-array

Quicksort Analysis Assume that keys are random, uniformly distributed. What is best case running time? Recursion: Partition splits array in two sub-arrays of size n/2 Quicksort each sub-array Depth of recursion tree?

Quicksort Analysis Assume that keys are random, uniformly distributed. What is best case running time? Recursion: Partition splits array in two sub-arrays of size n/2 Quicksort each sub-array Depth of recursion tree? O(log2n)

Quicksort Analysis Assume that keys are random, uniformly distributed. What is best case running time? Recursion: Partition splits array in two sub-arrays of size n/2 Quicksort each sub-array Depth of recursion tree? O(log2n) Number of accesses in partition?

Quicksort Analysis Assume that keys are random, uniformly distributed. What is best case running time? Recursion: Partition splits array in two sub-arrays of size n/2 Quicksort each sub-array Depth of recursion tree? O(log2n) Number of accesses in partition? O(n)

Quicksort Analysis Assume that keys are random, uniformly distributed. Best case running time: O(n log2n)

Quicksort Analysis Assume that keys are random, uniformly distributed. Best case running time: O(n log2n) Worst case running time?

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

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

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

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

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

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

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

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

Quicksort Analysis Assume that keys are random, uniformly distributed. Best case running time: O(n log2n) Worst case running time? Recursion: Partition splits array in two sub-arrays: one sub-array of size 0 the other sub-array of size n-1 Quicksort each sub-array Depth of recursion tree?

Quicksort Analysis Assume that keys are random, uniformly distributed. Best case running time: O(n log2n) Worst case running time? Recursion: Partition splits array in two sub-arrays: one sub-array of size 0 the other sub-array of size n-1 Quicksort each sub-array Depth of recursion tree? O(n)

Quicksort Analysis Assume that keys are random, uniformly distributed. Best case running time: O(n log2n) Worst case running time? Recursion: Partition splits array in two sub-arrays: one sub-array of size 0 the other sub-array of size n-1 Quicksort each sub-array Depth of recursion tree? O(n) Number of accesses per partition?

Quicksort Analysis Assume that keys are random, uniformly distributed. Best case running time: O(n log2n) Worst case running time? Recursion: Partition splits array in two sub-arrays: one sub-array of size 0 the other sub-array of size n-1 Quicksort each sub-array Depth of recursion tree? O(n) Number of accesses per partition? O(n)

Quicksort Analysis Assume that keys are random, uniformly distributed. Best case running time: O(n log2n) Worst case running time: O(n2)!!!

Quicksort Analysis Assume that keys are random, uniformly distributed. Best case running time: O(n log2n) Worst case running time: O(n2)!!! What can we do to avoid worst case?

Improving Performance of Quicksort Improved selection of pivot. For sub-arrays of size 3 or less, apply brute force search: Sub-array of size 1: trivial Sub-array of size 2: if(data[first] > data[second]) swap them Sub-array of size 3: if(data[second] > data[third]) swap them if(data[first] > data[third]) swap them