0% found this document useful (0 votes)
4 views29 pages

Final Project

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

Final Project

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

Name: Ricardo Vaccaro Padron

ID #: 129074
CECS 6010 Winter 2022
Advanced Design and Analysis of
Algorithms
CECS 6010 Final Project
Professor: Dr. Jeffrey Duffany
I. Description of the sorting algorithms selected:

a. Quick sort algorithm


For the time complexity of sorting algorithm project, the two sorting algorithms selected were
quicksort and insertion sort. The fastest one from the two selected is the quicksort which has a
time complexity Ø (n log(n)). Insertion sort which is the slowest of the two is Ø (n^2).
The quicksort algorithm is a divide and conquer sorting algorithm that works by partitioning its
input elements according to their value relative to some preselected element. Quicksort is noted
for its superior efficiency among n log n algorithms for sorting randomly ordered arrays by also
for the quadratic works case efficiency.
Furthermore, it is important to note that quicksort is an important sorting algorithm that is based
on the divide and conquer approach. What separates quicksort from other divide and conquer
sort algorithms like merge sort is that merge sort divides the input elements according to their
position in the array, but quicksort divides the array according to their value. Another important
fact regarding quicksort algorithm is the explanation of a partition. A partition is an arrangement
of the array’s elements so that all the elements to the left of some element A[s] are less than or
equal to A[s], and all the elements to the right of A[s] are greater than or equal to it.
An example of pseudocode of quicksort algorithm would be:

Quicksort(A[l..r]) //Sorts a subarray by quicksort

//Input: Subarray of array A[0..n − 1], defined by its left and right // indices l and r
//Output: Subarray A[l..r] sorted in nondecreasing order
if l < r

s ←Partition(A[l..r]) //s is a split position


Quicksort(A[l..s − 1])
Quicksort(A[s + 1..r])

In addition, it is important to state the best case, worst case, and average case for quicksort. The
average and best case are both (n log(n)) while the worst case is O(n^2). Quick sort is among the
fastest sorting algorithms that we have discover.

b. Insertion Sort Algorithm


The other sorting algorithm selected for the final project was insertion sort. Insertion sorts belong
to the class of O(n^2). In this sorting algorithm, sorted and unsorted elements are compared, and
the unsorted element is placed correct position after each iteration. The insertion sort assumes the
first element is to be sorted and the second element is stored separately as a key element that
needs to be sorted. The key is then compared with sorted element. If the sorted element is greater
than the key element, their places are swapped, and the key element becomes the first element.
An example of pseudocode of insertion sort algorithm would be:
ALGORITHM InsertionSort(A[0..n − 1]) //Sorts a given array by insertion sort
//Input: An array A[0..n − 1] of n orderable elements //Output: Array A[0..n − 1] sorted in
nondecreasing order for i ← 1 to n − 1 do
v ← A[i]
j←i−1
while j ≥ 0 and A[j ] > v do
A[j + 1] ← A[j ]
j←j−1 A[j + 1] ← v

Further characteristics important about insertion sort wort case for the insertion sort is Ø(n^2),
while the best case is Ø(n) and the average case is Ø(n^2).

c. Code written in R language to implement the insertion and quick sort algorithms

Insertion sort algorithm in R:

insertion_sort <- function(x)


{
# calculate the length of array
n <- length(x)
# outer loop
for (i in 2 : (n))
{
# store first element as key
key = x[i]
j =i-1
# compare key with elements for
# its correct position
while (j > 0 && x[j] > key)
{
x[j + 1] = x[j]
j=j-1
}
# Place key at its correct position
x[j + 1] = key
}
# return sorted array
x
}

# take sample array


arr <- sample(1:2000)
# call insertion sort function
sorted_arr <- insertion_sort(arr)

# print sorted array


sorted_arr
a <- sorted_arr
print(arr)
print(a)}
insertion()

Quick sort algorithm in R:

quickSort <- function(arr) {

# Pick a number at random


random_index <- sample(seq_along(arr), 1);
pivot <- arr[random_index]
arr <- arr[-random_index]

# Create array for left and right values.


left <- c()
right <- c()

# Move all smaller and equal values to the


# left and bigger values to the right.
# compare element with pivot
left<-arr[which(arr <= pivot)]
right<-arr[which(arr > pivot)]

if (length(left) > 1)
{
left <- quickSort(left)
}
if (length(right) > 1)
{
right <- quickSort(right)
}

# Return the sorted values.


return(c(left, pivot, right))
}

# take sample array


arr <- sample(1:100)
# call quickSort function
result <- quickSort(arr)

# print result
print(arr)
result
a <- result
print(a)
plot(a)
lines(log(a))
lines(a * log(a))
lines(a^2)
lines(a^(1/2))

III. Discussion of Results of Insertion Sort Algorithm

In Figure 1,Fig.1
in theInsertion_sort
top window wecode
can in
seeRstudio
the insertion
with sort algorithminwritten.
10 elements The letters that
the array.
appear in blue are comments which the processor ignores now to compile and run the algorithm.
If we observe the bottom window, we can see that the algorithm has been run with an array that
contains 10 elements which are unsorted, and the algorithm provides the array sorted out. For
redundancy, we can observe that the unsorted array is printed, followed by the sorted array to
make sure are algorithm is working properly. Lastly, if we observed the lower window, we could
also see the time it took to run the algorithm. The system.time() package provides the user time,
system time and the elapsed time. The times we are observing in figure 1, are based on the input
size of 10.

Figure 2. Environment window with values and functions

Another aspect important to point out is the window in the top right corner. There, we can find
the values and functions in the R project. In this project, I chose the insertion_sort and quick sort
which can be seen in the top right corner window under function and the values which are
variables can be used with the functions. If we observe the values, we can see the value arr is 10
element arrays unsorted. The other 3 variables are the array of 10 elements sorted with the values
sorted in 3 different variables.
The plot chart represented above is the insertion sort of linear growth with an
array of input size 10. We can see that the linear growth is a straight line with
a slope.

Figure 4. Plot of the run time of the insert algorithm based on 10


elements in an array.

The two figures above are the insertion sort(a) plot of an array of size 10 with linear growth, and
figure 4 is the corresponding system time it takes to run the algorithm. These times are being
taken with the array already sorted. The time obtained was 0.045 for user, 0.015 for system time
and 0.073 for the time elapsed.

F(a) = a^2
F(a) =(alog(a))
F(a) = a
The red line represents the insertion_sort algorithm run with an input of log(a), the green line
represents nlogn, the magenta line represents (a^2), the black line represents f(n) = a and the pink
line represents sqrt (a). The different growth rates can be appreciated with the plot chart and the
lines with different colors to represent the function. The two lowest growth rates are log(a) red
line and sqrt(a) which is represented with line purple.

IV. Discussion of Results of Insertion Sort for array of size 100

F(a) = a^2
F(a) =(alog(a))
F(a) = a
F = (sqrt(a))
F(a) = log(a)

(Plot chart legend)

Figure 6. Insertion_sort function with an array of size 100


The plot chart represented above represents the insertion sort algorithm growth rate using an
array of input size 100. The first input size used was of size 10, this plot uses an array of size
100. We can appreciate that as the size of the array increments the lines that represent growth
rate a^2 and a*log(a) increment faster. The two lines which are represented with color red and
green have greater slope when the input increases.

Figure 7. Code for Insert sort algorithm with run time displayed
for input of size 100.

The figure above represents the insert sort algorithm with an array of size 100. The algorithm can
be views in the upper screen. In the bottom screen we can see the last part of the array sorted in
order in addition to the time it took to run the algorithm with an array of size 100. We can also
observe that as the array increments the run time of the algorithm increments.
The plot chart in figure 8 represents the system run time it took to run the insertion sort algorithm
with an array of size 100. The plot chart corresponds to the user, system and elapsed time
represented in the bottom window of figure 7. The user time was 0.092, system time was 0.019
and elapsed time was 0.135.

Figure 9. R code for Insertion_sort algorithm with input size of 500.


Figure 9 represents the insertion sort algorithm with an input size 500. We can observe in the
bottom window the unsorted array displayed followed by the sorted array.

