Selection Sort Performance (Recursive)= (n-1)

MCS680:
Foundations Of
Computer Science
int MSTWeight(int graph[][], int size)
{
int i,j;
int weight = 0;
O(1)
1
n
for(i=0; i<size; i++)
for(j=0; j<size; j++)
n
weight+= graph[i][j];
O(n)
return weight;
1
}
O(n)
O(1)
Running Time = 2O(1) + O(n2) = O(n2)
Iteration
Induction
Recursion
Brian Mitchell
([email protected]) -
1
Introduction
• Iteration
– Computers have the ability to execute a
task repeatedly
– Can perform repetitive operations fast
– Many common operations can be
implemented by using iteration
• Searching, sorting, copying, ...
• Recursion
– A concept is defined in terms of itself
– Recurrence relation
– Example:
• “A list either is empty or it is an element
followed by a list”
– Recursion is supported in programming
languages by allowing a function to call
itself.
• Example Factorial:
– F(x) = x * F(x-1) given F(1) = 1
Brian Mitchell
([email protected]) -
2
Introduction
• Recursion Example: Factorial
int Factorial(int n)
{
if (n < 0)
return -1;
if ((n == 0) || (n == 1))
return 1;
else
return n * Factorial(n-1);
}
• Induction is used in mathematical proofs
– Used to show that a statement is true
– Technique “Proof by Induction”
• Basis Step
• Induction Hypothesis
• Inductive Step
Brian Mitchell
([email protected]) -
3
Iteration
• Iteration supported by looping constructs in
programming languages
– for loop, while loop, do...while loop
• Used in many algorithms
– Basis for automating computed solutions
• Example: Sorting with Selection Sort
– Many sorting algorithms exist
• Varing complexity and performance
• Insertion, merge, quick, heap, ...
• Selection Sort
– Goal: Sort an array of integers into a nondecreasing order
– Partition the array into a sorted and a nonsorted parts
sorted
0
unsorted
i
Brian Mitchell
([email protected]) -
n-1
4
Selection Sort
sorted
unsorted
n-1
i
0
movement of i
• Selection Sort
– Iterating step
• Find the smallest element in the unsorted
portion of the array (in range [i ... n-1])
• Exchange the smallest element with the first
element in the unsorted portion of the array
– Element at index i
– Advancement step
• The array is now sorted from [0 ... i]
• Advance i so that it is the first element in the
unsorted portion of the array
– Advance i by one position
– Termination step
• Stop advancing i when it gets to the last
position in the array
Brian Mitchell
([email protected]) -
5
Selection Sort
• Implementation of the selection sort in ‘C’
void SelectionSort(int A[], int n)
{
int i,j,small,temp;
for(i=0; i<(n-2); i++)
{
//Get initial smallest element
small = i;
//Find actual smallest element
for(j=i+1; j<n; j++)
if(A[j] < A[small])
small = j;
//Put smallest element in the first
//location of the unsorted portion of
//the array
temp = A[small];
A[small] = A[i];
A[i] = temp;
}
}
Brian Mitchell
([email protected]) -
6
Selection Sort - Example Run
Example: Sort (10, 3, 9, 4, 1, 7)
10 3 9 4 1 7
i
j
10 3 9 4 1 7
i
j
small
1 3 9 4 10 7
i
j
1 3 9 4 10 7
i
j
small
1 3 9 4 10 7
i
1 3 9 4 10 7
j
i
j
small
1 3 4 9 10 7
i
1 3 4 9 10 7
j
i
j
small
1 3 4 7 10 9
i
1 3 4 7 10 9
j
i j
small
1 3 4 7 9 10
i
j
Brian Mitchell
([email protected]) -
7
Induction
• Inductive Proofs
– Mathematical induction is a technique for
proving that a statement S(n) is true for all
integers above some lower limit
• Generally for integers > 0
– Example
• Prove:
n(n  1)
i
for all n  1

2
i 1
n
– Inductive proofs are performed using a
three step process
• Basis
– Show S(n) holds for a base case
• Induction Hypothesis
– Assume for some fixed n, the hypothesis
holds
• Inductive Step
– Show that S(n) implies S(n+1)
Brian Mitchell
([email protected]) -
8
Induction Example
• Prove by induction on n:
n
i 
i 1
n(n  1)
for all n  1
2
1(1  1)
i 1

