Professional Documents
Culture Documents
Review
common mans belief is that a computer can do anything and everything that he imagines. It is very difficult to make people realize that it is not really the computer but the man behind computer who does everything.
In the modern internet world, man feels that just by entering what he wants to search into the computers he can get information as desired by him. He believes that, this is done by computer. A common man seldom understands that a man made procedure called search has done the entire job and the only support provided by the computer is the execution speed and organized storage of information. In the above instance, a designer of the information system should know what one frequently searches for. He should make a structured organization of all those details to store in memory of the computer. Based on the requirement, the right information is brought out. This is accomplished through a set of instructions created by the designer of the information system to search the right information matching the requirement of the user. This set of instructions is termed as program. It should be evident by now that it is not the computer, which generates automatically the program but it is the designer of the information system who has created this. Thus, the program is the one, which through the medium of the computer executes to perform all the activities as desired by a user. This implies that programming a computer is more important than the computer itself while solving a problem using a computer and this part of programming has got to be done by the man behind the computer. Even at this stage, one should not quickly jump to a conclusion that coding is programming. Coding is perhaps the last stage in the process of programming. Programming involves various activities form the stage of conceiving the problem up to the stage of creating a model to solve the problem. The formal representation of this model as a sequence of instructions is called an algorithm and coded algorithm in a specific computer language is called a program.
BSIT 41 Algorithms
Chapter 1 - Review
One can now experience that the focus is shifted from computer to computer programming and then to creating an algorithm. This is algorithm design, heart of problem solving.
BSIT 41 Algorithms
In other words, viewed little more formally, an algorithm is a step by step formalization of a mapping function to map input set onto an output set. The problem of writing down the correct algorithm for the above problem of brushing the teeth is left to the reader.
Chapter 1 - Review
Once an algorithm has been devised, it becomes necessary to show that it works. i.e it computes the correct answer to all possible, legal inputs. One simple way is to code it into a program. However, converting the algorithms into programs is a time consuming process. Hence, it is essential to be reasonably sure about the effectiveness of the algorithm before it is coded. This process, at the algorithm level, is called validation. Several mathematical and other empirical methods of validation are available. Providing the validation of an algorithm is a fairly complex process and most often a complete theoretical validation, though desirable, may not be provided. Alternately, algorithm segments, which have been proved else where may be used and the overall working algorithm may be empirically validated for several test cases. Such methods, although suffice in most cases, may often lead to the presence of unidentified bugs or side effects later on.
BSIT 41 Algorithms
The pseudo code used resembles PASCAL and C language control structures. Hence, it is expected that the reader be aware of PASCAL/C. Even otherwise at least now it is required that the reader should know preferably C to practically test the algorithm in this course work. However, for the sake of completion we present the commonly employed control constructs present in the algorithms. 1. A conditional statement has the following form If < condition> then Block 1 Else Block 2 If end. This pseudo code executes block1 if the condition is true otherwise block2 is executed. 2. The two types of loop structures are counter based and conditional based and they are as follows For variable = value1 to value2 do Block For end Here the block is executed for all the values of the variable from value 1 to value 2. There are two types of conditional looping, while type and repeat type. While (condition) do Block While end. Here block gets executed as long as the condition is true. Repeat Block Until<condition> Here block is executed as long as condition is false. It may be observed that the block is executed at least once in repeat type.
6
SUMMARY
Chapter 1 - Review
In this chapter, the concepts of algorithm are presented and the properties of the algorithm are also given. The concept of designing algorithm is explained with a specific example. The concepts of validating the algorithms and test the devised algorithms is also presented.
EXERCISE
1. 2. 3. 4. __________ is the process of executing a correct program on data sets and measuring the time and space it takes to compute the results. Define algorithm? What are its properties What is debugging and What is profiling? One of the properties of an algorithm is beauty (true / false)
Chapter 2
2.1 FUNDAMENTALS
ata structure is a method of organizing data with a sort of relationship with an intension of enhancing the qualities of associated algorithms. In this chapter, we review only the non-primitive data structures. The non-primitive data structures can be broadly classified into two types linear and non-linear data structures. Under linear data structures Arrays, Stacks and Queues and under nonlinear data structures graphs and trees are reviewed.
BSIT 41 Algorithms
8
Read (A, i) g e element at ith position; Search (A, e) g Boolean;
Any array is associated with a lower bound l and an upper bound u in general. When the array is created then it starts at some base address B. Since the computer is byte addressable, each address can hold a byte. If an integer takes 2 bytes for representation and if B=1000 and if l=1, then the 1st element is at (1000 + 0)th location 2nd element is at (1000 + 2)th location 3rd element is at (1000 + 4)th location .. .. .. ith element is at (1000 + (i-1)*2 )th location In general, if w is the size of the data element, then i th element is at (B + (i l) w)th location. i.e., A[i] = B + (i l) w.
l2 l1 l1+1 l1+2 . u1
l2+1
l2+2
l2+3
l2+4 . u2
BSIT 41 Algorithms
Although we have an nm matrix representation the allocations is not in the form of matrix but is contiguous in nature and will be as shown below. Incase if l1=1, and l2=1 the indices start at [1, 1].
1,1
1,2
1,3
1,m 2,1
2,2
2,3
2,m .
.. n,1
n,2
. n,m
Given the indices (i, j), the address can be computed using A[i, j] = B + (i-1) m+ (j-1). In general, if li i ui and lj j uj , then A[i, j] = B + { (i - li ) (uj lj +1) +(j - lj )}w. For higher n-dimensional arrays, the address can be computed as A( i1, i2, i3, .in) where l1 i1 u1, l2 i2 u2, ln in un A( i1, i2, i3, .in) = B + { (i1 - l1) (u2 - l2 +1)(u3-l3+1) .(un- ln+1) + (i2 - l2) (u3 - l3 +1)(u4-l4+1) . (un- ln+1) + (i3 - l3) (u4 - l4 +1) (u5-l5+1) .(un- ln+1) + + (in-1 - ln-1) (un - ln +1) + (in- ln) }w The algorithm thus designed to compute the row major address is as follows Algorithm: Address Computation (Row Major) Input: (1) n, dimension (2) l1, l2, l3, ln n lower limits (3) u1, u2, u3, un n upper limits (4) w, word size (5) i1, i2, i3, ., in values of subscripts (6) B, the base address Output: A address of the element at (i1, i2, i3, ., in) Method:
n A = B + (i j l j ) Pj w j =1 where Pj =
k = j +1
(u
lk + 1)
Algorithm ends.
10 2.2.2 Stacks
A stack is an ordered list in which all insertions and deletions are made at one end, called the top. Stack is a linear data structure which works based on the strategy last-in-first out (LIFO). It is a linear data structure which is open for operations at only one end (both insertions and deletions are defined at only one end). One natural example of stack, which arises in computer programming, is the processing of procedure calls and their terminations. Stacks are generally used to remember things in reverse. It finds a major use in backtracking approaches. Some of the functions related to a stack are Create ( ) g S; Insertion(S, e) g updated S; Deletion (S) g S, e; Isfull(S) g Boolean; Isempty(S) g Boolean; Top(S) g e; Destroy(S) It has to be noted that with respect to a stack, insertion and deletion operations are, in general, called PUSH and POP operations respectively. Following are the algorithms for some functions of stack. Algorithm: Create Output: S, Stack created Method: Declare S[SIZE] //Array of size=SIZE Declare and Initialize T=0 Algorithm ends Algorithm: Isempty Input: S, stack Output: Boolean //Top pointer to remember the number of elements
BSIT 41 Algorithms
11
Method: If (T==0) Return (yes) Else Return (no) If end Algorithm ends Algorithm: Isfull Input: S, stack Output: Boolean Method: If (T==SIZE) Return (yes) Else Return (no) If end Algorithm ends Algorithm: Push Input: (1) S, stack; (2) e, element to be inserted; (3) SIZE, size of the stack; (4) T, the top pointer Output: (1) S, updated; (2) T, updated Method: If (Isfull(S)) then Print (stack overflow) Else T=T+1; S[T] =e If end Algorithm ends
12
Algorithm: Pop Input: (1) S, stack;
Output: (1) S, updated; (2) T, updated (3) e element popped Method: If (Isempty(S)) then Print (stack is empty) Else e = S[T] T=T-1; If end Algorithm ends
2.2.3 Queues
A queue is an ordered list in which all insertions take place at one end called the rear end, while all deletions take place at the other end called the front end. Queue is a linear data structure which works based on the strategy first-in-first out (FIFO). Unlike stacks, queues also arise quite naturally in the computer solution of many problems. Perhaps the most common occurrence of a queue in computer applications is for scheduling of jobs. A minimal set of useful operations on queue includes the following. Create ( ) g Q; Insertion (Q, e) g updated Q; Deletion (Q) g Q, e; Isfull (Q) g Boolean; Isempty (Q) g Boolean; Front (Q) g e; Back (Q); Destroy (Q); Following are the algorithms for some functions of queue. Algorithm: Create Output: Q, Queue created
BSIT 41 Algorithms
13
Method: Declare Q[SIZE] //Array with size=SIZE Declare and Initialize F=0, R=0 //Front and Rear pointers to keep track of the front element and the rear element respectively Algorithm ends Algorithm: Isempty Input: Q, Queue Output: Boolean Method: If (F==0) Return (yes) Else Return (no) If end Algorithm ends Algorithm: Isfull Input: Q, Queue Output: Boolean Method: If (R==SIZE) Return (yes) Else Return (no) If end Algorithm ends
14
Algorithm: Front Input: Q, Queue Output: element in the front Method: If (Isempty (Q)) Print no front element Else Return (Q[F]) If end Algorithm ends Algorithm: Rear Input: Q, Queue Output: element in the rear Method: If (Isempty (Q)) Print no back element Else Return (Q[R]) If end Algorithm ends Algorithm: Insertion
Input: (1) Q, Queue; (2) e, element to be inserted; (3) SIZE, size of the Queue; (4) F, the front pointer; (5) R, the rear pointer Output: (1) Q, updated; (2) F, updated; (3) R, updated
BSIT 41 Algorithms
15
Method: If (Isfull (Q)) then Print (overflow) Else R=R+1; Q[R]=e If (F==0) F=1; If end If end Algorithm ends Algorithm: Deletion Input: (1) Q, Queue; (2) SIZE, size of the Queue; (3) F, the front pointer; (4) R, the rear pointer Output: (1) Q, updated; (2) F, updated; (3) R, updated; (4) e, element if deleted; Method: If (Isempty (Q)) then Print (Queue is empty) Else e = Q[F] If (F==R) F=R=0; Else F=F+1; If end If end Algorithm ends
16
However, the linear queue makes less utilization of memory i.e., the return (isfull (Q)) =yes does not necessarily imply that there are n elements in the queue. This can be overcome by the using an alternate queue called the circular queue.
BSIT 41 Algorithms
17
Method: If (Isempty (CQ)) then Print (Queue is empty) Else e = CQ[F] If (F==R) F=R=0; Else F=F mod SIZE +1; If end If end Algorithm ends
The number of elements adjacent to a given element is called arity or the degree of the element. i.e., degree = number of relations the element has with others. There is no upper limit placed on this number.
Some of the examples in general are : Friendship among classmates; family structure; University with every component being a sub-component and the relations among them being non-linear; the nervous system of the human body, etc. Few of the specific to Computer Science are: graph, tree.
18
Fig. 2.1
edge ek are called the end vertices of ek. The most common representation of graph is by means of a diagram, in which the vertices are represented as points and each edge as a line segment joining its end vertices. In the Fig. 2.1 edge e1 having same vertex as both its end vertices is called a self-loop. There may be more than one edge associated with a given pair of vertices, for example e4 and e5 in Fig. 2.1. Such edges are referred to as parallel edges. A graph that has neither self-loop nor parallel edges are called a simple graph, otherwise it is called general graph. It should also be noted that, in drawing a graph, it is immaterial whether the lines are drawn straight or curved, long or short: what is important is the incidence between the edges and vertices. Because of its inherent simplicity, graph theory has a very wide range of applications in engineering, physical, social, and biological sciences, linguistics, and in numerous other areas. A graph can be used to represent almost any physical situation involving discrete objects and a relationship among them.
BSIT 41 Algorithms
19
Fig. 2.2 Graph containing isolated vertices, series edges and a pendant vertex.
In the definition of a graph G = (V, E), it is possible for the edge set E to be empty. Such a graph, without any edges, is called a null graph. In other words, every vertex in a null graph is an isolated vertex. A null graph of six vertices is shown in Fig. 2-3. Although the edge set E may be empty, the vertex set V must not be empty; otherwise, there is no graph. In other words, by definition, a graph must have at least one vertex.
Although a pictorial representation of a graph is very convenient for a visual study, other representations are better for computer processing. A matrix is a convenient and useful way of representing a graph to a computer. Matrices lend themselves easily to mechanical manipulations. Besides, many known results of matrix algebra can be readily applied to study the structural properties of graphs from an algebraic point of view. In many applications of graph theory, such as in electrical network analysis and operation research, matrices also turn out to be the natural way of expressing the problem.
Fig. 2.4
if (vi , v j ) belongs to E G. The entries in the matrix are either zero or one. i.e., X = otherwise 0
Thus the matrix where each column and row corresponds to the vertex in the graph G shown in Fig. 2.4 is
V1 V2 V3 V4 V5 V6
V1 0 1 0 0 1 0
V2 1 0 1 1 1 0
V3 0 1 0 0 0 0
V4 0 1 0 0 1 1 (2)
V5 1 1 0 1 0 0
V6 0 0 0 1 (2) 0 0
This matrix X uniquely represents the graph. It is indeed possible to reconstruct the graph back from the matrix. The high entry in the matrix says the vertex corresponding to the row and vertex corresponding
BSIT 41 Algorithms
21
to the column is adjacent. Since, two vertices are adjacent if there is an edge connecting them, and the matrix represents the same, the above matrix X is called an adjacency matrix. Adjacency matrix is a symmetric matrix. If the diagonal elements are high then the graph has a self loop, the respective row index gives the vertex label with self loop. The sum of the ith row elements gives the degree of the vertex Vi. While calculating the row sum of the adjacency matrix of a non-simple graph, a weightage 1 has to be given if the diagonal cell is high and additional weightage to every parallel edge.
a v1 v2 v3 v4 v5 v6 0 0 0 1 0 1
b 0 0 0 1 0 1
c 0 0 0 1 1 0
d 1 0 0 0 1 0
(b)
e 0 1 0 1 0 0
f 1 1 0 0 0 0
g 0 1 0 0 1 0
h 0 1 1 0 0 0
Such a matrix A is called the vertex-edge incidence matrix, or simply incidence matrix. Matrix A for a graph G is sometimes also written as A(G). A graph and its incidence matrix are shown in Fig. 2.4 and Fig. 2.5 respectively. The incidence matrix contains only two elements, 0 and 1. Such a matrix is called a binary matrix or a (0, 1)-matrix. The following observations about the incidence matrix A can readily be made: 1. Since every edge is incident on exactly two vertices, each column of A has exactly two1s. 2. The number of 1s in each row equals the degree of the corresponding vertex. 3. A row with all 0s, therefore, represents an isolated vertex.
22
4. Parallel edges in a graph produce identical columns in its incidence matrix, for example, columns 1 and 2 in Fig. 2.5.
2.3.3 Trees
The concept of a tree is probably the most important in graph theory, especially for those interested in applications of graphs. A tree is a connected graph without any circuits. The graph in Fig 2.6 for instance, is a tree. It follows immediately from the definition that a tree has to be a simple graph, that is, having neither a self-loop nor parallel edges (because they both form circuits).
Trees appear in numerous instances. The genealogy of a family is often represented by means of a tree. A river with its tributaries and sub-tributaries can also be represented by a tree. The sorting of mail according to zip code and the sorting of punched cards are done according to a tree (called decision tree or sorting tree).
BSIT 41 Algorithms
23
SUMMARY
This chapter devotes itself to present an overview of very fundamental data structures essential for the design of algorithms. One of the basic technique for improving algorithms is to structure the data in such a way that the resulting operations can be carried out efficiently. Though the chapter does not present all the data structure, we have selected several which occur more frequently in this book. This chapter also presents some terminologies used in the graph. The notions such as arrays, stack, queue, graphs and trees have been exposed.
EXERCISE
1. 2. 3. 4. 5. 6. 7. Give at least 5 real life examples where we use stack operations Give at least 5 real life applications where queue is used. Name 10 situations that can be represented by means of graphs. Explain what each vertex and edge represent Draw a connected graph that becomes disconnected when any edge is removed from it Draw all trees of n labeled vertices for n=1,2,3,4 and 5 Sketch all binary trees with six pendent edges Write adjacency and incidence matrix for all the graphs developed
Chapter 3
lgorithm is a blueprint, the program follows to achieve the end result. The end result thus depends on the proper understanding of the logic constructs rather than the programming constructs specific to the programming language. In this chapter we present some simple problems and discuss the issues in solving the problem and finally design the algorithms for the same.
The a ,b ,c are the memory locations from now on called the variables. When we generalize this, it appears as c= a + b To make it even more simple, we have two inputs and one output. To store one output and two inputs we need three variables or memory locations. The Algorithm to add two numbers is now given below.
24
BSIT 41 Algorithms
25
Algorithm : Add_two_numbers Input Output Method c= a + b Display c Algorithm ends : a, b, two numbers to be added : c updated
26
b = small k1 = a k2 = c end_if if (small> c) c = small k1 = a k2 = b end_if Display small If (k1 > k2 ) Display k2 Display k1 Else Display k1 Display k2 end_if Algorithm ends
BSIT 41 Algorithms
27
The co-ordinate positions thus entered have to fall in either of those Quadrant based on the sign of the X and Y co-ordinate positions. Algorithm : Quadrant_Finder Input : x, X co-ordinate y, Y co-ordinate Output Method If( x >=0) If(y>=0) Display I Quadrant Else Display IV-Quadrant end_if else If(y>=0) Display II Quadrant Else : Corresponding Co-ordinate
28
Display III-Quadrant end_if end_if Algorithm ends
R1 =
R2 =
b + b 2 4ac 2a
b b 2 4ac 2a
And these are two roots of the equation. The term (b2-4ac) in the solution to the root is called the discriminant of the root. Basically the roots can be real or imaginary in nature. If the roots are real in nature then they can be either real and distinct, or both of them can be equal. If they are imaginary the roots exists in complex conjugates. The problem of identifying the nature of the roots is achieved in checking the nature of the discriminant. The nature of the discriminant reflects the nature of the solution of the quadratic equation. If the discriminant is negative then the roots will be of imaginary in nature. i.e if (b2-4ac) = some ve value. And these are two roots of the equation. The term (b2-4ac) in the solution to the root is called the discriminant of the root. Basically the roots can be real or imaginary in nature. If the roots are real in nature then they can be either real and distinct, or both of them can be equal. If they are imaginary the roots exists in complex conjugates. The problem of identifying the nature of the roots is achieved in checking the nature of the discriminant. The nature of the discriminant reflects the nature of the solution of the quadratic equation. If the discriminant is negative then the roots will be of imaginary in nature. i.e if (b2-4ac) = some ve value. Then, b 2 4ac is complex in nature, because square root of any negative number always results in an imaginary result.
BSIT 41 Algorithms
29
Now the roots R1 and R2 has imaginary parts and hence they are imaginary in nature. Now the other possibility is that the roots being real. For that to happen the disciminant (b2-4ac) = 0. If it is equal to zero than the discriminant vanishes and hence the roots are real and equal,which are R1 = R2 = -b/2a. In case (b2-4ac) > 0 , then the roots are real and distinct. The algorithm to find the solution to a quadratic equation is given below. Algorithm: Quadratic_solver Input : a,b,c the co-efficients of the Quadratic Equation Output Method disc = ((b*b) (4*a*c)) if (disc = 0) display roots are real and equal r1 = -b/2a r2 = -b/2a display r1 display r2 else if(disc>0) display roots are real and distinct : The two roots of the Equation
30
display imaginary part, sqrt(absolute_value_of(disc)) display the two root exists in conjugates end_if Algorithm ends
First Approach
Here we keep dividing a number from 2 to half the value of that number. For ex: if 47 is the number under consideration for primality testing then we would divide 47 form 2 to 47/2(23.5 approx. 24) and check whether any number in this interval performs a division operation on 47 such that there is no remainder. If so then the given number is not prime. But in the case of 47 no number between 2 and 24 performs such sort of division operation and hence it is declared as a prime number. Algorithm: Primality_Testing (First approach) Input: n , number flag, test condition Output: flag updated Method flag = 0 for(i=2 to n/2 in steps of +1 and flag = 0) if( n % i = 0) // n mod i flag = 1 end-if end-for
if(flag = 0)
BSIT 41 Algorithms
31
display Number is prime else display Number is not prime end_if Algorithm ends
Second Approach
It is proved in number theory that instead of setting the interval of divisor to n/2 we can simply set that to square root of the given number under consideration of Primality and it would work perfectly fine as the previous algorithm. Note that in this algorithm we achieve the same result with lesser number of operations because we reduce the size of the interval. Algorithm: Primality_Testing (Second approach) Input : n , number flag, test condition Output Method flag = 0 for(i=2 to square_root(n) in steps of +1 and flag = 0) if( n % i = 0) // n mod i flag = 1 end_if end-for : flag updated
if(flag = 0) display Number is prime else display Number is not prime end_if Algorithm ends
Finding Factorial of a given number is another interesting problem. Mathematically represented as n! . For ex: 5! = 5*4*3*2*1. Not to forget that 1! = 1 and 0! = 1. We can now generalize the factorial of a given number which is any thing other than zero and one as the product of all the numbers ranging from given number to 1. i.e n! = n * (n 1) * (n 2 ) * . . . *1 Algorithm : Factorial Input Output Method fact = 1 for i = n to 1 in steps of 1 do fact = fact*i end_for :n : Factorial of n
display factorial = ,fact Algorithm ends In the above algorithm we have implemented the logic of the equation n! = n * (n 1) * (n 2 ) * . . . *1. The same can be achieved by the following algorithm which follows incremental steps rather than decremental steps of the given algorithm. Algorithm : Factorial Input Output :n : Factorial of n
BSIT 41 Algorithms
33
Method fact = 1 for i = 1 to n in steps of 1 do fact = fact*i end_for display factorial = ,fact Algorithm ends
34
Subsequently add 10 to 27 => 10 + 27 = 37 Subsequently add 5 to 37 => 37 + 5 = 42 And Finally add 1 to 42 => 42 + 1 = 43
Which is nothing but 12 + 15 + 10 + 5 + 1 = 43. The following logic of adding two successive elements and iterating the same process over the other remaining elements is described in the algorithm given below. The resulting sum divided by the number of elements yields the average of the domain of input set. Algorithm : Sum_and_Average Input : n , number of elements a(n) , array of n elements Output Method Display Enter the number of elements Accept n Display Enter the elements one by one For (i = 1 to n in steps of +1 do) Accept a(i) end_for sum = 0 For (i = 1 to n in steps of +1 do) sum = sum + a(i) end_for Display Sum = ,sum : Sum and Average of n array elements
BSIT 41 Algorithms
35
a11 a 21 a 31
a12 a 22 a32
a13 a 23 + a 33
The above example is of matrix addition. Matrix addition is possible iff orders of the two matrices are same. Respective matrix elements are added together in a third matrix and the results are thus obtained. The procedure is thus described below. The two Matrices has to read initially in a two dimensional array and then the respective row element and column elements in the Matrices have to be added to get a third matrix, which leads to the realization of Matrix addition. Algorithm : Matrix Addition Input : n , order of the matrices a(n,n),b(n,n) the two input matrices Output Method { Accept n for(i = 1 to n in steps + 1 do) for(j= 1 to n in steps of + 1do) accept a(i,j) end_for end_for : c(n,n) the resultant Sum matrix
for(i = 1 to n in steps + 1 do) for(j= 1 to n in steps of + 1do) accept b(i,j) end_for end_for
36
for(i = 1 to n in steps + 1 do) for(j= 1 to n in steps of + 1do) c(i,j) = a(i,j) + b(i,j) end_for end_for
for(i = 1 to n in steps + 1 do) for(j= 1 to n in steps of + 1do) display c(i,j) end_for end_for Algorithm ends
SUMMARY
In this chapter some simple problems, the problem solving concepts and the concept of designing algorithms for the problems has been presented. For the ease of students some simple problems are considered and the algorithms are developed. The students are expected to implement all the above explained algorithms and experience the way they work.
EXERCISE
1. Design and Develop algorithms for multiplying n integers. Hint: Follow the algorithm to add n numbers given in the text 2. 3. 4. 5. 6. 6. 7. Design and develop algorithm for finding the middle element in the three numbers. Develop algorithm to find the number of Permutations and Combinations for a given n and r Design a algorithm to generate all prime numbers within the limits l1 and l2. Design an algorithm to find the reverse of a number. A number if said to be a palindrome if the reverse of a number is same as the original. Design a algorithm to check whether a number is palindrome or not Design a algorithm to check whether a given string is palindrome or not Implement all the devised algorithms and also the algorithms discussed in the chapter.
Chapter 4
4.1 SEARCHING
et us assume that we have a sequential file and we wish to retrieve an element matching with key k, then, we have to search the entire file from the beginning till the end to check whether the element matching k is present in the file or not.
There are a number of complex searching algorithms to serve the purpose of searching. The linear search and binary search methods are relatively straight forward methods of searching.
BSIT 41 Algorithms
37
38
Method : i=1 While(i<=n) { if(A[i]=k) { write(search successful) write(k is at location i) exit(); } else i++ if end while end write (search unsuccessful); algorithm ends.
BSIT 41 Algorithms
39
Output : low index of k Method : low=1,high=n While(low<=high-1) { mid=(low+high)/2 if(k<a[mid]) high=mid else low=mid if end } while end if(k=A[low]) { write(search successful) write(k is at location low) exit(); } else write (search unsuccessful); if end; Algorithm ends.
4.2 SORTING
One of the major applications in computer science is the sorting of information in a table. Sorting algorithms arrange items in a set according to a predefined ordering relation. The most common types of data are string information and numerical information. The ordering relation for numeric data simply
40
involves arranging items in sequence from smallest to largest and from largest to smallest, which is called ascending and descending order respectively. The items in a set arranged in non-decreasing order are {7,11,13,16,16,19,23}. The items in a set arranged in descending order is of the form {23,19,16,16,13,11,7} Similarly for string information, {a, abacus, above, be, become, beyond}is in ascending order and { beyond, become, be, above, abacus, a}is in descending order. There are numerous methods available for sorting information. But, not even one of them is best for all applications. Performance of the methods depends on parameters like, size of the data set, degree of relative order already present in the data etc.
S 'i +1 , is obtained by inserting the (i + 1) th element of the unsorted sequence S 'i +1 into the correct position in S ' i .
Each sequence S ' i , 0 i n , contains the first i elements of the unsorted sequence S. Therefore, the final sequence in the series, S ' n , is the sorted sequence we seek. i.e., S ' = S 'n . Fig. 4.1 illustrates the insertion sorting algorithm. The figure shows the progression of the insertion sorting algorithm as it sorts an array of ten integers. The array is sorted in place. I.e., the initial unsorted sequence, S, and the series of sorted sequences, S ' 0: S '1 : ... : S ' n , , occupy the same array. In the ith step, the element at position i in the array is inserted into the sorted sequence
S ' i which occupies array positions 0 to (i-1). After this is done, array positions 0 to i
contain the i+1 elements of S ' i +1 . Array positions (i+1) to (n-1) contain the remaining n-i1 elements of the unsorted sequence S.
BSIT 41 Algorithms
41
As shown in Fig. 4.1, the first step (i=0) is trivialinserting an element into the empty list involves no work. Altogether, n-1 non-trivial insertions are required to sort a list of n elements.
Algorithm : Insertion Sort Input : n, Size of the input domain a[1..n], array of n elements Output : a[1..n] sorted
42
Method for j= 2 to n in steps of 1 do item = a[j] i = j-1 while((i>=1) and (item<a[i])) do a[i+1] = a[i] i = i-1 while end a[i+1] = item for end Algorithm ends
BSIT 41 Algorithms
43
At each step of the algorithm, a linear search of the unsorted elements is made in order to determine the position of the largest remaining element. That element is then moved into the correct position of the array by swapping it with the element which currently occupies that position.
For example, in the first step shown in Fig 4.2, a linear search of the entire array reveals that 9 is the largest element. Since 9 is the largest element, it belongs in the last array position. To move it there, we swap it with the 4 that initially occupies that position. The second step of the algorithm identifies 6 as the largest remaining element an moves it next to the 9. Each subsequent step of the algorithm moves one element into its final position. Therefore, the algorithm is done after n-1 such steps.
44
Algorithm : Selection Sort Input : n, Size of the input domain a[1..n], array of n elements Output: a[1..n] sorted Method: for i = 1 to n in steps of 1 do j=i for k = i+1 to n in steps of 1 do if(a[k]< a[j]) then j = k for end Interchange a[i] and a[j] For end Algorithm ends. Two more sorting algorithms are discussed in the next chapter.
SUMMARY
In this chapter two techniques for checking whether an element is presented in the list of elements is presented. Linear search is best employed when data searching operation is used minimally. But when data searching on the same data set has to be done several times then it is better to sort that data set and apply binary search. Binary search reduces the effort in searching as in case of Linear search. The chapter also presents some sorting techniques in sequel to searching. Selection sort is simplest of all sorting algorithms and it goes for the selection of the largest element at each iteration. Insertion sort builds a sorted list by inserting elements to a small sub sorted list.
EXERCISE
1. 2. 3. 4. 5. 6. What are the serious short comings of the binary search method and sequential search method. Consider a data set of nine elements {10, 30, 45, 54, 56, 78, 213, 415, 500} and trace the linear search algorithm to find whether the keys 30, 150, 700 are present in the data set or not. Trace the Binary search algorithm on the same data set and same key elements of problem 2. Try to know more sorting techniques and make a comparative study of them. Hand Simulate Insertion Sort on the data set { 13 , 45 , 12, 9 , 1, 10, 40} Implement all the algorithms designed in the chapter.
Chapter 5
Recursion
e look at the concept of recursion, which is one of the very powerful programming concepts, supported by most of the languages. At the same time, it is also a fact that most beginners are confused by the way it works and are unable to use it effectively. Also, some languages may not support recursion. In such cases, it may become necessary to rewrite recursive functions into nonrecursive ones. All these and many other aspects are dealt with in this chapter. Recursion is an offshoot of the concept of subprograms. A subprogram as we know is the concept of writing separate modules, which can be called from other points in the program or other programs. Then came a concept wherein any subprogram can call any other subprogram. The control goes to the called subprogram, performs the assigned tasks and comes back to the caller programs. Then comes the question can a program call itself? Theoretically it is possible. If so, where do we use them normally? A subprogram is called to perform a function, which the caller subprogram cannot perform itself. But if the caller program calls itself, what purpose does it serve? The answer is, the subprogram no doubt, calls itself, but with a different value of the parameter. In fact, in most cases, the calling continues until some specific value of the parameter is reached. We now understand that recursion is a process of defining a process/ problem/ an object in terms of itself. Recursion is one of the applications of stacks. The recursive mechanisms are extremely powerful, but even more importantly; many times they can express an otherwise complex process, very clearly. Any program can be written using recursion. Of course, the recursive program in that case could be tougher to understand. Hence, recursion can be used when the problem itself can be defined recursively. The general procedure for any recursive algorithm is as follows, 1. Save the parameters, local variables and return addresses.
BSIT 41 Algorithms
45
46
Chapter 5 - Recursion
2. If the termination criterion is reached perform final computation and go to step 3, otherwise perform final computations and go to step 1. 3. Restore the most recently saved parameters, local variables and return address and go to the latest return address.
BSIT 41 Algorithms
47
Suppose we are asked to evaluate N!. If we somehow know (N-1)! then we can evaluate N! = N*(N1)!. But how do we get (N-1)!? The same logic can be employed to evaluate (N-1)! = (N-1) * (N-2)!. The problem of finding the factorial of a given number can be recursively defined as
if n 1
The students are advised to try various values of n to actually see how the method works.
48
Output: nth Fibonacci number Method: If (n==0) Return (0) Else If (n == 1) Return (1) Else Return (Fibonacci (n-1) + Fibonacci (n-2)) If end If end Algorithm ends Again, the correctness can be checked for various input values.
Chapter 5 - Recursion
We use a third example, though normally this method is not used to explain recursion, nevertheless it is a very useful method.
BSIT 41 Algorithms
49
else if (n == 0) // Our terminating condition return 1; else return (n + SumPosInt( n -1 ); // recursive step if end if end Algorithm ends
50
if (a[mid]< K) Binary search(A, K, Low, mid) else Binary Search(A, K, High, mid) if end if end else return(0) if end Algorithm ends.
Chapter 5 - Recursion
max = a(p) min = a(q) Else If ( p q-1) Then If a(p) > a(q) Then
BSIT 41 Algorithms
51
max = a(p) min = a(q) Else max = a(q) min = a(p) If End Else m (p+q)/2 max-min(p,m,max1,min1) max-min(m+1,q,max2,min2) max f large(max1,max2) min f small(min1,min2) If End If End Algorithm Ends.
52
Chapter 5 - Recursion
Similarly compare A(2) with B(2), since A(2) is smaller, it will be the third element and so on. Finally, C is built up as C[ ]= {2, 3, 5, 6, 8, 9, 14, 15, 18, 27, 30, 32}. However the main problem remains. In the above example, we presume that both A & B are originally sorted. Then only they can be merged. But, how do we sort them in the first? To do this and show the consequent merging process, we look at the following example. Consider the series A= (7 5 15 6 4). Now divide A into 2 parts (7, 5, 15) and (6, 4). Divide (7, 5, 15) again as ((7, 5) and (15)) and (6, 4) as ((6) (4)). Again (7, 5) is divided and hence ((7, 5) and (15)) becomes (((7) and (5)) and (15)). Now since every element has only one number, we cannot divide again. Now, we start merging them, taking two lists at a time. When we merge 7 and 5 as per the example above, we get (5, 7) merge this with 15 to get (5, 7, 15). Merge this with 6 to get (5, 6, 7, 15). Merging this with 4, we finally get (4, 5, 6, 7 and 15). This is the sorted list. You are now expected to take different sets of examples and see that the method always works. We design two algorithms in the following. The main algorithm is a recursive algorithm (some what similar to the binary search algorithm that we saw earlier) which calls at times the other algorithm called MERGE. The algorithm MERGE does the merging operation as discussed earlier. Algorithm: MERGESORT Input: low, high, the lower and upper limits of the list to be sorted A, the list of elements Output: A, Sorted list Method: If (low<high) mid (low + high)/2 MERGESORT(low, mid) MERGESORT (mid, high) MERGE(A, low, mid, high) If end Algorithm ends You may recall that this algorithm runs on lines parallel to the binary search algorithm. Each time it divides the list (low, high) into two lists(low, mid) and (mid+1, high). But later, calls for merging the two lists.
BSIT 41 Algorithms
53
Algorithm: Merge Input: low, mid, high, limits of two lists to be merged i.e., A(low, mid) and A(mid+1, high) A, the list of elements Output: B, the merged and sorted list Method: h = low, i = low, j = mid + 1; While ((h d mid) and (j d high)) do If (A(h) d A(j) ) B(i) = a(h); h = h+1; else B(i) = A(j); j = j+1; If end i = i+1; If (h > mid) For k = j to high B(i) = A(k); i = i+1; For end Else For k = h to mid B(i) = A(k); i = i+1 For end If end While end Algorithm ends
54
Chapter 5 - Recursion
The first portion of the algorithm works exactly similar to the explanation given earlier, except that instead of using two lists A and B to fill another array C, we use the elements of the same array A[low,mid] and A[mid+1,high] to write into another array B. Now it is not necessary that both the lists from which we keep picking elements to write into B should get exhausted simultaneously. If the fist list gets exhausted earlier, then the elements of the second list are directly written into B, without any comparisons being needed and vice versa. This aspect will be taken care of by the second half of the algorithm.
5.10 QUICKSORT
This is another method of sorting that uses a different methodology to arrive at the same sorted result. It Partitions the list into 2 parts (similar to merge sort), but not necessarily at the centre, but at an arbitrarily pivot place and ensures that all elements to the left of the pivot element are lesser than the element itself and all those to the right of it are greater than the element. Consider the following example. 75 80 85 90 95 70 65 60 55 To facilitate ordering, we add a very large element, say 1000 at the end. We keep in mind that this is what we have added and is not a part of the list. 75 A(1) 80 A(2) 85 A(3) 90 A(4) 95 A(5) 70 A(6) 65 A(7) 60 A(8) 55 A(9) 1000 A(10)
Now consider the first element. We want to move this element 75 to its correct position in the list. At the end of the operation, all elements to the left of 75 should be less than 75 and those to the right should be greater than 75. This we do as follows: Start from A(2) and keep moving forward until an element which is greater than 75 is obtained. Simultaneously start from A(10) and keep moving backward until an element smaller than 75 is obtained. A(1) A(2) A(3) A(4) A(5) A(6) A(7) A(8) A(9) A(10) 75 80 85 90 95 70 65 60 55 1000
Now A(2) is larger than A(1) and A(9) is less than A(1). So interchange them and continue the process. 75 55 85 90 95 70 65 60 80 1000
Again A(3) is larger than A(1) and A(8) is less than A(1), so interchange them. 75 55 60 90 95 70 65 85 80 1000
Similarly A(4) is larger than A(1) and A(7) is less than A(1), interchange them
BSIT 41 Algorithms
55
65 95 70 90 85 80 1000
75
55
60
In the next stage A(5) is larger than A(1) and A(6) is lesser than A(1), after interchanging we have 75 55 60 65 70 95 90 85 80 1000
In the next stage A(6) is larger than A(1) and A(5) is lesser than A(1), we can see that the pointers have crossed each other, hence Interchange A(1) and A(5). 70 55 60 65 75 95 90 85 80 1000
We have completed one series of operations. Note that 75 is at its proper place. All elements to its left are lesser and to its right are greater. Next we repeat the same sequence of operations from A(1) to A(4) and also between A(6) to A(10). This we keep repeating till single element lists are arrived at. Now we suggest a detailed algorithm to do the same. As before, two algorithms are written. The main algorithm, called QuickSort repeatedly calls itself with lesser and lesser number of elements. However, the sequence of operations explained above is done by another algorithm called PARTITION Algorithm: QuickSort Input: p, q, the lower and upper limits of the list of elements A to be sorted Output: A, the sorted list Method: If (p < q) j = q+1; PARTITION (p, j) QuickSort(P, j-1) Quicksort(j+1, q) If end Algorithm ends Algorithm: PARTITION Input: m, the position of the element whose actual position in the sorted list has to be found p, the upper limit of the list Output: the position of mth element
56
Method: v = A(m); i = m; Repeat Repeat i = i+1 Until (A(i) e> v); Repeat p=p-1 Until (A(p) d v); If (i < p) INTERCHANGE(A(i), A(p)) If end Until (i e p) A(m) = A(p) ; A(p) = v; Algorithm ends
Chapter 5 - Recursion
BSIT 41 Algorithms
57
For example, the recursion tree for generating 6 numbers in a fibonacci series generation is given in fig 5.1. A fibonacci series is of the form 0,1,1,2,3,5,8,13etc, where the third number is the sum of preceding two numbers and so on. It can be noticed from the fig 5.1 that, f (n-2) is computed twice, f (n-3) is computed thrice, f (n-4) is computed 5 times. 3. A recursive procedure can be called from within or outside itself and to ensure its proper functioning it has to save in some order the return addresses so that, a return to the proper location will result when the return to a calling statement is made. 4. The recursive programs needs considerably more storage and will take more time.
SUMMARY
In this chapter, the concepts of recursion are introduced. Some simple problems which were discussed in the earlier chapters are reconsidered and the recursive algorithms are designed to achieve the same outcome. Two sorting algorithms namely Quick sort and merge sort are presented and the recursive algorithms are designed.
EXERCISE
1. 2. 3. 4. 5. 6. 7. Trace out the algorithm Merge Sort on the data set {1,5,2,19,4,17, 45, 12, 6} Trace out the algorithm Quick Sort on the data set {12 , 1, 5,7,19,15, 8, 9, 10} Implement all the algorithms designed in this chapter. Trace out the algorithm MaxMin on a data set consisting of atleast 8 elements. List out the merits and demerits of Recursion. The data structure used by recursive algorithms is _____________ When is it appropriate to use recursion?
Chapter 6
(b)
(a)
(c)
Fig. 6.1 (a) A complete binary tree (b) A full binary tree (c)A binary tree showing levels binary tree
58
BSIT 41 Algorithms
59
In the above definition if k is restricted to be maximum of 2 then the rooted tree is called binary tree. If k = 0, it implies that there are no children. A node without any children is called a leaf node. The number of levels in the tree is called the depth of the tree. A complete binary tree is one which allows sequencing of the nodes and all the previous levels are maximally accommodated before the next level is accommodated. i.e., the siblings are first accommodated before the children of any one of them. And a binary tree which is maximally accommodated with all leaves at the same level is called full binary tree. A full binary tree is always complete but complete binary tree need not be full. Fig. 6.1 (a) and (b) shows the examples for complete and full binary trees. The maximum number of vertices at each level in a binary tree can be found out as follows: At level 0: 20 number of vertices At level 1: 21 number of vertices At level 2: 22 number of vertices At level i: 2i number of vertices Therefore, maximum number of vertices in a binary tree of depth l is:
2 0 + 21 + 2 2 + 2 3 + ... + 2 l
i.e.,
0 k 1
= 2 l +1 1
In static allocation, we have two ways of representing the binary tree. One is through the use of Adjacency matrices and the other through the use of Single dimensional array representation.
60
matrix. Here the row indices correspond to the parent nodes and the column corresponds to the child nodes. i.e., A row corresponding to the vertex vi having the entries L and R indicate that vi has as its left child the index corresponding to the column with the entry L and the index corresponding to the column with R entry as its right child. The column with no entries corresponds to the root node. All other columns have only one element. Each row may have 0, 1 or 2 entries. Zero entry in the column indicates that the node is the root. Zero entry in the row means that, that element is a leaf node, only one entry means that the node has only one child and two entries denote that the node has both the children. L is used to represent left child and R is used to represent right child entries.
The adjacency matrix representation for the binary tree shown in Fig. 6.2 is given below.
A B C D E F G H I J K
A B C D E F G H I L R L R L L R R
L R
Now, let us see the space utilization of this method of binary tree representation. Let n be the number of vertices. There is space allocated for n x n matrix. i.e., we have n2 space allocated, but we have only n-1 entries in the matrix. Therefore, the percentage of space utilization is given as follows:
BSIT 41 Algorithms
61
n 1 1 n = 100% 2 n n
The space utilization decreases as n increases. For large n, the percentage of utilization becomes negligible. This is, therefore, not the most efficient method of representing a binary tree.
The left child of the ith node is placed at the 2ith position. The right child of the ith node is placed at the (2i+1) th position. The parent of the ith node is at the (i/2) th position in the array.
Thus the single dimensional array representation for the binary tree shown in Fig.6.2 turns out to be as follows.
4 D 5 E 6 F 7 8 9 10 G 11 H 12 13 I 14 15 16 17 18 19 20 21 22 23 24 25 26 J 27 K 28 29 30 31
If l is the depth of the binary tree then, the number of possible nodes in the binary tree is 2l+1-1. Hence it is necessary to have 2l+1-1 locations allocated to represent the binary tree. If n is the number of nodes, then the percentage of utilization is
n 1 100 2 l +1 l
For a complete and full binary tree, there is 100% utilization and there is a maximum wastage if the binary tree is right skewed or left skewed, where only l+1 spaces are utilized out of the 2l+1 1 spaces possible. i.e.,
l +1 100 is the worst possible utilization in the single dimensional array representation. 2 l +1 1
An important observation to be made here is that the organization of the data in the binary tree decides the space utilization of the representation used. The other alternative way of representing the binary tree is based on Linked Allocation (dynamic allocation method).
Here, the structure for each node becomes regular and in each node structure, there is a pointer to a left child and another to the right child and space for the data of that node. This is pictorially represented below:
Lchild
Data
Rchild
A binary tree represented using the linked representation is shown in Fig. 6.3. In this representation, ordering of nodes is not mandatory and we require a header to point to the root node of the binary tree. If there are n nodes to be represented, only n node-structures will be allocated. This means that there will be 2n link fields. Out of 2n link fields only (n-1) will be actually used to point to the next nodes and the remaining are wasted. Therefore the percentage of utilization is given as:
n 1 1 = 100 = 50% 2n n
BSIT 41 Algorithms
63
There are three major methods of traversals and the rest are reversals of them. They are: 1. Pre-order traversal 2. In-order traversal 3. Post-order traversal
Pre-Order Traversal
In this traversal, the nodes are visited in the order of root, left child and then right child. i.e., 1 Visit the root node first. 2 Go to the first left sub-tree. 3 After the completion of the left sub-tree, Go to the right sub-tree. Here, the leaf nodes represent the stopping criteria. We go to the sibling sub-tree after the traversal of a sub-tree. The pre-order traversal sequence for the binary tree shown in Fig. 6.3 is : A B D E G H C F IJK
In-Order Traversal
In this traversal, the nodes are visited in the order of left child, root and then right child. i.e., the left sub-tree is traversed first, then the root is visited and then the right sub-tree is traversed. Here also, the leaf nodes denote the stopping criteria. The in-order traversal sequence for the above considered example (Fig. 6.3) is: D B G E H A F J I K C
Post_Order Traversal
In this traversal, the nodes are visited in the order of left child, right child and then root. i.e., the left sub-tree is traversed first, then the sibling is traversed next. The root is visited last. The post-order traversal for the above example (Fig. 6.3) is: D G H E B J K I F C A
64
3 Push in to the stack
4 Scan the row in search of L for the left child information 5 Pop from the stack 6 Scan the row in search of R for the right child information 7 Check if array IsEmpty(). 8 Stop Sequencing the above stated steps helps us in arriving at preorder, inorder and postorder traversal sequences.
Preorder Traversal
Fig.6.4 shows flow graph of preorder traversal.
L found
Note that before popping, we need to check whether the stack is empty or not. Inorder Traversal The in-order traversal will also have the same steps explained above. Only the flow graph sequence changes, and is given in Fig. 6.5.
BSIT 41 Algorithms
65
Designing a flow graph for post order traversal is left as an exercise to the students.
66
Inorder Traversal
Algorithm: Inorder Traversal
Input: A[], one dimensional array representing the binary tree i, the root address //initially i=1 Output: Inorder sequence Method: If (A[i] != 0) Inorder Traversal (A, 2i) Display(A[i]) Inorder Traversal (A, 2i +1) If end Algorithm ends
Postorder Traversal
Algorithm: Postorder Traversal Input: A[], one dimensional array representing the binary tree i, the root address //initially i=1 Output: Postorder sequence Method: If (A[i] != 0) Postorder Traversal (A, 2i) Postorder Traversal (A, 2i +1) Display(A[i]) If end Algorithm ends We shall now look into the tree traversals in linked representation
BSIT 41 Algorithms
67
Algorithm: In-order Traversal Input: bt, address of the root node Output: Inorder sequence Method: if(bt != NULL) { In-order Traversal([bt].Lchild) Display([bt].data) In-order Traversal([bt].Rchild) } Algorithm ends.
68
Algorithm: Post-order Traversal Input: bt, address of the root node Output: Postorder sequence Method: if(bt != NULL) {
SUMMARY
In this chapter the binary trees are introduced. Trees form the core of non-linear data structure and Binary tree helps in storing the data more efficiently although the access is not as simple as arrays. The various ways of representing the binary tree, linear, two dimensional arrays and linked representation are discussed. The algorithms for traversing the binary tree represented in various representations are also presented.
EXERCISE
1. 2. 3. 4. 5. What is a binary tree Differentiate complete and full binary trees What is the maximum number of nodes in a binary tree of level 7, 8 and 9 What are the wastage of memory for a binary tree with 16 nodes represented in a 1D array, 2D array and a linked representation. For a atleast 5 binary trees of different depths greater than or equal to 6 of your choice obtain the preorder, postorder and inorder sequences.
BSIT 41 Algorithms
69
References
1. 2. 3. 4. 5. 6. 7. Sartaj Sahni, 2000, Data structures, algorithms and applications in C++, McGraw Hill international edition. Horowitz and Sahni, 1983, Fundamentals of Data structure, Galgotia publications Horowitz and Sahni, 1998, Fundamentals of Computer algorithm, Galgotia publications. Narsingh Deo, 1990, Graph theory with applications to engineering and computer science, Prentice hall publications. Tremblay and Sorenson, 1991, An introduction to data structures with applications, McGraw Hill edition. Horowitz, Sahni and Rajasekaran, 2000, Computer algorithms, Galgotia publications Dromey R. G., 1999, How to solve it by computers, Prentice Hall publications , India.