























































































Study with the several resources on Docsity
Earn points by helping other students or get them with a premium plan
Prepare for your exams
Study with the several resources on Docsity
Earn points to download
Earn points by helping other students or get them with a premium plan
everything stated there in very short manner so i hope u enjoy it!
Typology: Lecture notes
1 / 95
This page cannot be seen from the preview
Don't miss anything!
























































































February, 2013 Debre Tabor
Introduction of Data Structures (Linear ,non-Linear Data Structures) and Algorithm Analysis Concept, Measuring Complexity, Complexity of Algorithm Big-O notation. Simple Sorting and Searching Algorithms (Bubble Sort, Insertion Sort, Selection Sort, Sequential Searching, Binary Searching.). Abstract Data Types, Structures, Pointers, Arrays, Linked Lists, Stacks, Queues, Trees, Graphs. Advanced Sorting and Searching Algorithms (Shell Sort, Quick Sort, heap Sort, Merge Sort, and Hashing). These contents will be delivered to the students through brain storming, group discussion, observation/demonstration, test and mini lecture. And students assessed with lab exercise, quiz, group work and individual assignment.
At the end of the course students will be able to:-
A program is written in order to solve a problem. A solution to a problem actually consists of two things:
The way data are organized in a computer’s memory is said to be Data Structure and the
sequence of computational steps to solve a problem is said to be an algorithm. Therefore, a program is nothing but data structures plus algorithms.
Given a problem, the first step to solve the problem is obtaining ones own abstract view, or model , of the problem. This process of modeling is called^ abstraction.
The model defines an abstract view to the problem. This implies that the model focuses only on problem related stuff and that a programmer tries to define the properties of the problem.
These properties include
With abstraction you create a well-defined entity that can be properly handled. These
entities define the data structure^ of the program.
An entity with the properties just described is called an abstract data type (ADT).
An ADT consists of an abstract data structure and operations. Put in other terms, an ADT is an abstraction of a data structure.
The ADT specifies:
A data structure is a language construct that the programmer has defined in order to implement an abstract data type.
There are lots of formalized and standard Abstract data types such as Stacks, Queues, Trees, etc.
Do all characteristics need to be modeled? Not at all
Abstraction is a process of classifying characteristics as relevant and irrelevant for the particular purpose at hand and ignoring the irrelevant ones.
Applying abstraction correctly is the essence of successful programming
How do data structures model the world or some part of the world?
Where are algorithms, then?
Algorithm analysis refers to the process of determining how much computing time and
storage that algorithms will require. In other words, it’s a process of predicting the resource requirement of algorithms in a given environment.
In order to solve a problem, there are many possible algorithms. One has to be able to
choose the best algorithm for the problem at hand using some scientific method. To classify some data structures and algorithms as good, we need precise ways of analyzing them in terms of resource requirement. The main resources are:
Running time is usually treated as the most important since computational time is the most precious resource in most problem domains.
There are two approaches to measure the efficiency of algorithms: Empirical: Programming competing algorithms and trying them on different instances. Theoretical: Determining the quantity of resources required mathematically (Execution time, memory space, etc.) needed by each algorithm.
However, it is difficult to use actual clock-time as a consistent measure of an algorithm’s efficiency, because clock-time can vary based on many things. For example,
Accordingly, we can analyze an algorithm according to the number of operations required, rather than according to an absolute amount of time involved. This can show how an algorithm’s efficiency changes according to the size of the input.
Complexity Analysis is the systematic study of the cost of computation, measured either in time units or in operations performed, or in the amount of storage space required.
The goal is to have a meaningful measure that permits comparison of algorithms independent of operating platform. There are two things to consider:
Complexity analysis involves two distinct phases:
There is no generally accepted set of rules for algorithm analysis. However, an exact count of operations is commonly used.
1 for the assignment statement: int k= 1 for the output statement. 1 for the input statement. In the for loop: 1 assignment, n+1 tests, and n increments.
In the above examples we have seen that analysis so complex. However, it can be
simplified by using some formal approach in which case we can ignore initializations, loop control, and book keeping.
For Loops: Formally
In general, a for loop translates to a summation. The index and bounds of the summation are the same as the index and bounds of the for loop.
Suppose we count the number of additions that are done. There is 1 addition per iteration of the loop, hence N additions in total.
Nested Loops: Formally Nested for loops translate into multiple summations, one for each for loop.
Again, count the number of additions. The outer summation is for the outer for loop.
Consecutive Statements: Formally Add the running times of the separate blocks of your code
Conditionals: Formally If (test) s1 else s2: Compute the maximum of the running time for s1 and s2.
Exercises
Determine the run time equation and complexity of each of the following code segments.
for (int i=0; i<n; i++) for (int j=i; j<n; j++) k++; What is the value of k when n is equal to 20?
What is the correct big-Oh Notation for the above code segment?
In order to determine the running time of an algorithm it is possible to define three functions T (^) best (n) , Tavg (n) and T (^) worst (n) as the best, the average and the worst case running
time of the algorithm respectively.
Average Case (Tavg ): The amount of time the algorithm takes on an "average" set of
inputs.
Worst Case (T (^) worst): The amount of time the algorithm takes on the worst possible set of inputs.
Best Case (T (^) best ): The amount of time the algorithm takes on the smallest possible set of
inputs.
4n <=4n^2 for all n>=1 and 1<=n 2 for all n>=
3n 2 +4n+1<=3n^2 +4n^2 +n^2 for all n>=
<=8n^2 for all n>=
So we have shown that f(n)<=8n^2 for all n>=
Therefore, f (n) is O(n 2 ) (c=8,k=1)
Typical Orders Here is a table of some typical cases. This uses logarithms to base 2, but these are simply proportional to logarithms in other base.
N O(1) O(log n) O(n) O(n log n) O(n 2 ) O(n^3 ) 1 1 1 1 1 1 1 2 1 1 2 2 4 8 4 1 2 4 8 16 64 8 1 3 8 24 64 512 16 1 4 16 64 256 4, 1024 1 10 1,024 10,240 1,048,576 1,073,741,
Demonstrating that a function f(n) is big-O of a function g(n) requires that we find specific constants c and k for which the inequality holds (and show that the inequality does in fact hold). Big-O expresses an upper bound on the growth rate of a function, for sufficiently large values of n.
An upper bound is the best algorithmic solution that has been found for a problem. “ What is the best that we know we can do?” Exercise: f(n) = (3/2)n^2 +(5/2)n- Show that f(n)= O(n^2 )
In simple words, f (n) =O(g(n)) means that the growth rate of f(n) is less than or equal to g(n).
For all the following theorems, assume that f(n) is a function of n and that k is an arbitrary constant.
Theorem 1 : k is O(1) Theorem 2 : A polynomial is O(the term containing the highest power of n). Polynomial’s growth rate is determined by the leading term
In general, f(n) is big-O of the dominant term of f(n).
Theorem 3 : k*f(n) is O(f(n)) Constant factors may be ignored E.g. f(n) =7n^4 +3n^2 +5n+1000 is O(n 4 )
Theorem 4(Transitivity) : If f(n) is O(g(n))and g(n) is O(h(n)), then f(n) is O(h(n)).
Theorem 5 : For any base b, log b(n) is O(logn). All logarithms grow at the same rate log bn is O( log dn) F 02 2 b, d > 1
Theorem 6: Each of the following functions is big-O of its successors: k logbn n nlogbn n^2 n to higher powers 2n 3 n larger constants to the nth power n! nn
f(n)= 3nlogbn + 4 logbn+2 is O(nlog (^) bn) and )(n^2 ) and O(2 n)
Higher powers grow faster nr^ F 02 0is F 02 0F 02 0O( ns^ ) if 0 <= r <= s
Fastest growing term dominates a sum
If f(n) is O(g(n)), then f(n) + g(n) is O(g) E.g 5n^4 + 6n3 is O (n^4 ) F 0 2 0
F 0 2 0
F 0 Exponential functions grow faster than powers, i.e. is (^) 2 0O( b n F 0 ) (^) 2 2 F 0 2 2 b > 1 and k >= 0 E.g. n^20 is O( 1.05^ n) Logarithms grow more slowly than powers logb n F 02 0isF 02 0 F 02 0O( nk) F 02 2F 02 2 b > 1 and k >= 0 E.g. log2n is O( n 0.5)
=O(n^3 )
f(n)=o(g(n)) means for all c>0 there exists some k>0 such that f(n)<c.g(n) for all n>=k. Informally, f(n)=o(g(n)) means f(n) becomes insignificant relative to g(n) as n approaches infinity.
Example : f(n)=3n+4 is o(n 2 )
In simple terms, f(n) has less growth rate compared to g(n). g(n)= 2n^2 g(n) =o(n^3 ), O(n^2 ), g(n) is not o(n^2 ).
Little-omega (F 07 7 ) notation is to big-omega (F 05 7 ) notation as little-o notation is to Big-Oh notation. We use F 07 7 notation to denote a lower bound that is not asymptotically tight. Formal Definition : f(n)= F 07 7 (g(n)) if there exists a constant no>0 such that 0<= c. g(n)<f(n) for all n>=k. Example : 2n^2 =F 07 7 (n) but it’s not F 05 7 (n).
Transitivity
Symmetry
Assessment
void func() { int x=0; int i=0; int j=1; cout<< “Enter an Integer value”; cin>>n; while (i<n){ x++; i++; } while (j<n) { j++; } }
second. How long would it take to execute an algorithm whose complexity function was: T (n) = 2n 2 on an input size of n=10^8?
Answer
1 for the first assignment statement: x=0; 1 for the second assignment statement: i=0; 1 for the third assignment statement: j=1; 1 for the output statement. 1 for the input statement. In the first while loop: n+1 tests n loops of 2 units for the two increment (addition) operations In the second while loop: n tests n-1 increments
Searching is a process of looking for a specific element in a list of items or determining that the item is not in the list. There are two simple searching algorithms:
Pseudocode
Loop through the array starting at the first element until the value of target matches one of the array elements.
If a match is not found, return –1.
Time is proportional to the size of input ( n) and
we call this time complexity O(n)
Example Implementation:
int Linear_Search(int list[], int key) { int index=0; int found=0; do{ if(key==list[index]) found=1; else index++; }while(found==0&&index<n); if(found==0) index=-1; return index; }
Brain Storming: - What do you think about Binary search?
This searching algorithms works only on an ordered list.
The basic idea is:
The computational time for this algorithm is proportional to log (^) 2 n
. Therefore the time complexity is O ( log n)
Example Implementation:
int Binary_Search(int list[],int k)
{ int left=0; int right=n-1; int found=0; do{ mid=(left+right)/2; if(key==list[mid]) found=1; else{ if(key<list[mid]) right=mid-1; else left=mid+1; } }while(found==0&&left<right); if(found==0) index=-1; else index=mid; return index; }
Sorting is one of the most important operations performed by computers. Sorting is a process of reordering a list of items in either increasing or decreasing order. The following are simple sorting algorithms used to sort small-sized lists.