2
i 1
1
Basis n=1:
Induction Hypothesis -- Assume the following is true:
n(n  1)
i
for all n  1

2
i 1
n
Induction Step -- Show the following:
(n  1)(n  1)  1
i

2
i 1
n 1
Brian Mitchell
([email protected]) -
9
Induction Example
n 1
 i  1  2  3  ...  (n  1)  n  (n  1)
i 1
 1  2  3  ...  (n  1)  n  (n  1)
n(n  1)
 n 
   i   (n  1) 
 (n  1)
2
 i 1 
n 2  n  2n  2 n 2  2n  1  n  1


2
2
(n 2  2n  1)  (n  1)


2
2

(n  1)( n  1)  (n  1) (n  1)  (n  1)


2
2
(n  1)(n  1)  1

2
Brian Mitchell
([email protected]) -
10
Induction Example
• Prove by induction on n:
n
2
i
 
i 1
n(n  1)( 2n  1)
for all n  1
6
Basis n=1:
1
2
i

1


i 1
1(1  1)( 2  1) 6
 1
6
6
Induction Hypothesis -- Assume the following is true:
n 1
2
i
 
i 1
(n  1)(( n  1)  1)( 2(n  1)  1)
for all n  1
6
Induction Step -- Show the following:
n
2
i
 
i 1
n(n  1)( 2n  1)
6
Brian Mitchell
([email protected]) -
11
Induction Example
n
2
2
2
2
2
2
i

1

2

...

(
n

2
)

(
n

1
)

n

i 1


 12  2 2  ...  (n  2) 2  (n  1) 2  n 2
 n 1 2  2
 i   n
 i 1 
(n  1)(( n  1)  1)( 2(n  1)  1) 6n 2


6
6
2n 3  n 2  2n 2  n  6n 2 2n 3  3n 2  n


6
6
2
n(2n  3n  1) n(n  1)( 2n  1)


