0% found this document useful (0 votes)
33 views

Quick Sort

Merge sort is a sorting algorithm that uses a divide and conquer approach. It divides an array into halves, recursively sorts each half, and then merges the sorted halves into one sorted array. This results in an overall time complexity of O(n log n). Quicksort is another comparison-based sorting algorithm that chooses a pivot element and partitions the array into two sub-arrays - one with elements less than the pivot and one with greater elements. It then recursively applies the same approach to the two sub-arrays. The average time complexity is O(n log n) but it can be O(n^2) in the worst case.

Uploaded by

Mohammed Jeelan
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPT, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
33 views

Quick Sort

Merge sort is a sorting algorithm that uses a divide and conquer approach. It divides an array into halves, recursively sorts each half, and then merges the sorted halves into one sorted array. This results in an overall time complexity of O(n log n). Quicksort is another comparison-based sorting algorithm that chooses a pivot element and partitions the array into two sub-arrays - one with elements less than the pivot and one with greater elements. It then recursively applies the same approach to the two sub-arrays. The average time complexity is O(n log n) but it can be O(n^2) in the worst case.

Uploaded by

Mohammed Jeelan
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPT, PDF, TXT or read online on Scribd
You are on page 1/ 64

Mergesort and Quicksort

Chapter 8
Kruse and Ryba

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 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?

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 Contd
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]

Static Method mergeSort()


Public static void mergeSort(Comparable []a, int left,
int right)
{
// sort a[left:right]
if (left < right)
{// at least two elements
int mid = (left+right)/2;
//midpoint
mergeSort(a, left, mid);
mergeSort(a, mid + 1, right);
merge(a, b, left, mid, right); //merge from a to b
copy(b, a, left, right); //copy result back to a
}
}

Merge Function

Evaluation
Recurrence equation:
Assume n is a power of 2
c1
if n=1
T(n) =
2T(n/2) + c2n

if n>1, n=2k

Solution
By Substitution:
T(n) = 2T(n/2) + c2n
T(n/2) = 2T(n/4) + c2n/2
T(n) = 4T(n/4) + 2 c2n
T(n) = 8T(n/8) + 3 c2n
T(n) = 2iT(n/2i) + ic2n
Assuming n = 2k, expansion halts when we get T(1) on right side; this
happens when i=k T(n) = 2kT(1) + kc2n
Since 2k=n, we know k=logn; since T(1) = c1, we get
T(n) = c1n + c2nlogn;
thus an upper bound for TmergeSort(n) is O(nlogn)

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

60

50

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

30 100

Partitioning Array
Given a pivot, partition the elements of the array
such that the resulting array consists of:
1.
2.

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.

pivot_index = 0

40

20

10

80

60

50

30 100

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


too_big_index

too_small_index

1. While data[too_big_index] <= data[pivot]


++too_big_index

pivot_index = 0

40

20

10

80

60

50

30 100

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


too_big_index

too_small_index

1. While data[too_big_index] <= data[pivot]


++too_big_index

pivot_index = 0

40

20

10

80

60

50

30 100

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


too_big_index

too_small_index

1. While data[too_big_index] <= data[pivot]


++too_big_index

pivot_index = 0

40

20

10

80

60

50

30 100

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


too_big_index

too_small_index

1. While data[too_big_index] <= data[pivot]


++too_big_index
2. While data[too_small_index] > data[pivot]
--too_small_index

pivot_index = 0

40

20

10

80

60

50

30 100

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


too_big_index

too_small_index

1. While data[too_big_index] <= data[pivot]


++too_big_index
2. While data[too_small_index] > data[pivot]
--too_small_index

pivot_index = 0

40

20

10

80

60

50

30 100

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


too_big_index

too_small_index

1. While data[too_big_index] <= data[pivot]


++too_big_index
2. While data[too_small_index] > data[pivot]
--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

50

30 100

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


too_big_index

too_small_index

1. While data[too_big_index] <= data[pivot]


++too_big_index
2. While data[too_small_index] > data[pivot]
--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

50

80 100

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


too_big_index

too_small_index

1. While data[too_big_index] <= data[pivot]


++too_big_index
2. While data[too_small_index] > data[pivot]
--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

50

80 100

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


too_big_index

too_small_index

1. While data[too_big_index] <= data[pivot]


++too_big_index
2. While data[too_small_index] > data[pivot]
--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

50

80 100

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


too_big_index

too_small_index

1. While data[too_big_index] <= data[pivot]


++too_big_index
2. While data[too_small_index] > data[pivot]
--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

50

80 100

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


too_big_index

too_small_index

1. While data[too_big_index] <= data[pivot]


++too_big_index
2. While data[too_small_index] > data[pivot]
--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

50

80 100

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


too_big_index

too_small_index

1. While data[too_big_index] <= data[pivot]


++too_big_index
2. While data[too_small_index] > data[pivot]
--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

50

80 100

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


too_big_index

too_small_index

1. While data[too_big_index] <= data[pivot]


++too_big_index
2. While data[too_small_index] > data[pivot]
--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

50

80 100

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


too_big_index

too_small_index

1. While data[too_big_index] <= data[pivot]


++too_big_index
2. While data[too_small_index] > data[pivot]
--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

50

60

80 100

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


too_big_index

too_small_index

1. While data[too_big_index] <= data[pivot]


++too_big_index
2. While data[too_small_index] > data[pivot]
--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

50

60

80 100

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


too_big_index

too_small_index

1. While data[too_big_index] <= data[pivot]


++too_big_index
2. While data[too_small_index] > data[pivot]
--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

50

60

80 100

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


too_big_index

too_small_index

1. While data[too_big_index] <= data[pivot]


++too_big_index
2. While data[too_small_index] > data[pivot]
--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

50

60

80 100

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


too_big_index

too_small_index

1. While data[too_big_index] <= data[pivot]


++too_big_index
2. While data[too_small_index] > data[pivot]
--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

50

60

80 100

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


too_big_index

too_small_index

1. While data[too_big_index] <= data[pivot]


++too_big_index
2. While data[too_small_index] > data[pivot]
--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

50

60

80 100

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


too_big_index

too_small_index

1. While data[too_big_index] <= data[pivot]


++too_big_index
2. While data[too_small_index] > data[pivot]
--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

50

60

80 100

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


too_big_index

too_small_index

1. While data[too_big_index] <= data[pivot]


++too_big_index
2. While data[too_small_index] > data[pivot]
--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

50

60

80 100

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


too_big_index

too_small_index

1. While data[too_big_index] <= data[pivot]


++too_big_index
2. While data[too_small_index] > data[pivot]
--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

50

60

80 100

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


too_big_index

too_small_index

1. While data[too_big_index] <= data[pivot]


++too_big_index
2. While data[too_small_index] > data[pivot]
--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

50

60

80 100

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


too_big_index

too_small_index

1. While data[too_big_index] <= data[pivot]


++too_big_index
2. While data[too_small_index] > data[pivot]
--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

20

10

30

40

50

60

80 100

[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:
1. Partition splits array in two sub-arrays of size n/2
2. Quicksort each sub-array

Quicksort Analysis

Assume that keys are random, uniformly


distributed.
What is best case running time?

Recursion:
1. Partition splits array in two sub-arrays of size n/2
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:
1. Partition splits array in two sub-arrays of size n/2
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:
1. Partition splits array in two sub-arrays of size n/2
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:
1. Partition splits array in two sub-arrays of size n/2
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:
pivot_index = 0

10

12

13

50

57

63 100

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


too_big_index

too_small_index

1. While data[too_big_index] <= data[pivot]


++too_big_index
2. While data[too_small_index] > data[pivot]
--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

10

12

13

50

57

63 100

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


too_big_index

too_small_index

1. While data[too_big_index] <= data[pivot]


++too_big_index
2. While data[too_small_index] > data[pivot]
--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

10

12

13

50

57

63 100

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


too_big_index

too_small_index

1. While data[too_big_index] <= data[pivot]


++too_big_index
2. While data[too_small_index] > data[pivot]
--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

10

12

13

50

57

63 100

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


too_big_index

too_small_index

1. While data[too_big_index] <= data[pivot]


++too_big_index
2. While data[too_small_index] > data[pivot]
--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

10

12

13

50

57

63 100

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


too_big_index

too_small_index

1. While data[too_big_index] <= data[pivot]


++too_big_index
2. While data[too_small_index] > data[pivot]
--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

10

12

13

50

57

63 100

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


too_big_index

too_small_index

1. While data[too_big_index] <= data[pivot]


++too_big_index
2. While data[too_small_index] > data[pivot]
--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

10

12

13

50

57

63 100

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


too_big_index

too_small_index

1. While data[too_big_index] <= data[pivot]


++too_big_index
2. While data[too_small_index] > data[pivot]
--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

10

12

13

50

57

63 100

[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:
1.

Partition splits array in two sub-arrays:

2.

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:
1.

Partition splits array in two sub-arrays:

2.

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:
1.

Partition splits array in two sub-arrays:

2.

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:
1.

Partition splits array in two sub-arrays:

2.

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?

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.

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: left as an exercise.

You might also like