F(a) = a^2
F(a) =(alog(a))
F(a) = a
F = (sqrt(a))
F(a) = log(a)

(Plot chart legend)

Figure 10. Plot of insertion sort and different


growth rates with input size 500.
The plot chart in figure 10 represents the different growth rates for the insertion sort array with
input size 500. As we mentioned previously, as the array increments in size, the slops of a^2 and
a * log(a) increment faster, while the two slowest ones, the blue and red line which represent
sqrt(a) and log(a) run faster, and the lines almost overlap each other.

Figure 11. Plot chart of the runtime it took the insertion sort
algorithm to finish with input size of 500.

The plot chart above, represents the system run time for the insertion sort array of input size 500.
The figure below this one displays the sorted array in addition to displaying the output of the run
time. We can observe that the user time is 0.145, system time 0.016 and elapsed time of 0.177.
Figure 12. The system.time() displayed on the bottom screen for the insertion
sort algorithm running time with input size 500. The plot chart on the bottom
right window represents the system.time of the array.

Figure 13. Insertion sort algorithm for input size 1000 displaying the array unsorted.
Figure 14. Insertion sort algorithm with input size of 1000. Displaying the sorted array and
the time it took for the algorithm to run.

F(a) = a^2
F(a) = ((a)log(a))
F(a) = a
F = (sqrt(a))
F(a) = log(a)

Figure 15. Insertion_sort plot with input size of 1000.


The plot chart above represents the different growth rates for the insertion sort array size
1000. We can continue to observe that as the array increments in size, the lines a^2 and line
(a)*log(a) grow faster and the slope increment. The opposite happens with the lines sqrt(a)
and log(a) which almost overlap when the array keeps incrementing in size, which means is
running faster.
Figure 16. Insertion sort system.time plot of the time it took the insertion sort algorithm to
complete with input size of 1000.

The plot chart above represents the run system.time for the array of input size 1000. The time
displayed can be in the bottom window of figure 14. The user time displayed is 0.229, system
time displayed is 0.016 and the elapsed time is 0.261.

Figure 17. Insertion sort algorithm with input size 2000.


The bottom window displays the sorted array and the time. It took to run the algorithm.
The figure above represents the insertion sort array algorithm with an input size of 2000. The
upper left window has the entire algorithm, the bottom window displays the sorted array plus
the run time it took to run the algorithm with input size 2000. The bottom right window
displays the different growth rates depending on the function. The more the array increments in
size the a^2 and a *log(a) slope keeps incrementing, while log(a) and sqrt(a) keep getting faster.
F(a) = a^2
F(a) = ((a)log(a))
F(a) = a
F = (sqrt(a))
F(a) = log(a)

(Plot chart legend)

Figure 18. Plot chart of Insertion sort algorithm with input size
2000.
The plot chart above represents the different growth rates for the different function
when using insertion sort algorithm. We can continue to observe that as the array
size get bigger, the slopes for the first two lines increase which means the greater
the input the slower it runs. However, the last two lines which almost overlap each
other, represent that as the array keeps growing it becomes more efficient.

Figure 19. Plot chart of the run time of insertion algorithm


with an input size of 2000.

The plot chart in figure 19 represents the run time obtained using system.time function. If
we refer to figure 17, in the bottom lower window we can see the user, system and elapsed
time displayed. The user time obtained for this size input was 0.424 for user time, 0.018 for
system time and elapsed time of 0.468.
Figure 21. Insertion sort with factorial growth printed with
the system.time taken to run the algorithm.

Figure 22. Insertion sort plot chart run time of the algorithm including
factorial growth.
IV. Quick Sort Algorithm Results

A. Quick Sort Algorithm results with input size 10.

Figure 23. Quick sort algorithm with input size 10.

