Data structures and algorithms help you handle problems in a smart and efficient way.
It goes without a saying that they go hand in hand. For solving a problem with a given algorithm efficiently you need to put your data in a appropiate data structure that benefits the algorithm. Using a specific data structure will dictate which algorithms you can use.
This topic is very rich and can go very deep. Understanding the core data structures and algorithms helps you to understand what tools are out there, the more specific your challenge becomes that you try to solve, the more specific a certain data structure and algorithm gets.
The efficiency of your algorithm strongly depends also on the size of your data set that you need to processl. A certain algorithm might perform better on a small set of data, but much worse on a big data set, therefore it is commong that sort()
functions first probe the size of your data set and based on that might choose another algorithm that is known ot perform better for given data set size.
It’s also worth to take in consideration on how your typical data set will be structured or ordered. Statiscally a data set can be faily ordered already, or it can be a given that your data set is almost always sorted in a certain way. This can have an impact on the algorithm you choose.
To be able to decide what is an appropiate algorithm, you must understand the performance (time complexity) expressed in the big O notation. The performance can greatly vary based on the size of the data set and how the typical sample data set that you provide will look like (partialy ordered, always descending, etc…).
As you learn new algorithms, you will find the performance for each of the differen characteristics.
Data Structures often differ in their efficiency for each sorting algorithm and their basic operations (like read, insert, remove, update and search).
n
, we typically asume that integers are repesented by c lg n
bits for some constant c >= 1
. We require c >= 1
so that each word can hold the value of n
, enabling us to index the indivudual input elements, and we restrict c
to be constant so the word size does not grow arbitrarly. Because of this property, we can easily index in an array as each item will have the same word size and we kan O(1) access in an array.an² + bn + c
.n
in terms of the running time on smaller inputs. We can then use the mathematical tools to solve the recurrence and provide bounds on the performance of the algorithm.
c
: Some constantT(n)
: Running time on problem of size n
D(n)
: Time to divide the problem in subproblems.C(n)
: Time to combine the solutions of the subproblems into the solution of the original problem.a
: # of subproblems each of which is 1/b
the size of the original. It takes time T(n/b)
to solve one subproblem of size n/b
, and so it takes time aT(n/b)
to solve a
of then.O
must be Θ
here)
n <= c
) the time might be constant O(1)
.n > 1
, n
is an exact power of 2
elements applied with the merge sort algorithm:
D(n) = O(1)
.n/2
, which contributes 2T(n/2)
to the running time.n
-element subarray takes O(n)
, so C(n) = O(n)
.O
must be Θ
here) c
represents the time required to solve problems of size 1
as well as the time per array element of the divide and combine steps.It’s perfectly reasonable to divide the orginal problem into sub problems untill the subproblems are small enough, and then use a insertion sort on those subproblems as they might perform better on smaller subproblems/arrays.
For obtaining asymptotic Θ or O bounds on the solution.
T(n) = aT(n/b) + f(n)