CO-1 CH-1 Algorithms
CO-1 CH-1 Algorithms
Introduction
Algorithm Specification:
The word algorithm comes from the name of a Persian and Muslim mathematician Abu
Abdullah Muhammad ibn Musa Al-Khwarizmi, he was mathematician, astronomer and
geographer during the Abbasid Caliphate, a scholar in the House of Wisdom in Baghdad. This
word has taken a special significance in computer Science as it is used as a tool for solving a
well specified computational problem.
• Definition:
Or
An Algorithm is any well defined computational procedure that takes some value or set of values
as input and produces some value or set of values as output.
Or
• Specification of Algorithm:
1. Input: There are zero or more quantities that are externally supplied.
2. Output: At least one quantity is produced.
3. Definiteness: Each instruction is clear and unambiguous.
4. Finiteness: If we trace out the instructions of an algorithm, then for all cases, the
algorithm terminates after a finite number of steps.
5. Effectiveness: Every instruction must be basic enough to be carried out, in principle, by a
person using only pencil and paper. It is not enough that each operation be definite as in
(3); it also must be feasible.
In computational theory, one distinguishes between an algorithm and a program, the latter
of which does not have to satisfy the fourth condition. For example, we can think of an
operating system that continues in a wait loop until more jobs are entered. Such a program
does not terminate unless the system crashes. Since our programs will always terminate.
We can describe an algorithm in many ways. We can use a natural language like English,
although, if we select this option, we must make sure that the resulting instructions are
definite. Graphic representations called flowcharts are another possibility, but they work well
only if the algorithm is small and simple.
Suppose we must devise a program that sorts a set of n ≥ 1 integers. A simple solution is given
by the following:
From those integers that are currently unsorted, find the smallest and place it next in the sorted
list.
Although this statement adequately describes the sorting problem, it is not an algorithm since it
leaves several unanswered questions. For example, it does not tell us where and how the integers
are initially stored, or where we should place the result. We assume that the integers are stored in
an array, list, such that the ith integer is stored in the ith position, list [i ], 0 ≤ i < n.
Selection Sort - finding the smallest integer in the given list and interchanging it with list [i].
void sort(int list[],int n) {
int i, j, min, temp;
for (i = 0; i < n-1; i++) {
min = i;
for (j = i+1; j < n; j++)
if (list[j] < list[min])
min = j;
SWAP(list[i],list[min],temp);
}
}
Assume that we have n ≥ 1 distinct integers that are already sorted and stored in the array list.
That is, list [0] ≤ list [1] ≤ ... ≤ list [n-l]. We must figure out if an integer searchnum is in this list.
If it is we should return an index, i, such that list[i] = searchnum. If searchnum is not present, we
should return -1. Sincethe list is sorted we may use the following method to search for the value.
Let left and right, respectively, denote the left and right ends of the list to be searched.
Initially, left = 0 and right = n-1. Let middle = (left+right)/2 be the middle position in the list. If
we compare list [middle] with searchnum, we obtain one of three results:
Data Abstraction
We are familiar with the basic data types of C. These include char, int, float, and double.
Some of these data types may be modified by the keywords short, long, and unsigned.
Ultimately, the real world abstractions we wish to deal with must be represented in terms of
these data types.
In addition to these basic types, C helps us by providing two mechanisms for grouping
data together. These are the array and the structure. Arrays are collections of elements of the
same basic data type. They are declared implicitly, for example, int list[5] defines a five-element
array of integers whose legitimate subscripts are in the range 0 ... 4. Structs are collections of
elements whose data types need not be the same. They are explicitly defined. For example,
struct student {
char studentName;
int studentId;
char grade;
};
Defines a structure with three fields, two of type character and one of type integer. The structure
name is student. All programming languages provide at least a minimal set of predefined data
types, plus the ability to construct new, or user-defined types. It is appropriate to ask the
question, "What is a data type?"
Definition: A data type is a collection of objects and a set of operations that act on those
objects.
Whether your program is dealing with predefined data types or user-defined data
types,these two aspects must be considered: objects and operations. For example, the data type
intconsists of the objects {0, +1, -1, +2, -2, ..., INT-MAX, INT-MIN}, where INT_MAX and
INT_MIN are the largest and smallest integers that can be represented on your machine. (They
are defined in limits.h.) The operations on integers are many, and would certainly include the
arithmetic operators +, -, *, /, and %. There is also testing for equality/inequality and the
operation that assigns an integer to a variable.
In addition to knowing all of the facts about the operations on a data type, we might also
want to know about how the objects of the data type are represented. For example on most
computers a char is represented as a bit string occupying 1 byte of memory, where as an int
might occupy 2 or possibly 4 bytes of memory. If 2 eight-bit bytes are used, then INT_MAX is
215 -1 = 32,767.
Knowing the representation of the objects of a data type can be useful and dangerous. By
knowing the representation we can often write algorithms that make use of it. However, if we
ever want to change the representation of these objects, we also must change the routines that
make use of it. It has been observed by many software designers that hiding the representation of
objects of a data type from its users is a good design strategy. In that case, the user is constrained
to manipulate the objects solely through the functions that are provided. The designer may still
alter the representation as long as the new implementations of the operations do not change the
user interface.
Definition: An Abstract Data Type (ADT) is a data type that is organized in such a way that the
specification of the objects and the specification of the operations on the objects is separated
from the representation of the objects and the implementation of the operations.
The specification consists of the names of every function, the type of its arguments, and
the type of its result. There should also be a description of what the function does, but without
appealing to internal representation or implementation details. This requirement is quite
important, and it implies that an abstract data type is implementation-independent.
ADT NaturalNumber is
Objects: an ordered subrange of the integers starting at zero and ending at the maximum integer
(lNT -MAX) on the computer.
Functions:
for all x, y ∈ NaturalNumber; TRUE, FALSE ∈ Boolean
where +, -, <, and == are the usual integer operations.
NaturalNumber Zero() :: = 0
The ADT definition begins with the name of the ADT. There are two main sections in the
definition: the objects and the functions.
✓ The objects are defined in terms of the integers, but we make no explicit reference to
their representation.
✓ The function definitions are a bit more complicated. First, the definitions use the symbols
x and y to denote two elements of the data type NaturalNumber, while TRUE and FALSE
are elements of the data type Boolean. In addition, the definition makes use of functions
that are defined on the set of integers, namely, plus, minus, equals, and less than. For
each function, we place the result type to the left of the function name and a definition of
the function to the right. The symbols "::=" should be read as "is defined as."
Functions:
• The first function, Zero, has no arguments and returns the natural number zero. This is a
constructor function.
• The function Successor(x) returns the next natural number in sequence. This is an
example of a transformer function. Notice that if there is no next number in sequence,
that is, if the value of x is already INT_MAX, then we define the action of Successor to
return INT_MAX. Some programmers might prefer that in such a case Successor return
an error flag.
• Other transformer functions are Add and Subtract. They might also return an error
condition, although here we decided to return an element of the set NaturalNumber.
Performance Analysis:
If we want to travel from 'City - A' to 'City - B', there can be many ways of doing this.
We can go by flight, by bus, by train and also by bicycle. Depending on the availability and
convenience, we choose the one which suits us. Similarly, in computer science, there are
multiple algorithms to solve a problem. When we have more than one algorithm to solve a
problem, we need to select the best one. Performance analysis helps us to select the best
algorithm from multiple algorithms to solve a problem. When there are multiple alternative
algorithms to solve a problem, we analyze them and pick the one which is best suitable for our
requirements. To compare algorithms, we use a set of parameters or set of elements like memory
required by that algorithm, the execution speed of that algorithm i.e., Space Complexity and
Time Complexity.
Space complexity: The amount of computer memory required to run an application. Space
complexity can be broadly classified into two types. Fixed or constant space complexity and
Linear space complexity.
✓ In Fixed or constant space complexity the size of space consumed will not be increased
with the increase of input size. Consider the following example “ Square of the given
Number”
int getSquare (int n) {
return (n * n);
}
Here we can solve the problem without consuming any extra space, hence the space
complexity is constant even if the input size increases.
✓ In Linear space complexity the space consumed will be increased with the increase of
input size. Consider the following example “Sum of Array elements”
int calculate_sum(int arr[], int len){
int total_sum = 0;
int i = 0;
for( i= 0; i< len; i++) {
total_sum = total_sum + arr[i];
}
}
From the above code, we can see that:
A variable “total_sum” that takes constant sum of 1 unit
But the variable arr[] is an array, it’s space consumption increases with the increase of
input size.
Hence the total time taken to execute is = “2N+3”. For larger value of N, we ignore the
constants, hence the final time complexity is “O(N)” times.
int add_matrix( int a[m] [n], int b [m] [n], int m, int n) {
for (i = 0; i< n; i++) {
for(j = 0; j<n; j++){
c[i][j] = a[i][j] + b[i][j]
}
}
}
For larger value of “n” we ignore the constants, hence total time taken to execute is O(n^2).
Asymptotic Notations
Asymptotic analysis of an algorithm refers to defining the mathematical bound of its run-
time performance. Using asymptotic analysis, we can very well conclude the best case, average
case, and worst case scenario of an algorithm. Asymptotic analysis is input bound i.e., if there's
no input to the algorithm, it is concluded to work in a constant time. Other than the "input" all
other factors are considered constant.
Asymptotic Notations:
Consider function f(n) as time complexity of an algorithm and g(n) is the most significant term.
If f(n) <= C g(n) for all n >= n0, C > 0 and n0 >= 1. Then we can represent f(n) as O(g(n)).
Omega Notation, Ω
Theta Notation, θ
Constant − Ο(1)
Logarithmic − Ο(log n)
Linear − Ο(n)
Quadratic − Ο(n2)
Cubic − Ο(n3)
Polynomial − nΟ(1)
Exponential − 2Ο(n)
Searching: In computer science, searching is the process of finding an item with specified
properties from a collection of items. The items may be stored as records in a database, simple
data elements in arrays, text in files, nodes in trees, vertices and edges in graphs, or they may be
elements of other search spaces.
Searching is one of the core computer science algorithms. We know that today’s computers store
a lot of information. To retrieve this information proficiently we need very efficient searching
algorithms. There are certain ways of organizing the data that improves the searching process.
That means, if we keep the data in proper order, it is easy to search the required element. Sorting
is one of the techniques for making the elements ordered. In this chapter we will see different
searching algorithms.
Types of Searching
✓ Linear/Sequential Search
✓ Binary Search
• Linear Search: Linear Search is also called as Sequential Search. In Linear search, Search
for a key within an array one by one until it finds in. In an unordered array, linear search
would have to check the entire array until it found the desired value.
#include <stdio.h>
int main() {
int a[20], n, i, key, search_result;
printf("Number of Elements in the array:");
scanf("%d",&n);
search_result = linear_search(a,n,key);
if(search_result>=0)
printf("Search Key %d is found @ %d Location",key, search_result);
else
printf("Search Key %d is Not found ",key);
return 0;
}
Output:
Number of Elements in the array:5 Number of Elements in the array:5
Enter Array Elements: a[0]=34 Enter Array Elements: a[0]=34
a[1]=23 a[1]=23
a[2]=56 a[2]=56
a[3]=32 a[3]=32
a[4]=40 a[4]=40
What is your Search Key?:40 What is your Search Key?:10
Search Key 40 is found @ 4 Location Search Key 10 is Not found
Binary Search, Search a sorted array by repeatedly dividing the search interval in half. Begin with
an interval covering the whole array. If the value of the search key is less than the item in the middle of
the interval, narrow the interval to the lower half. Otherwise, narrow it to the upper half. Repeatedly
check until the value is found or the interval is empty.
int main()
{
int a[20],n,i,key,search_result=-1;
printf("Number of Elements in the array:");
scanf("%d",&n);
search_result = binary_search(a,n,key);
if(search_result>=0)
printf("Search Key %d is found @ %d Location",key, search_result);
else
printf("Search Key %d is Not found ",key);
return 0;
}
OUTPUT:
Number of Elements in the array:5 Number of Elements in the array:5
Enter Array Elements: a[0]=23 Enter Array Elements: a[0]=23
a[1]=32 a[1]=32
a[2]=34 a[2]=34
a[3]=40 a[3]=40
a[4]=56 a[4]=56
What is your Search Key:40 What is your Search Key:10
Search Key 40 is found @ 3 Location Search Key 10 is Not found
• At Iteration 1,
Length of array = n
• At Iteration 2,
Length of array = n⁄2
• At Iteration 3,
Length of array = (n⁄2)⁄2 = n⁄22
• Therefore
Length of array = n⁄2k = 1
=> n = 2k
• As (loga (a) = 1)
Therefore,
=> k = log2 (n)
Questions: