Applied Programming (Recursion, Searching, Sorting) : National University of Computer & Emerging Sciences

You might also like

Download as pptx, pdf, or txt
Download as pptx, pdf, or txt
You are on page 1of 133

Applied Programming

(Recursion, Searching, Sorting)


(CS 319)

School of Computing
National University of Computer & Emerging Sciences ,
Islamabad Campus
Recursion
Introduction to Recursion
• A recursive function is one that calls itself.
void Message(void)
{
cout << "This is a recursive function.\n";
Message();
}

The function above displays the string


"This is a recursive function.\n", and then calls itself.

Can you see a problem with this function?


Recursion
• The function is like an infinite loop because there is no
code to stop it from repeating.

• Like a loop, a recursive function must have some


algorithm to control the number of times it repeats.
Recursion : Using Control Condition
void Message(int times)
{
if (times > 0)
{
cout << "This is a recursive function.\n";
Message(times ‑ 1);
}
return;
}

• The function contains an if/else statement that controls the


repetition. For example, if we call the function:
 
Message(5);
 
The argument, 5, will cause the function to call itself 5 times.
Recursion : Using Control Condition
void Message(int times)
{
if (times > 0) // Base case
{
cout << "This is a recursive function.\n";
Message(times ‑ 1);
}
return;
}

• With each recursive call, the parameter controlling the


recursion should move closer to the base case

• Eventually, the parameter reaches the base case and the


chain of recursive calls terminates
void Message(int times)
{
if (times > 0)
1st call of the function {
cout << "This is a recursive function.\n";
Value of times: 5 Message(times ‑ 1);
}
2nd call of the function return;
Value of times: 4 }

3rd call of the function

Value of times: 3

4th call of the function

Value of times: 2

5th call of the function


This cycle repeats itself
until 0 is passed to the Value of times: 1
function.
6th call of the function

Depth of recursion: 6 Value of times: 0


Program Output
  This is a recursive function.
This is a recursive function.
This is a recursive function.
This is a recursive function.
This is a recursive function.
What Happens When Called?
• Each time a recursive function is called, a new copy of
the function runs, with new instances of parameters
and local variables being created

• As each copy finishes executing, it returns to the copy of


the function that called it

• When the initial copy finishes executing, it returns to


the part of the program that made the initial call to the
function
14-10
Types of Recursion
• Direct recursion
– a function calls itself

• Indirect recursion
– function A calls function B, and function B calls
function A. Or,

– function A calls function B, which calls …, which calls


function A

14-11
Recursive Function
#include <iostream>
using namespace std;

void message(int);
int main()
{ message(5);
return 0; message called with 5 in times.
}
This is a recursive function.
//************************************************************message called with 4 in times.
// Definition of function message. If the value in times is *
// greater than 0, the message is displayed and the function *This is a recursive function.
// is recursively called with the argument times - 1. *
//************************************************************message called with 3 in times.
This is a recursive function.
void message(int times)
{ cout << "message called with " << times message called with 2 in times.
<< " in times.\n";
This is a recursive function.
if (times > 0)
{ message called with 1 in times.
cout << "This is a recursive function.\n";
This is a recursive function.
message(times - 1);
} message called with 0 in times.

message returning with 0 in times.


cout << "message returning with " << times;
cout << " in times.\n"; message returning with 1 in times.
return;
} message returning with 2 in times.
Recursion
message returning with 3 in times.
The Recursive Factorial Function
• The factorial of a nonnegative integer n is the product of
all positive integers less or equal to n
• Factorial of n is denoted by n!
• The factorial of 0 is 1:
0!=1
n ! = n x (n-1) x … x 2 x 1 if n > 0

14-13
The Recursive Factorial Function
• Factorial of n can be expressed in terms of the factorial of n-1
0!=1
n ! = n x (n-1) !
• The base case is n = 0

• Recursive function:

int factorial(int n)
{
if (n == 0)
return 1;
else
return n * factorial(n-1);
} 14-14
Character count - Recursive
#include <iostream> search, char str[], int subscript)
int numChars(char
using namespace std;
{
// Function prototype
int if (str[subscript] == '\0')
numChars(char, char [], int);
{
int main()
{ // Base case: The end of the string is reached.
char array[] = "abcddddef";
return 0;
/* Display the number of times the letter
} appears in the string. */
'd'
else if (str[subscript] == search)
cout << "The letter d appears "
<<
{ numChars('d', array, 0) << " times.\n";

/* Recursive
return 0; case: A matching character was found. Return
} 1 plus the number of times the search character appears in the
rest of the string.*/
14-15
return 1 + numChars(search, str,subscript+1);
Finding gcd

14-16
The Recursive gcd Function
int gcd(int x, int y)
{
if (x % y == 0) //base case
return y;
else
return gcd(y, x % y);
}

14-17
Solving Recursively Defined Problems
• The natural definition of some problems leads to a
recursive solution

• Example: Fibonacci numbers:


0, 1, 1, 2, 3, 5, 8, 13, 21, ...

• After the starting 0,1, each term is the sum of the


two preceding terms

• Recursive solution:
fib(n) = fib(n – 1) + fib(n – 2);

• Base cases: n == 0, n == 1 14-18


Recursive Fibonacci Function
int fib(int n)
{
if (n <= 0) // base case
return 0;
else if (n = = 1) // base case
return 1;
else
return fib(n – 1) + fib(n – 2);
}

Finds the nth fib number 14-20


Recursive Algorithms… Examples
– The Towers of Hanoi
– Binary Search Algorithm
– Height of a Binary Tree
–…

14-21
Recursion VS. Iteration
• Benefits (+), disadvantages(-) for recursion:
+ Natural formulation of solution to certain problems
+ Results in shorter, simpler functions
– May not execute very efficiently

• Benefits (+), disadvantages(-) for iteration:


+ Executes more efficiently than recursion
– May not be as natural as recursion for some problems

14-31
Searching
Searching
• Given a collection and an element (key) to find…

• Output
– Print a message (“Found”, “Not Found”)
– Return a value (position of key )

• Don’t modify the collection in the search!


Linear Search: A Simple Search
• A search traverses the collection until:
– The desired element is found
– Or the collection is exhausted

• If the collection is ordered, you might not have


to look at all elements
– I can stop looking when I know the element
cannot be in the collection
Un-Ordered Iterative Array Search
procedure Search(my_array Array,
target Num)
i, Num
i = 1 Scan the array
loop
exitif((i > MAX_ELEMENTS) OR (my_array[i] = target))
i = i + 1
endloop

if(i > MAX_Elements) then


print(“Target data not found”)
else
print(“Target data found”)
endif
endprocedure // Search
procedure Search(my_array Array, target Num)

i = 1
loop
exitif((i > MAX_ELEMENTS) OR (my_array[i] =
target))
i = i + 1
endloop

if(i > MAX_ELEMENTS) then


print(“Target data not found”)
else
print(“Target data found”)
endif

endprocedure // Search

my_array
7 12 5 22 13 32
target = 13 1 2 3 4 5 6
procedure Search(my_array isoftype in NumArrayType,
target isoftype in Num)
i = 1
loop
exitif((i > MAX) OR (my_array[i] = target))
i = i + 1
endloop

if(i > MAX) then


print(“Target data not found”)
else
print(“Target data found”)
endif

endprocedure // Search

my_array
7 12 5 22 13 32
target = 13 1 2 3 4 5 6
procedure Search(my_array isoftype in NumArrayType,
target isoftype in Num)
i = 1
loop
exitif((i > MAX) OR (my_array[i] = target))
i = i + 1
endloop

if(i > MAX) then


print(“Target data not found”)
else
print(“Target data found”)
endif

endprocedure // Search

my_array
7 12 5 22 13 32

target = 13 1 2 3 4 5 6
procedure Search(my_array isoftype in NumArrayType,
target isoftype in Num)
i = 1
loop
exitif((i > MAX) OR (my_array[i] = target))
i = i + 1
endloop

if(i > MAX) then


print(“Target data not found”)
else
print(“Target data found”)
endif

endprocedure // Search

my_array
7 12 5 22 13 32

target = 13 1 2 3 4 5 6
procedure Search(my_array isoftype in NumArrayType,
target isoftype in Num)
i = 1
loop
exitif((i > MAX) OR (my_array[i] = target))
i = i + 1
endloop

if(i > MAX) then


print(“Target data not found”)
else
print(“Target data found”)
endif

endprocedure // Search

my_array
7 12 5 22 13 32
target = 13 1 2 3 4 5 6
procedure Search(my_array isoftype in NumArrayType,
target isoftype in Num)
i = 1
loop
exitif((i > MAX) OR (my_array[i] = target))
i = i + 1
endloop

if(i > MAX) then


print(“Target data not found”)
else
print(“Target data found”)
endif
endprocedure // Search

my_array
7 12 5 22 13 32
target = 13 1 2 3 4 5 6
procedure Search(my_array isoftype in NumArrayType,
target isoftype in Num)
i = 1
loop
exitif((i > MAX) OR (my_array[i] = target))
i = i + 1Target data found
endloop

if(i > MAX) then


print(“Target data not found”)
else
print(“Target data found”)
endif
endprocedure // Search

my_array
7 12 5 22 13 32
target = 13 1 2 3 4 5 6
Linear Search Analysis: Best Case
pr oc e dur e Se a r c h( my_ ar r ay Ar r a y,
t ar ge t Num)
i Num
i <- 1 S c an the array
l o op
e xi t i f ( ( i > MAX) OR ( my_ ar r ay [ i ] = t ar ge t ) )
i <- i + 1
e ndl oo p
Best Case:
i f ( i > MAX) t he n
pr i nt ( “Tar ge t dat a not f ound”) 1 comparison
el s e
pr i nt ( “Tar ge t dat a f ound”)
e ndi f
e ndpr oc e dur e / / Se ar c h

Best Case: match with the first item

7 12 5 22 13 32
target = 7
Linear Search Analysis: Worst Case
pr o c e dur e Se ar c h( my_a r r a y Ar r ay,
t ar g e t Num)
i Num
i <- 1 S c an the array
l oo p
e xi t i f ( ( i > MAX) OR ( my_a r r a y [ i ] = t a r ge t ) )
i <- i + 1
e ndl oop

i f ( i > MAX) t he n Worst Case:


pr i nt ( “Tar ge t da t a not f o und”)
N comparisons
el s e
pr i nt ( “Tar ge t da t a f ound”)
e ndi f
e ndpr oc e dur e / / Se ar c h

Worst Case: match with the last item (or no match)

7 12 5 22 13 32
target = 32
Searching Example
(Binary Search on Sorted List)
The Scenario
• We have a sorted array

• We want to determine if a particular element is in


the array:
– Once found, print or return (index, boolean, etc.)
– If not found, indicate the element is not in the
collection

7 12 42 59 71 86 104 212
A Better Search Algorithm
• Of course we could use our simpler search and
traverse the array

• But we can use the fact that the array is sorted to


our advantage

• This will allow us to reduce the number of


comparisons
Binary Search
• Requires a sorted array or a binary search tree

• Cuts the “search space” in half each time.

• Keeps cutting the search space in half until the


target is found or has exhausted the all possible
locations.
Binary Search Algorithm
look at “middle” element

if no match then
look left (if need smaller) or
right (if need larger)

Look for 42

1 7 9 12 33 42 59 76 81 84 91 92 93 99
The Algorithm: Binary Search
look at “middle” element

if no match then
look left (if need smaller) or
right (if need larger)

1 7 9 12 33 42 59 76 81 84 91 92 93 99

Look for 42
The Algorithm: Binary Search
look at “middle” element

if no match then
look left (if need smaller) or
right (if need larger)

1 7 9 12 33 42 59 76 81 84 91 92 93 99

Look for 42
The Algorithm: Binary Search
look at “middle” element

if no match then
look left (if need smaller) or
right (if need larger)

1 7 9 12 33 42 59 76 81 84 91 92 93 99

Look for 42
The Algorithm: Binary Search
• Returns found or not found (true or false)

• When move left or right, change the array boundaries


– We’ll need a first and last
The Binary Search Algorithm
calculate middle position

if(first and last have “crossed”) then


“Item not found”

elseif (element at middle = to_find) then


“Item Found”

elseif to_find < element at middle then


Look to the left

else
Look to the right
Looking Left

• Use indices “First” and “Last” to keep track of


where we are looking
• Move left by setting last = middle – 1

7 12 42 59 71 86 104 212

F L M L
Looking Right

• Use indices “first” and “last” to keep track of


where we are looking
• Move right by setting first = middle + 1

7 12 42 59 71 86 104 212

F M F L
Binary Search Example – Found

7 12 42 59 71 86 104 212

F M L

Looking for 42
Binary Search Example – Found

7 12 42 59 71 86 104 212

F M L

Looking for 42
Binary Search Example – Found

7 12 42 59 71 86 104 212

F
M
L
42 found – in 3 comparisons
Binary Search Example – Not Found

7 12 42 59 71 86 104 212

F M L

Looking for 89
Binary Search Example – Not Found

7 12 42 59 71 86 104 212

F M L

Looking for 89
Binary Search Example – Not Found

7 12 42 59 71 86 104 212

F L
M
Looking for 89
Binary Search Example – Not Found

7 12 42 59 71 86 104 212

L F

89 not found – 3 comparisons


Recursive: Binary Search Function
Function Find return boolean (A Array, first, last, to_find)

middle = (first + last) div 2

if (first > last) then


return false
elseif (A[middle] == to_find) then
return true
elseif (to_find < A[middle]) then
return Find(A, first, middle–1, to_find)
else
return Find(A, middle+1, last, to_find)
endfunction
Recursive: Binary Search Analysis: Best Case
Func t i on Fi nd r e t ur n bool e a n ( A Ar r ay, f i r s t , l as t , t o _f i nd)
mi ddl e <- ( f i r s t + l as t ) di v 2
i f ( f i r s t > l as t ) t he n
r e t ur n f al s e
e l s e i f ( A[ mi ddl e ] = t o_ f i nd) t he n
r e t ur n t r ue
e l s e i f ( t o_f i nd < A[ mi ddl e ] ) t he n
r e t ur n Fi nd( A, f i r s t , mi ddl e –1, t o_f i nd)
Best Case:
el s e
1 comparison
r e t ur n Fi nd( A, mi ddl e +1 , l as t , t o_f i nd)
e ndf unc t i on

Best Case: match from the firs comparison

1 7 9 12 33 42 59 76 81 84 91 92 93 99

Target: 59
Binary Search Analysis: Worst Case
Func t i o n Fi nd r e t ur n bo o l e a n ( A Ar r a y, f i r s t , l a s t , t o _ f i nd)
mi ddl e <- ( f i r s t + l as t ) di v 2
i f ( f i r s t > l a s t ) t he n
How many
r e t ur n f a l s e
e l s e i f ( A[ mi ddl e ] = t o _f i nd) t he n
comparisons??
r e t ur n t r ue
e l s e i f ( t o _ f i nd < A[ mi ddl e ] ) t he n
r e t ur n Fi nd( A, f i r s t , mi ddl e – 1 , t o _ f i nd)
el s e
r e t ur n Fi nd( A, mi ddl e +1 , l a s t , t o _f i nd)
e ndf unc t i o n

Worst Case: divide until reach one item, or no match.

1 7 9 12 33 42 59 76 81 84 91 92 93 99
Binary Search Analysis: Worst Case
• With each comparison we throw away ½ of the list

N ………… 1 comparison

N/2 ………… 1 comparison Number of steps is at


most Log2N
N/4 ………… 1 comparison

N/8 ………… 1 comparison


.
.
.
1 ………… 1 comparison
Summary
• Binary search reduces the work by half at each
comparison

• If array is not sorted  Linear Search


– Best Case O(1)
– Worst Case O(N)

• If array is sorted  Binary search


– Best Case O(1)
– Worst Case O(Log2N)
Sorting
Sorting Algorithms
• There are several sorting algorithms in the
literature

• We discuss some of the commonly used sorting


algorithms

• These sorting algorithms can be applied to either


array-based lists or linked lists
Bubble Sort
• Suppose list[0]...list[n - 1] is a list of
n elements, indexed 0 to n – 1

• Bubble sort algorithm:


– In a series of n - 1 iterations, compare successive
elements, list[index] and list[index + 1]
– If list[index] is greater than list[index +
1], then swap them
Sorting An Array(Ascending)
int a[10]={33,10,1,87,6,44,23,3,11,82};
int i,j,temp;
int N=10;

for (i=0; i<N; i++)


{
for (int j=0; j<N-i-1; j++)
if (a[j] > a[j+1])
{ temp = a[j];
a[j] = a[j+1];
a[j+1] = temp;
}
}
Sorting An Array(Descending)
int a[10]={33,10,1,87,6,44,23,3,11,82};
int i,j,temp;
int N=10;

for (i=0; i<N; i++)


{
for (int j=0; j<N-i-1; j++)
if (a[j] < a[j+1])
{ temp = a[j];
a[j] = a[j+1];
a[j+1] = temp;
}
}
Bubble Sort
• bubbleSort contains nested loops
– Outer loop executes n – 1 times
– For each iteration of outer loop, inner loop executes a
certain number of times

• Comparisons and Assignments (worst case):


Selection Sort
Re-arrange list by selecting an element and moving it to
its proper position.

Selection sort algorithm:


for (int index=0; index<length-1; index++)
{

- find the location (smallestIndex) of the smallest


element in list[index]…list[length-1].
- swap the smallest element with list[index] (For
example: swap list[smallestIndex] with list[index])

}
Selection Sort Example
Scan the items in the list to find the smallest element

65 35 25 85 50 55 70

interchange the smallest element with the first element, 65

25 35 65 85 50 55 70

Find the smallest element starting from the second


element (index+1) in the list
25 35 65 85 50 55 70
Selection Sort Example
Find the smallest element starting from the second
element in the list  35

25 35 65 85 50 55 70

35 is already in the correct order. No interchange is


needed.

The process continues as following…


Selection Sort Example

25 35 65 85 50 55 70

25 35 50 85 65 55 70

25 35 50 55 65 85 70

25 35 50 55 65 85 70

25 35 50 55 65 70 85
Selection Sort Example
Selection Sort Example
Insertion Sort: Array-Based Lists
• Reduces number of key comparisons made in selection
sort
• Can be applied to both arrays and linked lists (examples
follow)
• The insertion sort algorithm sorts the list by moving each
element to its proper place

• Sorts list by:


– Finding first unsorted element in list
– Moving it to its proper position
• Given an unsorted list as follows:
65 35 25 85 50 55 70

• Compare element 65 and 35


65 35 25 85 50 55 70
• Interchange 65 and 35:
65 35 25 85 50 55 70

35 65 25 85 50 55 70

• Now, compare 25 with the previous elements:


35 65 25 85 50 55 70

25 35 65 85 50 55 70
• Now, compare 85 with the previous elements:
25 35 65 85 50 55 70

25 35 65 85 50 55 70

• No need to change the position..


• Now, compare 50 with the previous elements:
25 35 65 85 50 55 70

25 35 50 65 85 55 70
• Now, compare 55 with the previous elements:
25 35 50 65 85 55 70

25 35 50 55 65 85 70

• Now, compare 70 with the previous elements:

25 35 50 55 65 85 70

• A sorted list…
25 35 50 55 65 70 85
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 <= pivot
• Elements > pivot
– Quicksort (2 sub-arrays)
– Return results
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 (as pivot) 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 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 array.

Partitioning loops through, swapping elements


below/above pivot.
pivot_index = 0 40 20 10 80 60 50 7 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 7 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 7 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 7 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 7 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 7 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 7 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 7 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 step 1

pivot_index = 0 40 20 10 30 60 50 7 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 7 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
20 10
10 30
30 60 50
50 7 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 7 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 7 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 7 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 7 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 7 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 7 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 7 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 7 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 7 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 7 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 7 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
10 30
30 7 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 7 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 7 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
Recursively sort 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?
• 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? O(n)
Quicksort Analysis
• Assume that keys are random, uniformly
distributed.

• Best case running time: O(n log2n)

• Worst Case O(n2)


Merge Sort
Merge Sort: Linked List-Based Lists

• Merge sort: always O(n log2 n)


– Uses the divide-and-conquer technique
• Partitions the list into two sublists
• Sorts the sublists
• Combines the sublists into one sorted list

• Differs from quick sort in how list is partitioned


• Divides list into two sublists of nearly equal size
Merge Sort Example

99 6 86 15 58 35 86 4 0
Merge Sort Example
99 6 86 15 58 35 86 4 0

99 6 86 15 58 35 86 4 0
Merge Sort Example
99 6 86 15 58 35 86 4 0

99 6 86 15 58 35 86 4 0

99 6 86 15 58 35 86 4 0
Merge Sort Example
99 6 86 15 58 35 86 4 0

99 6 86 15 58 35 86 4 0

99 6 86 15 58 35 86 4 0

99 6 86 15 58 35 86 4 0
Merge Sort Example
99 6 86 15 58 35 86 4 0

99 6 86 15 58 35 86 4 0

99 6 86 15 58 35 86 4 0

99 6 86 15 58 35 86 4 0

4 0
Merge Sort Example

99 6 86 15 58 35 86 0 4

Merge 4 0
Merge Sort Example

6 99 15 86 35 58 0 4 86

99 6 86 15 58 35 86 0 4

Merge
Merge Sort Example

6 15 86 99 0 4 35 58 86

6 99 15 86 35 58 0 4 86

Merge
Merge Sort Example

0 4 6 15 35 58 86 86 99

6 15 86 99 0 4 35 58 86

Merge
Merge Sort: Sorted Values

0 4 6 15 35 58 86 86 99
Merge Sort (Array, Left-index, right-index)
Merge
• Easy concept, tricky code
• lots of special cases:
• keep track of two indices to step through both
arrays (the “front” of each array)
• Indices do not necessarily move at the same
speed
• Stop loop when either index reaches the end
• Two arrays are not necessarily the same size
• What to do when you reach the end of one
array but not the other?
• copy from temp back into the array
Merge
Time Complexity Analysis
• Worst case: O(nlog2n)
• Average case: O(nlog2n​​)
• Best case: O(nlog2n​​)
Comparison of Sorting Algorithms

You might also like