F(results) = results^2
F(results) = results!
F(results)= (results * log(results)
F(results) = results
F(results) = sqrt(results)
F(results) = log(results)

Figure 24. Quick Sort algorithm growth rates with


input size 10.
Next, we are going to discuss the quick sort algorithm and the results obtained from the
algorithm based on the input size. We start the discussion with an array of size 10. Looking at
figure 23, we can observe the quick sort algorithm implemented for this part. The algorithm can
be viewed in figure 23 in the upper screen and if we look at the bottom screen, we can see the
array of size 10 printed unsorted first and then printed sorted.
Looking at figure 24, we can observe the plot chart with the different growth rates when the
array is size 10. When the array contains a small sample size, the results^2 and results! (factorial)
grow almost at the same rate. Also, we can observe that when the array has a small sample
size ,10 in this case, the growth rate between sqrt(results) and log(results) is more
distinguishable.

Figure 25. Plot chart of the system.runtime of the quick sort algorithm with
input size 10
The plot chart above represents the quick sort run time when the array is size 10. In figure 26, we
can observe the quick sort algorithm and in the bottom window we can see the run time it took
for the quick sort algorithm to run and finish. Looking at figure 26, we can see that the user run
time was 0.038, the system time was 0.014 and the elapsed time was 0.064.
Figure 26. A closer look at the quick sort algorithm with input size 10. If we
observed the bottom window, we could see the runtime displayed which
corresponds to the plot chart in figure 25.
B. Quick Sort Algorithm results with input size 100.

Figure 27. Quick sort algorithm with input size 100. At the bottom right window, we
can see the different growth rates depend on the function used. Also in the lower
window, we can see the system.time displayed which is the time it took for the
algorithm to run.

In figure 27 in the upper left window, we can see the entire quick sort algorithm with an
array of size 100. After running the code, we can see the plot chart displayed in the lower
right corner with the different growth rates and speeds. Lastly, in the lower left window we
can view the time it took the algorithm to run with an input of size 100. It is important to
mentioned that we continue to see a tendency of the system run time incrementing when the
size of the arrays incremented.
F(results) = results^2
F(results) = results!
F(results)= (results * log(results)
F(results) = results
F(results) = sqrt(results)
F(results) = log(results)

Figure 28. Quick sort algorithm plot chart with input


size 100 and the different growth rates.
The plot chart above represents the different growth rates for the quick sort algorithm with an
array of size 100. Observing from the plot chart, the fastest growing rate is the green line which
represents the factorial growth rate. The second fastest growth rate is the quadratic function
represented by the blue line. On the opposite end, the quickest efficiency time are represented by
the magenta and red line. The magenta represents a growth rate of sqrt and the red line represents
the log function.

Figure 29. Quick sort plot chart of system.time execution to run the
algorithm with input size 100.
The plot chart in figure 29 represents the run time by the system when running the quick sort
algorithm with input size 100. The user run time was 0.057. the system time was 0.015 and the
elapsed time was 0.087. The graph in figure 29 represents these values in addition to
representing the different time fluctuations.

Figure 30. Quick Sort algorithm system.time displayed in bottom window. The plot
chart in the lower right corner is the plot chart representing the times obtained from
running the algorithm with input size 100.

The figure above represents the quick sort array with input size of 100 displaying the
unsorted array followed by the sorted array. If we look at the bottom of the main window,
we can observed the system.time displayed after running the algorithm. Finally, the plot
chart in the right window is the plot chart for the system. time.
C. Quick Sort Algorithm results with input size 500.

Figure 31. Upper window we can see the quick sort algorithm. In the
bottom window we can first see the array of size 500 unsorted followed
by the sorted array.

In figure 31 in the upper window, we can view the quick sort algorithm that was implemented.
Looking at the bottom window we can observe the unsorted array displayed first, followed by
the array sorted from 1 to 500.
c

Figure 32. Quick sort array sorted with input size 500. At the bottom we can
see the system.time it took for the algorithm to run for input of size 500.
Figure 32 displays the result of the array being sorted and at the end we can observed the
run time it took the quick sort algorithm to run with an input size of 500. The relationship
of the system time incrementing while the input size increments can be observed. This
means that the bigger the array, the more time it will take to run the algorithm.

F(results) = results!
F(results) = results ^2
F(results) = results * log(results)
F(results) = results
F(results) =sqrt(results)
F(results) = log(results)

Figure 33. Quick sort plot chart for input size 500 and the different growth rates.
The plot chart above represents the growth rates of the quick sort algorithm of array size 500.
The two slowest or inefficient growth rates or functions is the results! which is factorial
represented by the green line. The second slowest and inefficient growth rate is results^2
represented by the blue line. The most efficient growth rates or efficient which mean that are
the fastest are the sqrt(results) function and log(results) function. The magenta and red line
represent the fastest functions which almost overlap with each other.

Figure 34. Quick Sort system.time plot chart for the time it took the algorithm to
run with input of size 500

D. Quick Sort Algorithm results with input size 1000.

Figure 35. Quick sort algorithm with input size of 1000.


In the bottom window we can observed the array sorted and the system.time it took.
Next, we are going to discuss the quick sort array with input size of 1000. Thus far, we have
discuss the quick sort algorithm with arrays of input size, 10, 100, 500 and now a 1000. Figure
35 shows the quick sort algorithm with input size 1000. The upper window demonstrates the
quick sort algorithm. In the bottom window we can see the sorted array displayed as well as the
system run time. If we observe the system run time, it is consistent with the relationship that as
the size of the array increases, the run time is longer. We can see that the user time is 0.244, the
system time was 0.017 and the elapsed time was 0.276.

F(results) = results!
F(results) = results^2
F(results) = results * log(results)
F(results) = results
F(results) = sqrt(results)
F(results) = log(results)

Figure 36. Quick sort plot chart with input size 1000 and the different growth
rates.
The plot chart above represents the quick sort algorithm growth rates. The slowest
growth rates can be viewed by the green and blue lines, the green line represents the
factorial growth, and the blue line represents the quadratic growth. The fastest functions
are represented by the magenta and red line which are the closest to the x axis. The
magenta line represents the sqrt function growth, and the red line represents log growth
function. We can also see that the two lines almost overlap each other.
Figure. 37 Quick sort plot chart run system.time with input size 1000. The
chart represents the time displayed at the bottom window in figure 35.

The plot chart in figure 37 represents the system.time it took for the quick sort array
to complete running based on an array of input size 1000. The system times can be
viewed in figure 35 in the bottom window. System.time keeps incrementing as the
array size increments.

E. Quick Sort Algorithm results with input size 2000.

Figure 38. Quick sort algorithm with input size of 2000. We can see that the system only prints
until entry 1000, meaning it is too big of an array for the computer to display in its entirety.
In addition, we can see in the bottom window how long it took the algorithm to run using
system.time.
Looking at figure 38, we can see the quick sort algorithm for an array of input size 2000. In the
upper window we can observe the quick sort algorithm for input size 2000. The bottom screen is
also displaying the system.time it took the quick sort to run the algorithm with input size 2000.
We can continue to observe that as the array size increases, the run time increases also.

F(results) = results!
F(results) = results^2
F(results) = results * log(results)
F(results) = results
F(results) = sqrt(results)
F(results) = log(results)

Figure 39. Quick sort plot of input size 2000 with the different growth
rates.
The plot chart in figure 39 represents the quick sort algorithm growth rate with
the different functions. The bigger the array, the factorial function runs slower,
the same happens with results^2. The two functions factorial represented with a
green line and results ^2 represented with the blue line are the slowest. The
fastest functions are sqrt(results) represented with the magenta line and
log(results) represented with the red line which are basically overlapping each
other.

Figure 40. Quick sort run time with an array of size 2000. We can observe
the times displayed by the algorithm in figure 38 bottom window.
The plot chart in figure 40 represents the run time of the quick sort algorithm with an array of
input size 2000. Referring back to figure 38, the bottom window displays the system.time
calculated. The user time was 0.441, the system time was 0.017, and the elapsed time was
0.474. Comparing these values, we can see that the run time double using an array of size 2000
when compared to an array of size 1000.
References:

 Levitin, A. (2012). Introduction to the design & analysis of algorithms. Pearson.


 The R project for statistical computing. R. (n.d.). Retrieved February 11, 2023, from
https://www.r-project.org/
 Paradis, E. (2005). R for Beginners. Institut des Sciences de l'Evolution. Université
Montpellier II.

You might also like