6
6
Brian Mitchell
([email protected]) -
12
Why Does Induction Work?
• Suppose that we want to show that S(n) is
true for a particular value of n
– Assume for the lowest value of n that S(n)
holds (this can easily be shown in the basis
case)
– If we can show that S(n) implies S(n+1) by
the inductive step then we can show that
•
•
•
•
•
•
•
S(0) implies S(1)
S(1) implies S(2)
S(2) implies S(3)
eventually we will reach:
S(n-2) implies S(n-1)
S(n-1) implies S(n)
Thus by repetitively applying the inductive
step we can show that S(n) is true for any n
so long as the basis case holds and we can
show that S(n) implies S(n+1)
– S(n) implies S(n+1) is shown in the
inductive step
Brian Mitchell
([email protected]) -
13
Induction Example -Error
Correcting Codes
• Background
– Computers operate using binary data
– Information is transmitted between
components using an analog representation
of the data
– The analog data must be converted back to
a digital representation before it can be
used for computation
– Example: The ASCII code for ‘C’ is 67
• This is 1000011 in binary
• We want to send this character over a
computer network
Sending Computer
C
DAC
Amp
Noise
Receiving Computer
A
DAC
Amp
Brian Mitchell
([email protected]) -
14
Error Correcting Codes Parity
• Because transmission is susceptible to
error additional information must be added
to the message to verify its correctness
• Goal: Design an encoding scheme where
all codes differ by two or more bits
– Consider ‘A’ and ‘C’
– A: 1000001
C: 1000011
– An error in the 6th or 7th bit will make the
two characters indistinguishable
• Solution: Add a parity bit to ensure that all
codes differ by two or more bits
– Even Parity: The sum of the on bits is even
– Odd Parity: The sum of the on bits is odd
Standard Code
Even Parity
Odd Parity
‘A’
1000001
01000001
11000001
Brian Mitchell
([email protected]) -
‘C’
1000011
11000011
01000011
15
Error Correcting CodesParity
Signaling With Even Parity
Sending Computer
C
DAC
Amp
Noise
Receiving Computer
xx
DAC
Amp
Signaling With Odd Parity
Sending Computer
C
DAC
Amp
Noise
Receiving Computer
xx
DAC
Amp
Brian Mitchell
([email protected]) -
16
Error Correcting CodesInduction
• Show that if C is a set of bit strings of
length n, then C contains at most 2n-1
strings. Assume that n = len(C)
• Basis Step
– Assume n=2 (Definition kind of funny for
n=0 and n=1)
– C = {(00),(1,1)} because C is error
correcting, |C| = 2
• All strings differ by two or more bits
• 2(2-1) = 21 =2
• Basis holds because for n=2, |C| = 2 and
2(n-1) =2
• Induction Hypothesis
– Assume for n>2 that C contains at most
2(n-1) strings
• Induction Step
– Show that for strings of length (n+1) that C
contains at most 2n strings
Brian Mitchell
([email protected]) -
17
Error Correcting CodesInduction
• Induction Step
– By the induction hypothesis |C| = 2n-1
– 50% prefixed by a ‘0’, 50% prefixed by a ‘1’
– Split C into C0 and C1 based on the first bit:
‘0’
D0
C0
C
‘1’
D1
C1
– |C0| = |C1| = (2n-1 /2)
– Because C0 & C1 are error correcting, so are
D0 and D1
• Adding a zero bit in front of D0 or a one bit in
front of D1 still ensures that the resultant
strings differ in two or more bits
– If this was false C0 and C1 would not be error
correcting
Brian Mitchell
([email protected]) -
18
Error Correcting CodesInduction
‘0’
D0
C0
C
‘1’
D1
C1
• Now let n= length(D0) or length(D1)
– Note: length(D0) = length(D1)
• There are 2n-1 strings in D0 and D1
– D0 and D1 are error correcting (shown before)
by the inductive hypothesis
• Now, prefix all D0 strings by a zero bit (=C0)
• Also, prefix all D1 strings by a one bit (=C1)
– length(C0) = length(C1) = n+1
– |C0| = |C1| = 2n-1
• Because C0 and C1 were derived from D0 and
D1 by adding a single bit
Brian Mitchell
([email protected]) -
19
Error Correcting CodesInduction
‘0’
D0
C0
C
‘1’
D1
C1
• C = C0  C1
– |C| = |C0| + |C1|
– |C| = 2n-1 + 2n-1 = 2n
– length(C) = length(C0) = length(C1) = n+1
• Thus we have shown that given C of length
n+1 that the total number of error correcting
strings in C is |C| = 2n
– This verifies the induction hypothesis
• Thus we have proved that given C, which is
a set of bit strings, contains at most 2n-1
strings.
Brian Mitchell
([email protected]) -
20
Complete Induction
• In ordinary induction we have:
– A basis case
– An induction hypothesis
– An induction step that shows that S(n)
implies S(n+1)
– Thus because S(n) implies S(n+1) we may
continuously reapply this definition to
work up from the base case to an S(n)
• Complete Induction
– Same as ordinary induction for the base
case and induction hypothesis
– The induction step differs because we may
use all values of i from the base case up
until S(i) to show S(i+1)
• Ordinary induction only uses S(i) to show
S(i+1)
Brian Mitchell
([email protected]) -
21
Recursive Definitions
• Define a class of related objects in terms of
the objects themselves
• Recursive definitions must have
– A basis case in which one or more simple
objects are defined
– An inductive or recursive step in which
larger objects are defined in terms of the
smaller ones in the collection
• Example: Factorial
– Definition: n! = 1*2*3* ... * (n-1) * n
– Basis case:
• Factorial(n) not defined for n < 0
• Factorial(n) = 1 for n  {0,1}
– Recursive/Inductive Step:
• Factorial(n) = n * Factorial(n-1) for n > 1
Brian Mitchell
([email protected]) -
22
Induction on a Recursive
Definition
• Show that Factorial(n) = n * Factorial(n-1)
for all n > 0
– Basis Case: Factorial(1)
• Factorial(1) = 1 * Factorial(0) = 1*1 = 1 = 1!
• Thus the basis case holds
– Inductive Hypothesis
• Assume Factorial(n) = n * Factorial(n-1) = n!
for all n > 1
– Induction Step
• Show that Factorial(n+1) = (n+1) *
Factorial((n+1)-1) for all n>1
• By the inductive hypothesis we know that
Factorial((n+1)-1) = Factorial(n)
= n! = 1*2* ... * (n-1) * (n)
• Thus Factorial(n+1) = (n+1) * Factorial(n)
which is (n+1) * n! (from the previous step)
• This can be rewritten as n! * (n+1) which
equals 1*2* ... * (n-1) * n * (n+1) which is
(n+1)! by the mathematical definition of
the factorial operator
Brian Mitchell
([email protected]) -
23
Recursive Procedures
• A recursive procedure (or function) is one that
is called from within its own body
– Direct: f() calls f() from within its body
– Indirect: f() calls f1() which in turn calls
f2() which calls f()
• This can be generalized for any number of
indirect calls so long as the original function
gets called from within its body
• Recursive procedures are easy to code
– Can directly map recursive definition into
source code
• Must have a basis case and an inductive part
• Basis case resolves to a direct answer based on
the base case of the recursive definition
– Used an an exiting condition
• Inductive part makes one or more call to the
recursive procedure
– Generally the procedure parameters are changed
Brian Mitchell
([email protected]) -
24
Recursive ProceduresFactorial() Function
• Recall the recursive definition of the
factorial operation
– Factorial(0) = Factorial(1) = 1
– Factorial(n) = n * Factorial(n-1)
• Develop the code directly from the
factorial recursive definition:
int Factorial(int n)
{
if (n < 0)
return -1;
if ((n == 0) || (n == 1))
return 1;
else
return n * Factorial(n-1);
}
– Notice how the above program fragment
directly maps to the factorial recursive
definition
Brian Mitchell
([email protected]) -
25
Recursive ProceduresFactorial() Function
Analyze a call to Factorial(5):
Procedure Calls
return 5 * Factorial(5-1)
return 4 * Factorial(4-1)
return 3 * Factorial(3-1)
return 2 * Factorial(2-1)
return 1
return 1* 2
return 2*3
return 6*4
return 24*5
Stack
<empty>
5
4, 5
3, 4, 5
2, 3, 4, 5
3, 4, 5
4, 5
5
<empty>
• With recursive procedures the system stack
is used to “remember” values needed to
evaluate the recursive function once the
basis case is reached
– Stack must be restored to its original state
• Efficiency issues: Stack space is limited
and procedure calls are (relatively) slow
Brian Mitchell
([email protected]) -
26
Divide and Conquer
Techniques
• Divide the problem into subproblems
• Solve the subproblems directly or by futher
dividing into more subproblems
• Ideal for implementation with recursive
procedures
• Requirements
– The subproblems must be simpler then the
original problem
• The inductive definition
– After a finite number of subdivisions we
must encounter a subproblem that can be
directly solved
• The basis case
• If the above requirements are not met then
the recursive procedure may continue to
subdivide without ever reaching a
condition that can be directly solved
Brian Mitchell
([email protected]) -
27
Transformation of Selection Sort
Into a Recursive Procedure
Recall the original Selection Sort Algorithm:
sorted
unsorted
i
0
movement of i
n-1
• Selection Sort - Recursive
– Selection step
• Find the smallest element in the unsorted
portion of the array (in range [i ... n-1])
• Exchange the smallest element with the first
element in the unsorted portion of the array
– Element at index i
– Advancement/Recursive step
• The array is now sorted from [0 ... i]
• Resort the array using the selection sort
routine for [i+1...n]
– Termination step
• Stop resorting the array when i gets to the
last position in the array
Brian Mitchell
([email protected]) -
28
Transformation of Selection Sort
Into a Recursive Procedure
Now the Recursive Selection Sort Algorithm:
sorted
unsorted
i
0
movement of i
n-1
• Selection Sort
– Iterating step
• Find the smallest element in the unsorted
portion of the array (in range [i ... n-1])
• Exchange the smallest element with the first
element in the unsorted portion of the array
– Element at index i
– Advancement step
• The array is now sorted from [0 ... i]
• Advance i so that it is the first element in the
unsorted portion of the array
– Advance i by one position
– Termination step
• Stop advancing i when it gets to the last
position in the array
Brian Mitchell
([email protected]) -
29
Transformation of Selection Sort
Into a Recursive Procedure
void SelectionSort(int A[], int idx, int n)
{
int j,small,temp;
//BASIS
if (idx
{
//Get
small
CASE: If idx=(n-1)then array sorted
< (n - 2))
initial smallest element
= idx;
//Find actual smallest element
for(j=idx+1; j<n; j++)
if(A[j] < A[small])
small = j;
//Smallest element put in the first
//location in the unsorted array side
temp = A[small];
A[small] = A[idx];
A[idx] = temp;
//Recursively sort the rest of the array
SelectionSort(A, idx+1, n);
}
}
Brian Mitchell
([email protected]) -
30
Comparison: Iterative vs
Recursive Selection Sort
• Selection Sort
– Initialization operations
– Comparisons to find minimum element
• Copy operation to save minimum element
– Copies to exchange minimum element with
the first element in the unsorted portion of
the array
• Iterative Algorithm
– Initialization operations
small = i
• This operation executes (n-1) times in the
outer loop
– Comparisons to find minimum element
for(j=i+1; j<n; j++)
if(A[j] < A[small])
small = j;
• This operation executes (n-i) times in the
inner loop and (n-1) times in the outer loop
Brian Mitchell
([email protected]) -
31
Comparison: Iterative vs
Recursive Selection Sort
• Iterative Algorithm (con’t)
– Comparisons to find minimum element can be
bounded by the following sum:
n
 (n  i )
i 1
• (n-i) is the worse case on the number of
comparisons that are performed in the inner loop
• There are (n-1) copies of j into small (worst
case)
• And the inner loop is executed (n-1) times
– Thus the number of comparisons can be
bounded by [n(n-1)]/2:
 (n  1)(n  1)  1 
(
n

i
)

n

i

n
(
n

1
)






2


i 1
i 1
i 1
2
2
 n(n  1)  2n  2n  n  n
2
 ( n  n)  

2
 2 
n 1
n 1
n 1
n 2  n n(n  1)


2
2
Brian Mitchell
([email protected]) -
32
Comparison: Iterative vs
Recursive Selection Sort
• Iterative Algorithm (con’t)
– Copies to exchange minimum element with
the first element in the unsorted portion of
the array
temp = A[small];
A[small] = A[i];
A[i] = temp;
– The above 3 copy statements are executed
(n-1) times by the outer loop
• Total performance of the iterative
algorithm:
Selection Sort Performance (Iterative)=
(n-1) copies for initialization +
[n(n-1)]/2 comparisons +
(n-1) copies to save smallest element +
3(n-1) copies for the exchange
= [n(n-1)]/2 comparisons + 5(n-1) copies
Brian Mitchell
([email protected]) -
33
Comparison: Iterative vs
Recursive Selection Sort
• Consider the following lines of code in the
recursive version of SelectionSort():
void SelectionSort(int A[], int id,
int n)
{
...
if(idx < (n-2))
{
...
SelectionSort(A,idx+1,n);
}
}
– Notice that the SelectionSort() routine is
called (n-1) times
– Initialization operations
small = i
• This operation executes (n-1) times due to
(n-1) calls to SelectionSort()
Brian Mitchell
([email protected]) -
34
Comparison: Iterative vs
Recursive Selection Sort
• Recursive Algorithm (con’t)
– Comparisons to find minimum element can
be bounded by the following sum:
n
 (n  i )
i 1
• (n-i) is the worse case on the number of
comparisons that are performed in the inner
loop
• And the inner loop is executed (n-1) times
due to (n-1) calls to SelectionSort()
• Also there are (n-1) copies of j into small
(worst case)
– Thus the number of comparisons can be
bounded by [n(n-1)]/2
• Shown before in the iterative algorithm
Brian Mitchell
([email protected]) -
35
Comparison: Iterative vs
Recursive Selection Sort
• Recursive Algorithm (con’t)
– Copies to exchange minimum element with
the first element in the unsorted portion of the
array
temp = A[small];
A[small] = A[i];
A[i] = temp;
– The above 3 copy statements are executed (n1) times due to (n-1) calls to SelectionSort()
• Total performance of the recursive algorithm:
Selection Sort Performance (Recursive)=
(n-1) copies for initialization +
[n(n-1)]/2 comparisons +
(n-1) copies to save smallest element +
3(n-1) copies for the exchange
= [n(n-1)]/2 comparisons + 5(n-1) copies
Brian Mitchell
([email protected]) -
36
Summary: Iterative vs
Recursive Selection Sort
• The iterative and recursive version of the
selection sort have the same execution
complexity:
– [n(n-1)]/2 comparisons + 5(n-1) copies
• If a comparison and a copy take about the
same amount of execution time, execution
complexity becomes:
– [n(n-1)]/2 + 5(n-1) operations
Selection Sort Runtime Analysis
Execution Complexity
14000
12000
10000
8000
6000
4000
2000
0
0
20
40
60
80
100
120
140
160
Sample Size
Brian Mitchell
([email protected]) -
37
Merge Sort: A “Real”
Recursive Sorting Algorithm
• A divide and conquer technique
• List A = (a1, a2, ... , an) is sorted by
– Divide the list into two lists that are half
the size of the original list
– Sort each of the half sized lists separately
– Merge the two sorted sub-lists to produce a
sorted list, Asorted
• Merge sort grows much slower then the
selection sort for larger values of n
• Merging
– Produce a sorted list from two sorted lists
Sorted List 1
Merge
Sorted List
Sorted List 2
Brian Mitchell
([email protected]) -
38
Merge Sort
• Merge Algorithm
– Examine the element at the front of both
lists
– Pick the smallest from one of the lists
• Ties are broken arbitrarily
– Add the smallest element (chosen above) to
the sorted list
– Remove the chosen element from the front
of the list
– Continue until both lists are empty
– The resultant output list will be sorted
– The algorithm assumes that the two
input lists have been pre-sorted
• Merge algorithm will not produce a sorted
list unless the input lists are sorted!
Brian Mitchell
([email protected]) -
39
Merging With Linked Lists
• The merge routine will use the following data
structure to represent a merge list:
typedef struct _mList
{
int element;
struct _mList next;
}*mList;
• The merge algorithm can then be recursively
defined for two lists (given lst1 and lst2):
– Basis cases:
• lst1 is NULL, add lst2 to the merge list
• lst2 is NULL, add lst1 to the merge list
• if neither lst1 nor lst2 is null then add the
smallest of element in the front of lst1 or
lst2 to the merge list
– Merge steps
• if lst1->element < lst2->element
– remove the first element from the lst1 list and
add it to the merge list
Brian Mitchell
([email protected]) -
40
Merging With Linked Lists
– Merge Steps (con’t)
• if lst2->element < lst1->element
– remove the first element from the lst2 list
and add it to the merge list
– Termination step: Stop merging when both
lst1 and lst2 are empty
mList Merge(mList lst1, mList lst2)
{
mList *ml;
if (lst1 == NULL) ml = lst2;
else if (lst2 == NULL) ml = lst1;
else if (lst1->element <= lst2->element)
{ //Ans: lst1->element + merge of remainder
lst1->next = Merge(lst1->next, lst2);
ml = lst1;
}
else
{ //Ans: lst2->element + merge of remainder
lst2->next = Merge(lst1, lst2->next);
ml = lst2;
}
return ml; //Return the merged list
}
Brian Mitchell
([email protected]) -
41
Splitting Linked Lists
• Merge sort must be able to split a list into
two equal parts
– The lists may differ by one in length if the
input list to be split is odd in length
• Options
– Split at the midpoint
– Split taking every other element
7
1
3
5
SplitMidpoint()
7
1
3
5
7
1
3
5
SplitEveryOther()
7
Brian Mitchell
([email protected]) -
3
1
5
42
Split Routine (Every Other)
• A recursive routine to split a list
– Input list is modified with every other
element removed
– A new list is created based on the removed
elements from the input list
• The new list is returned from the Split()
function
mList Split(mList orig)
{
mList secondCell;
if (orig == NULL) return NULL;
else if (orig->next == NULL) return NULL;
else
{
secondCell = orig->next;
orig->next = secondCell->next;
secondCell->next =
Split(secondCell->next);
return secondCell;
}
}
Brian Mitchell
([email protected]) -
43
Merge Sort
• Now we are able to split a list and merge a
sorted list
– Notice that a list of length 1 is sorted
• MergeSort() algorithm
– Recursively split the input lists until the list
lengths are 1
• Lists of length 1 are sorted
• Result is a tree
– Recursively merge the sorted lists
• Build the resultant sorted list by recursively
merging the lists in the tree that was created
in the previous step
Brian Mitchell
([email protected]) -
44
MergeSort Algorithm
Input List
742897721
Splitting
72971
791
71
7
4872
27
9
2
47
7 4
82
8
7
2
Direction of
Execution
742897721
1
Merging
12779
179
17
7
9
2478
27
2
47
7 4
28
7
8
2
Direction of
Execution
12247789
1
Brian Mitchell
([email protected]) -
45
MergeSort Algorithm
• Recursively split list
– Continue until list sizes are 1
• Recursively merge lists
– Continue until entire list is sorted
• Resultant list is sorted
void MergeSort(mList list)
{
mList SecondList;
if (list != NULL)
{
if(list->next != NULL)
{
SecondList = Split(list);
MergeSort(list);
MergeSort(SecondList);
list = Merge(list,SecondList);
}
}
}
Brian Mitchell
([email protected]) -
46
Rough AnalysisMergeSort()
• Merge() - 2(n-1)
– (n-1) recursive calls
– 2 assignments each call
• Split() - 3(n-1)
– (n-1) recursive calls
– 3 assignments each call
• MergeSort() - [10n - 6]lg n
– 2 lg n recursive calls
• MergeSort() is called twice from within its
body
– Each call is with a list of length (n/2)
– Each recursive call contains
• A call to Split()
• A call to Merge()
• 2 assignments
Brian Mitchell
([email protected]) -
47
Rough AnalysisMergeSort()
• Merge Sort Performance (con’t)
Merge Sort Performance =
(2 calls to MergeSort() *
lg n internal recursive calls) *
(time to Merge() + time to Split +
2 assignments)
= (2 lg n) * [2(n-1) + 3(n-1) + 2]
= (2 lg n) * [2n - 2 + 3n -3 + 2]
= (2 lg n) * [5n - 3]
= (10n - 6) lg n
Brian Mitchell
([email protected]) -
48
Merge Sort Performance
Merge Sort Performance
50000
Execution Complexity
45000
Merge Sort
40000
35000
30000
25000
20000
15000
10000
5000
0
0
100
200
300
400
500
600
n
Brian Mitchell
([email protected]) -
49
Merge vs Selection Sort
• Selection Sort - Quadratic Growth
• Merge Sort - Logarithmic Growth
Merge vs Selection Sort
140000
Merge Sort
Execution Complexity
120000
Selection Sort
100000
80000
60000
40000
20000
0
0
100
200
300
400
500
600
n
Brian Mitchell
([email protected]) -
50
MergeSort() - ‘C’ Example
#include <stdio.h>
#include <stdlib.h>
typedef struct _mList
{
int element;
struct _mList *next;
}mList;
void Add(mList **lst, int val)
{
mList *x = (mList *)malloc(sizeof(mList));
x->element = val;
x->next = *lst;
*lst = x;
}
Brian Mitchell
([email protected]) -
51
MergeSort() - ‘C’ Example
void Print(mList *lst, char *title)
{
printf("%s: ",title);
while(lst != NULL)
{
printf("%d ",lst->element);
lst = lst->next;
}
printf("\n");
}
mList * Merge(mList *lst1, mList *lst2)
{
mList *ml;
if (lst1 == NULL)
ml = lst2;
else if (lst2 == NULL)
ml = lst1;
else if (lst1->element <= lst2->element)
{
lst1->next = Merge(lst1->next, lst2);
ml = lst1;
}
Brian Mitchell
([email protected]) -
52
MergeSort() - ‘C’ Example
else
{
lst2->next = Merge(lst1, lst2->next);
ml = lst2;
}
return ml;
}
mList *Split(mList *orig)
{
mList *secondCell;
if (orig == NULL)
return NULL;
else if (orig->next == NULL)
return NULL;
else
{
secondCell = orig->next;
orig->next = secondCell->next;
secondCell->next =
Split(secondCell->next);
return secondCell;
}
}
Brian Mitchell
([email protected]) -
53
MergeSort() - ‘C’ Example
void MergeSort(mList *list)
{
mList *SecondList;
if (list != NULL)
{
if(list->next != NULL)
{
SecondList = Split(list);
MergeSort(list);
MergeSort(SecondList);
list = Merge(list,SecondList);
}
}
}
Brian Mitchell
([email protected]) -
54
MergeSort() - ‘C’ Example
void main()
{
int data[] = {7,4,3,8,9,7,7,2,1};
int i;
mList *theList = NULL;
for(i=0; i<9; i++)
Add(&theList,data[i]);
MergeSort(theList);
Print(theList,"Merge Sorted List
");
}
Brian Mitchell
([email protected]) -
55