Vous êtes sur la page 1sur 118

UNIT I

DATA STRUCTURES
Data Object: A data object is a set of instances or values.
For example,
Boolean = { false, true }
Digit = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }
Letter = { A, B, C,Z, a, b, c..z }
In the above examples, Boolean, Digit and Letter are the data objects which are
the set of values that are shown within the braces. The values within the braces are called
the instances of that particular data object.
Consider a data object,
Natural Number = { 1, 2, 3, }
The instances of this data object may be atomic or compound in nature. The
values 1, 2, 3, etc are atomic as they cannot be split further. But take a value 483 which
is also an instance of the data object Natural Number. 483 is a compound instance as it
can be further split into 4, 8 and 3. These are called the elements of the instance. The
elements may be instances of the same data object or it may be the instances of some
other data object.
The instances of a data object as well as the elements that constitute individual
instances are generally related in some way.
For example,
In the data object Digit, 0 may the smallest number, 1 may be the next number
and so on. This is a type of simple relationship. Take the instance 483 of the data object
Natural Number. It may be split into 4, 8 and 3, where 4 is the most significant bit, 8 is
the next and 3 is the least significant bit. This again is a simple relationship existing
between the elements of an instance.
Hence, now it must be clear that there is always some relationship existing
between the instances of a data object and between the elements of the instance. In
addition to these relationships, a set of functions is generally associated with a data
object. These functions transform one instance of an object into another instance of that
object or into an instance of another data object. The function could also create a new
instance without transforming the instance from which the new one is created.
For example, there can be a function called Add on the instances of a Natural
number data object. When Add function is applied on the instances 4 and 5, we get new
instance 9 but the original instances 4 and 5 are not disturbed. They still remain in the
list of instances of the data object.

Data Structure: A Data Structure is a data object together with the relationships that
exist among the instances and among the individual elements that compose an instance.
In other words, we define Data Structure as a way of organizing data that considers not
only the items stored but also their relationship to each other.
Once a data structure has been chosen for a particular application, they have to be
handled in an efficient way. Hence there comes the necessity of studying Algorithms.
The two categories data structures are,
1. Linear Data Structures
2. Non-linear Data Structures
Linear data structures are those in which the elements form a sequence whereas nonlinear data structures are those in which the elements do not form a sequence.

LINEAR DATA STRUCTURES


There are two methods by which we can construct a linear data structure. They
are,
Method 1: By using a sequence of memory locations. These are implemented using
arrays.
Method 2: By using pointers or links. These are implemented using linked lists.
The different types of linear data structures are:
1. Array
- The collection of similar data items grouped together which shares
the common name
2. Lists
- The list can be implemented using arrays
these are called linear
lists or ordered lists.
- The list can be implemented using pointers
these are called
linked lists.
3. Stacks
- The stacks can be implemented using arrays.
- The stacks can be implemented using linked.
4. Queues
- The queue can be implemented using arrays.
- The queue can be implemented using linked lists.

ARRAY
Array:

It is an ordered set which consists of fixed number of same data items. All the
data items in the set shares the common name called array name. The individual item in
the set is called an element of an array.
Whenever an array gets declared, a contiguous memory location is sequentially
allocated and the starting address will be stored in the array name.

Characteristics:
i.
ii.
iii.
iv.
v.
vi.

Array concept can be used if the same data items have to be grouped
together
Element of an array can be accessed using the array name and subscript
variable called index
The subscript variable can be treated like an ordinary variable.
The range of the index is 0 to N-1 where N is the total number of elements
in an array.
The size of the array is fixed.
Like the other variables, array also has to be declared before its usage.

Storage representation:
Whenever an array gets declared, a contiguous memory location gets allocated
and the address of the first location (Base address) gets stored in the array name.
For example the following statement can be used to allocate five contiguous
locations of type integer.
Int a[5];
The element in the array can be accessed using the array name and subscript like
a[0],a[1],.
100

102

104

106

108

2 Bytes
a

a[0]

100

a[1]

a[2]

a[3]

a[4]

The address of the element gets calculated by


a[i]= a+i*size of the data item
a[2]=a+2*2
= 100+ 4 = 104
A multidimensional array can be represented by an equivalent one-dimensional
array. For example a 2D array can be represented by an equivalent one dimensional array
by following any one of the following order
i. row major order
ii. Column major order
Row major order
The given two dimensional arrays will get stored row by row.
For example consider the two dimensional array
Int a[3][2];
It is the collection of 3 one dimensional arrays and the capacity of each one
dimensional array is two.
3

100
A[0][0]

102
A[0][1]
st
1 Row

A[0][0]

A[0][1]

A[1][0]

A[1][1]

A[2][0]

A[2][1]

104
A[1][0]

106
A[1][1]
nd
2 Row

108
110
A[2][0]
A[2][1]
3rd Row

100
A

The address of the elements gets calculated by using the formula given below
A[i][j]= A+ i*size of the one dimensional array * size of the
data item + j * size of the data item
A[2][0]=100+2*2*2+0*2
=100+8+0= 108

Column major order


The given two dimensional arrays will get stored column by column.
For example consider the two dimensional array
Int a[3][2];
It is the collection of 3 one dimensional arrays and the capacity of each one
dimensional array is two.

100
A[0][0]

A[0][0]

A[0][1]

A[1][0]

A[1][1]

A[2][0]

A[2][1]

102
104
A[1][0]
A[2][0]
1st Column

106
A[0][1]

108
A[1][1]
2nd Column

110
A[2][1]

100
A

The address of the elements gets calculated by using the formula given below
A[i][j]= A+ j* number of one dimensional array * size of the
data item + i * size of the data item
A[2][0]=100+0*3*2+2*2
=100+0+4= 104
Applications:

BUBBLE SORT

This is the most commonly used sorting method. The bubble sort derives its
name from the fact that the smallest data item bubbles up to the top of the sorted array.
Principle : The bubble sort method compares the two adjacent elements starting from
the start of the list and swaps the two if they are out of order. This is continued up to the
last element in the list and after each pass, a check is made to determine whether any
interchanges were made during the pass. If no interchanges occurred, then the list must
be sorted and no further passes are required.
Algorithm:
ALGORITHM BUBBLESORT( K, N )
// K is the array containing the list of data items
// N is the number of data items in the list
FOR I=N-1 TO 1
Exch 0
Repeat For J = 0 to I-1
If K[J] > K[J+1]
Then
K[J] K[J+1]
Exch 1
End If
End Repeat
If (Exch = 1) Then
Exit Loop
End If
End While
End BUBBLESORT
In Bubble sort algorithm, initially Exch flag is assumed 0 because no exchange
was made initially. Starting from the first element, the adjacent elements in the list are
compared. If they are found out of order then they are swapped immediately and Exch
flag is set to 1. This comparison is continued until the last two elements are compared.
After this pass, the Exch flag is checked to determine whether any exchange has taken
place. If no exchange has taken place then the control comes out of the loop and the
procedure comes to an end as the list is sorted. If any exchange has taken place during
5

the pass, the I value is decremented by 1 and the next pass is continued. This process
continues till list is sorted.
Example:
N = 10 Number of elements in the list
Pass 1
Exch =0
j=0

j =1

j=2

j=3

j=4

j=5

j=6

j=7

j=8

j=9

42

23

74

11

65

58

94

36

99

87

Out of order
23

42

Out of order
23

42

Out of order
23

42

Out of order
23

42

Out of order
23

42

Out of order

Swap
74

exch=1

i=9

11

65

58

94

36

99

87

74

65

58

94

36

99

87

65

74

58

94

36

99

87

65

58

74

94

36

99

87

65

58

74

36

94

99

87

65

58

74

36

94

87

99

Swap
11
Swap
11
Swap
11
Swap
11
Swap

Pass 2
23

42

Out of order
23

11

Out of order
23

11

Out of order
23

11

Out of order

11
Swap
42

i=8
65

58

74

36

94

Swap
42

Swap

99

i=8
58

65

74

36

94

Swap
42

87

87

99

i=8
58

65

36

74

94

87

99

i=8
6

Pass 3
23

11

Out of order
23

11

Out of order

42

58

65

36

74

Swap
42

87

94

99

94

99

87

94

99

87

94

99

87

94

99

i=7
58

65

36

74

Swap

87
i=7

Pass 4
23

11

Out of order
11

23

Out of order

42

58

36

65

Swap
42

74
i=6

58

36

65

Swap

74
i=6

Pass 5
11

23

Out of order

42

36

58

Swap

65

74

i=5

Pass 6
Adjacent numbers are compared up to i=4. But no swapping takes place. As there was no
swapping taken place in this pass, the procedure comes to an end and we get a sorted list:
11

23

36

42

58

65

74

87

94

99

Program:
#include <stdio.h>
#include <conio.h>
int K[10],N=10;
bubblesort(){
int i,j,exch=0,temp;
for(i=n-1;i>=0;i--){
exch=0;
for(j=0;j<=i-1;j++){
if(K[j]>k[j+1]){
temp=K[j];
K[j]=K[j+1];
K[j+1]=temp;
Exch=1;
}
}
7

}
}

if (exch==0)
break;

main(){
int i;
printf(\nEnter the values);
for(i=0;i<N;i++)
scanf(%d,&k[i]);
bubblesort();
printf(\nThe sorted values are);
for(i=0;i<N;i++)
printf( %d,k[i]);
}
The bubblesort( ) function sorts the data items in the array in the ascending order.
A variable i is declared to point to the number of elements under consideration in every
pass. The first two adjacent elements are compared and if they are found out of order
they are swapped else next two adjacent elements are compared. This process repeats till
the last two elements in the list. A variable exch is initially set as 0 and is used as flag to
determine whether an exchange has taken place. If exchange is done then the exch flag is
assigned 1. After every pass exch flag is checked. If it is 0, then control returns back to
the main function, else last pointer i.e, I is decremented once and next pass is continued.
In each pass the greatest elements in the list is pushed to the last position and the smaller
elements bubble up or move up.
In the main( ) function, the list of elements to be sorted will be received from the
user and stored in the array K. The list of sorted elements is displayed after invoking the
bubblesort function to sort all the elements in the ascending order.
Advantages:
1. Simple and works well for list with less number of elements.
Disadvantages:
1. Inefficient when the list has large number of elements.
2. Requires more number of exchanges for every pass.

LINEAR LIST
Linear List: A Linear list is a data object whose instances are of the form ( e1, e2, en),
where n is a finite natural number.
ei Element of the list.
n length of the list.
s size of the element.

For example a list of names, list of marks, etc.


The operations that are performed on a linear list are,
1.
2.
3.
4.
5.
6.
7.
8.
9.

Create a list.
Delete a list.
Determine whether the list is empty.
Determine the length of the list.
Find the kth element.
Search for a given element.
Delete the kth element
Insert a new element.
Display all elements.

Abstract Data Type (ADT): An Abstract Data Type is a representation in which we


provide a specification of the instances as well as of the operations that are to be
performed. More precisely,
An Abstract Data Type is a data type that is organized in such a way that the
specification of the object and the specification of the operation on the object are
separated from the representation of the object and the implementation of the operation.
Hence an Abstract Data Type representation separates the implementation of the
operations from their specification, thus leading the way to object oriented programming.
Formula Based Representation:
In this method we use an array to represent the instances of an object. Each
position of array is called a cell or a node. Individual elements of an instance are located
in the array using a mathematical formula as shown.
Location (i) = i - 1

ith element is in position i-1 (if array starts with position zero)

(or)
Location (i) = i

ith element is in position i (if array starts with position one)

A Linear list may be specified as an abstract data type (ADT) in which we provide a
specification of the instances as well as of the operations that are to be performed.
AbstractDataType LinearList
{
instances
ordered finite collection of zero or more elements
operations
Create( ): Create an empty linear list.
Destroy( ): Erase the list.
IsEmpty( ): Return true if the list is empty, false otherwise.
Length( ): Return the list size.
Find(k, x): Return kth element of the list in x and return false if not found.
Search(x): Return the position of x in the list otherwise return -1 if not found.
Delete(k): Delete the kth element.
9

Insert(k, x): Insert x just after kth element


Display( ): Display all elements of the list

LINKED LIST
Linked List: A Linked list is a collection of elements called nodes, each of which stores
two items called info and link. Info is an element of the list and a link is a pointer to the
next element. The linked list is also called a chain.
The different types of Linked lists are,
1. Singly linked list.
2. Doubly linked list
3. Circular linked list

SINGLY LINKED LIST


Singly Linked List: A singly linked list is a linked list in which each node contains only
one link pointing to the next node in the list.

In a singly linked list, the first node always pointed by a pointer called HEAD. If the link
of the node points to NULL, then that indicates the end of the list.
Operations on a singly linked list are,
1.
2.
3.
4.
5.
6.
7.

Count the number of elements.


Add an element at the beginning of the list.
Add an element at the end of the list.
Insert an element at the specified position in the list.
Delete an element from the list.
Search x in the list.
Display all the elements of the list.

10

The Abstract Data Type of the linked list may be written as shown.
AbstractDataType LinkedList
{
instances
finite collection of zero or more elements linked by pointers
operations

Count(HEAD ): Count the number of elements in the list.


Addatbeg(HEAD,x): Add x to the beginning of the list.
Addatend(HEAD,x): Add x at the end of the list.
Insert(HEAD,k, x): Insert x just after kth element.
Delete(HEAD,X): Delete the node which has the information X.
Search(HEAD,x): searches X in the list if found displays the element found if not
Found it displays the element not found
Display(HEAD ): Display all elements of the list

Algorithm:
Count:
The first operation count( ) counts the number of elements in the list. Let Head be
a pointer pointing to the beginning of the list. If the head points to NULL, then the list is
empty. In the count algorithm given below, we first create a temporary pointer Temp and
make it point to the node where Head is pointing. Since Head always points to the
beginning of the list, Temp is now pointing to the first node in the list. A counter is
initialized to zero. The list is traversed using a while loop and every time we move to the
next node, the counter is incremented. If Temp doesnt point to NULL, that means the
end of the list is not reached and hence temp is made to point to the next node. This is
repeated till the end of the list and finally we have the number of elements of the list in
the count variable.
ALGORITHM COUNT(HEAD)
BEGIN
Temp Head
Count
0
While Temp NULL
Count Count +1
Temp
Link (Temp)
End While
Write (Count)
End COUNT

11

Addatbeg:
The operation Addatbeg, adds the element k at the beginning of the existing list.
First a temporary pointer is created and made to point to the node where head is pointing.
The given element K is stored in a new node. Check if the list is empty. If so make link
of new node point to NULL and make Head to point to new, making it the first element
of the list. If the list is not empty, then the link of new is made to point to the first
element of the existing list and Head is made to point to the new node.

12

ALGORITHM ADDATBEG(HEAD, K )
BEGIN
Info(New) K
If (Head = NULL)
Then
Link(New)
NULL
Else
Link(New)
Head
Endif
Head
New
End ADDATBEG
Addatend:
The operation Addatend, adds the given element k at the end of the existing list.
Initially it is checked whether the list is empty or not. If the list is empty then create a
new node New and add the value k to the info part of the node. The link part is made to
point to NULL. Then the Head is made to point this new node making it the first node.
If the list already has some nodes and now a new node is to be added to the end of the
list, then create a temporary pointer called Temp and make it to point to the Head
initially. Then move the pointer the last node and now create a new node with value x.
Make the link part point to NULL. Now the link of temp is made to point to the new
node, thus making the new node as the last node of the list.

13

ALGORITHM ADDATEND(HEAD, K )
BEGIN
If (Head = NULL)Then
Info(Temp)
k
Link(Temp)
NULL
Head
Temp
Else
Temp
Head
While link(Temp) NULL
Temp
link(Temp)
End While
Info(New)
k
Link(New) NULL
Link(Temp)
New
Endif
End ADDATEND( )
Insert at k:
The operation Insertatk( k, x ) inserts the given element x in the kth position. A
temporary pointer Temp is created and made to point to Head. Now the Temp pointer is
moved to the k 1 th node. A new node with value x is created and the link of the new
node is made to point to the position where the link of temp is pointing. Then the link of
temp is made to point to the new node. Thus the given element is inserted in the position
k.

14

ALGORITHM INSERTATK(HEAD, K, X )
BEGIN
Temp
Head
I
1
While I < k-1
Temp
link(Temp)
I
I+1
End While
Info(New)
x
Link(New)
Link(Temp)
Link(Temp)
New
End INSERT( )
Delete ( x )
The operation Delete( x ), deletes the node with value x. The given value x is
compared with each node starting from the first node and continued till the last node. If
the node to be deleted is the first node, then simply Temp pointer is made to point to
Head and then Head is safely moved to point the next node. Now the first node is deleted
by deleting the Temp. If the node to be deleted is not the first node, then make it the old
node and move the temp pointer to the next node. Check if that is the node to be deleted.
If so, make the link of old point to link of temp and delete the node pointed by temp.
Now the node pointed by temp can be deleted. If this is also not the node to be deleted
then make this old node and move the Temp pointer to the next node and the process is
repeated till we reach the last node or the specified node is deleted.
ALGORITHM DELETE( HEAD,X)
BEGIN
Temp
Head
While Temp NULL
If (Info(Temp) =X)Then
If (Temp = Head) Then
Head
link(Temp)
QUIT
Else
Link(old)
Link(Temp)
QUIT
End If
Else
Old
Temp
Temp
Link(Temp)
End If
End While
End DELETE( )

15

Search:
The operation Search( x ), searches the given value x in the list. If found it
displays the element found message. A temporary pointer Temp is created and made to
point to the Head. Now info part of Temp is compared with the value x. If the value
matches the node the appropriate message will be displayed to the user otherwise Temp
pointer is moved to the next node. This is repeated till the end of the list is reached or till
the element to be searched is found.

16

ALGORITHM SEARCH(HEAD,X)
Begin
Temp
Head
While Temp NULL
If (Info(Temp) = X)Then
Write(Element found)
Quit
Else
Temp Link(Temp)
End While
End SEARCH( )
Display:
The operation Display( ), displays all the value in each node of the list. A
temporary pointer is created and made to point to Head initially. Now info part of Temp
is printed and Temp is moved to the next node. This is repeated till the end of the list is
reached.
ALGORITHM DISPLAY( HEAD )
Begin
Temp
Head
While Temp NULL
Write(INFO(Temp))
Temp Link(temp)
End While
End DISPLAY( )
Program
#include <stdio.h>
#include <conio.h>
#include <alloc.h>
struct Node{
char info;
struct
link;
};
struct Node *HEAD=NULL;
count()
{

Node

struct Node *temp;


int i=0;
temp=HEAD;
while(temp){
temp=temp->link;
i++;
}
printf(\nThe number of nodes in the list is %d,i);
17

}
display()
{
node *p;
p=HEAD;
if(p==NULL)
printf(\nList is empty);
while(p!=NULL)
{
printf(%c,p->info);
p=p->link;
}
}
addatbeg(char x){
struct *temp;
temp=malloc(sizeof(struct Node));
temp->info=x;
temp->link=HEAD;
HEAD=temp;
}
addatend(char x){
struct * temp,*p;
temp=malloc(sizeof(struct Node));
temp->info=x;
if(HEAD==NULL)
{
temp->link=HEAD;
HEAD=temp;
}
else
{
p=HEAD;
while(p->link!=NULL)
p=p->link;
p->link=temp;
temp->link=NULL;
}
}
addatk(char x,int k){
struct * temp,*p;
int i=1;
temp=malloc(sizeof(struct Node));
temp->info=x;
p=HEAD;
while(i<k-1){
p=p->link;
i++;
18

}
temp->link=p->link;
p->link=temp;

delete(char x){
struct Node *old, *temp;
int flag=0;
temp=HEAD;
while (temp!=NULL)
{
if (temp->info==x)
{
if (temp==HEAD)
HEAD=HEAD->link;
else
old->link=temp->link;
flag=1;
break;
}
else
{
old=temp;
temp=temp->link;
}
}
if(flag==0)
printf(\nElement not found");
}
search(char x)
{
struct node *temp;
int flag=0;
temp=HEAD;
while (temp!=NULL)
{
if (temp->data==x)
{
printf("\nElement found );
flag=1;
break;
}
else
{
temp=temp->link;
}
}
if(flag==0)
printf(\nElement not found");;
}
19

main()
{

}
Output

clrscr();
display();
addatbeg(a);
addatbeg(b);
display();
addatend(c);
addatend(d);
display();
addatk(e,2);
display();
count();
search(a);
search(n);
getch();

List is empty
b a
b a c d
b e a c d
The number of nodes in the list is 5
Element found
Element not found

DOUBLY LINKED LIST


Doubly linked list: The Doubly linked list is a collection of nodes each of which consists
of three parts namely the data part, prev pointer and the next pointer. The data part
stores the value of the element, the prev pointer has the address of the previous node and
the next pointer has the value of the next node.

In a doubly linked list, the head always points to the first node. The prev pointer
of the first node points to NULL and the next pointer of the last node points to NULL.
Operations on a Doubly linked list are,
1. Count the number of elements.
2. Add an element at the beginning of the list.
3. Add an element at the end of the list.
4. Insert an element at the specified position in the list.
5. Delete an element from the list.
6. Display all the elements of the list.
20

The Abstract Data Type of the linked list may be written as shown.
AbstractDataType DoublyLinkedList
{
instances
finite collection of zero or more elements linked by two pointers, one pointing the
previous node and the other pointing to the next node.
operations

Count(head ): Count the number of elements in the list.


Addatbeg(head,x): Add x to the beginning of the list.
Addatend(head,x):
Add x at the end of the list.
Insert(head,k, x): Insert x just after kth element.
Delete(head,x): Delete the element x from the list.
Search(head, x): searches the element x in the given list if found it displays the
element found message else element not found message will be displayed
Display(head ): Display all elements of the list

Algorithm:
The operations count( ), Search(x) and Delete(x) are similar to that of the singly
linked list.
Addatbeg:
The operation Addatbeg() adds a given element x at the beginning of the list. A
new node R is created and the value x is store in the data part of R. The prev pointer of R
is made to point to NULL and the next pointer is made to point to head. Then the prev
pointer of head is made to point to R and head is now moved to point to R making it the
first node. Thus the new node is added at the beginning of the doubly linked list.
ALGORITHM ADDATBEG(HEAD,X)
BEGIN
Info(R) x
Prev(R) NULL
Next(R) head
Prev(head) R
Head R
End ADDATBEG( )

21

Addatend:
The Addatend(x) operation adds the given element x at the end of the doubly
linked list. If the given list is empty then create a new node R and store the value of x in
the data part of R. Now make the prev pointer and the next pointer of R point to NULL.
Then head is pointed to R. If the list already contains some elements then, a temporary
pointer is created and made to point to head. The temp pointer is now moved to the last
node and then a new node R is created. The value x is stored in the data part of R and
next pointer of R is made to point to NULL. The prev pointer of R is made to point to
temp and next pointer of Temp is made to point to R. Thus the new node is added at the
end of the doubly linked list.
ALGORITHM ADDATEND(HEAD,X)
BEGIN
If (head = NULL) Then
Info(R) x
Next(R) NULL
Prev(R) NULL
Head R
Else
Temp head
While next(temp) NULL
Temp next(temp)
22

End While
Info(R) x
Next(R) NULL
Prev(R) Temp
Next(Temp) R

End If
End ADDATEND( )

Insert at K:
The Insertatk() operation inserts a given element x at the specified position k. A
temporary pointer is created and made to point to head. Then it is moved to the k-1th
node. Now a new node R is created and the data part is stored with value of x. The next
pointer of R is made to point to next(temp) and the prev pointer of next(temp) is made to
point to R. Thus the links on the right side of the new node is established. Now the next
of Temp is made to point to R and the prev pointer of R is made to point to temp thus
establishing the links on the left side of the new node. Now the new node is inserted at
the position k.

23

ALGORITHM INSERTATK(HEAD,X,K)
Begin
Temp head
I 1
Info(R) X
While I < k -1
Temp next (temp)
I I+1
End while
Next(R) Next(temp)
Prev(Next(Temp) R
Next(Temp) R
Prev(R) Temp
End INSERT( )
Delete:
The Delete(x) operation deletes the element x from the doubly linked list. A
temporary pointer is created and made to point to head. Now the data of temp is
compared with x and if it matches that is the node to be deleted otherwise move to the
next node and again compare. If the node to be deleted is first node, then
prev(next(temp)) is made to point to NULL and head is pointed to next(temp). The node
pointed by temp is deleted. When the node to be deleted is not the first node, then
next(prev(temp)) is made to point to next(temp) and prev(next(temp)) is made to point to
prev(temp). The node pointed by temp is deleted.
24

ALGORITHM DELETE(HEAD,X)
Begin
Temp head
While temp NULL
If x = info(temp)
Then
If head = temp
Then
Prev(next(temp) NULL
Head next(temp)
quit
Else
Prev(next(temp)) prev(temp)
Next(prev(temp)) next(temp)
quit
End if
Else
Temp = next(temp)
End if
End while
End DELETE( )

25

Program
#include <stdio.h>
#include <conio.h>
#include<alloc.h>
struct Node
{
struct Node *prev;
char info;
struct Node *next;
};
struct Node *HEAD=NULL;
count(){
struct Node *p;
int i=0;
p=HEAD;
while(p){
p=p->next;
i++;
}
printf(\nThe total number of nodes in the list is %d,i);
}
search(char x){
struct Node *p;
int flag=0;
p=HEAD;
while(p){
if(p->info==x){
printf(\nElement found);
flag=1;
break;
}
else
p=p->next;
}
if(flag==0)
printf(\nElement not found);
}
display(){
sturct Node *p;
p=HEAD;
if(p==NULL)
printf(\nList is empty);
while (p!=NULL)
{
printf(%c,p->data);
p=p->next;
}
}
26

addatbeg(char x)
{
struct Node *r;
r=malloc(sizeof(struct Node));
r->info=x;
r->prev=NULL;
r->next=HEAD;
HEAD=r;
}
addatend(char x)
{
node *temp, *r;
temp=HEAD;
while (temp->next!=NULL)
temp=temp->next;
r=malloc(sizeof(struct Node));
r->info=x;
r->prev=temp;
r->next=NULL;
temp->next=r;
}
addatk(int k,char x)
{
node *temp, *r;
temp=head;
int i=1;
while (i<k-1)
temp=temp->next;
r=malloc(sizeof(struct Node));
r->info=x;
r->next=temp->next;
(temp->next)->prev=r;
r->prev=temp;
temp->next=r;
}
delete(char x)
{
node *temp;
temp=head;
while (temp!=NULL)
{
if (temp->info==x)
{
if (head==temp)
{
temp->next->prev=NULL;
head=temp->next;
27

}
else
{

}
else
}

main()
{

temp->prev->next=temp->next;
temp->next->prev=temp->prev;

temp=temp->next;

clrscr();
display();
addatbeg(a);
addatbeg(b);
display();
addatend(c);
display();
addatk(2,d);
display();
count();
search(a);
search(m);
getch();

Output:
List is empty
b a
b a c
b
d a c
The total number of nodes in the list is 4
Element found
Element not found
RADIX SORT

APPLICATIONS OF LINKED LISTS

Radix sort is a method of sorting which predates any digital computer. Actually
this method was performed on a mechanical card sorter. The sorter processes a standard
card of 80 columns, each of which may contain a character or a number. Any one of the
column will be examined and the sorter places all cards containing a given digit in an
appropriate pocket. There are ten pockets corresponding to the ten digits. Finally the
operator of sorter combines in order the deck of cards from the ten pockets. The resultant
deck contains the cards at pocket 0 at bottom and cards of pocket 9 at top.
28

Principle:
Each element in the given set has to be placed in the corresponding pocket
based upon the digit under consideration. Once the distribution is over, the elements
in various pockets have to be collected. The same process has to be repeated for all
the digits starting from LSB to MSB.
This method of sorting can be implemented by using a linked list. Sequential
allocation techniques are not practical in representing the pockets, since the number of
records occupied in a pocket cannot be predicted. It will be decided during the execution
time. Therefore each pocket will be considered as a separate linked list with two pointers
namely FRONT and REAR. FRONT is the pointer used to point the first node and REAR
is the pointer used to point the last node of the corresponding pocket.
Algorithm:
ALGORITHM RADIXORT(HEAD, M)
// HEAD is the address of the first node of the list of data items
// M is the number of digits of the largest number
Begin
For I=1 to M
Begin
FOR K=0 TO 9
FRONT[K] REAR[K] NULL
WHILE(HEAD!=NULL)
BEGIN
D Jth digit(INFO(P))
If (FRONT[D]==NULL) THEN
FRONT[D] REAR[D] P
P LINK(P)
LINK(REAR[D]) NULL
ELSE
LINK(REAR[D]) P
P LINK(P)
REAR[D] LINK(REAR[D])
LINK(REAR[D]) NULL
END IF
END
I 0
WHILE (FRONT[I]=NULL)
I I+1
HEAD FRONT[I]
FOR K=I+1 TO 9
IF (FRONT[I]!=NULL)THEN
LINK(REAR[I]) FRONT[K]
I K
END

29

For example

Initially all the pockets will be empty i.e, all the front and rear pointers will be NULL
Front[0]
Front[1]
Front[2]
Front[3]
Front[4]
Front[5]
Front[6]
Front[7]
Front[8]
Front[9]

null
null
null
null
null
null
null
null
null
null

Rear[0]
Rear[1]
Rear[2]
Rear[3]
Rear[4]
Rear[5]
Rear[6]
Rear[7]
Rear[8]
Rear[9]

After completion of one pass (for LSB)


Front[0]

null

Rear[0]

Front[2]
Front[3]
Front[4]

null
null
null

Rear[2]
Rear[3]
Rear[4]

Front[7]
Front[8]
Front[9]

null
null
null

Rear[7]
Rear[8]
Rear[9]

By combining all the pockets the resultant list is

30

After the second pass( next digit to the LSB)


Front[0]
Front[1]

null
null

Rear[0]
Rear[1]

Front[3]

null

Rear[3]

Front[6]

null

Rear[6]

Front[8]
Front[9]

null
null

Rear[8]
Rear[9]

By combining all the pockets the resultant list is

31

UNIT-II
STACK
The data structures seen so far, allows insertion and deletion of elements at any
place. But sometimes it is required to permit the addition and deletion of elements only
at one end that is either at the beginning or at the end.
Stacks: A stack is a data structure in which addition of new element or deletion of an
existing element always takes place at the same end. This end is often known as top of
stack. Stack is also called as Last-In-First-Out (LIFO) list because the element which
was placed most recently will be deleted first.
Operations on Stack:
There are four possible operations done on a stack. They are

Push: Allows adding an element at the top of the stack.


Pop: Allows removing an element from the top of the stack.
Peep: Allows to access the Ith element from the top of the stack
Change: Allows changing the Ith element from the top of the stack by new value.

The Stack can be implemented using both arrays and linked lists. When dynamic
memory allocation is preferred we go for linked lists to implement the stacks.
ARRAY IMPLEMENTATION OF THE STACK
Push operation:
If the elements are added continuously to the stack using the push operation then
the stack grows at one end. Initially when the stack is empty the top = -1. The top is a
variable which indicates the position of the topmost element in the stack.

ALGORITHM PUSH(S,N,TOP,X)
// S is the stack name
// N is the size of an array S
// Top is the index of the topmost element
// X is the element to be pushed
Begin
If (Top = N 1) then
Write Stack is full
Return
Else
Top Top + 1
S[Top] X
End if
End
The algorithm first checks for some empty locations by comparing the top value
with the index of the last location. If top variable has the respective index then stack
overflow message will be printed else the element X will be placed in the top most
position and top variable will be made to point that location.
Pop operation:
On deletion of elements the stack shrinks at the same end, as the elements at the
top get removed.

ALGORITHM POP(S,TOP )
// S is the stack name
// TOP is the index of the top most element
Begin
If (Top < 0 ) Then
Write Stack is empty
Return
Else
Item S[Top]
Top Top 1
Return (Item)
End if
End
2

The pop algorithm first checks whether the stack is empty or not by checking the
top variable value. If the top value is less than 0 then stack underflow error message will
gets displayed and the control gets returned. Suppose the stack contains some elements
with it means the top most element gets extracted and returned to the invoked side after
reducing the top value by 1.
Peep Operation:
Peep operation allows extracting the Ith element from the top of the stack. The
Index I will gets validated by checking the result of the expression (Top-I+1). If the result
of the expression is less than zero then Invalid Index Message will gets displayed and the
control gets returned. If the index is valid then appropriate element gets extracted and
returned to the invoking side.

If I = 2 then (Top-I+1)=1. Since the result of the expression is greater than 0 the
appropriate element S[1]=40 will be returned to the invoking side.
ALGORITHM PEEP(S,TOP,I)
// S is the stack name
// TOP is the index of the top most element
// I is the position of the element to be peeped
Begin
If ((Top-I+1)< 0 ) Then
Write Invalid Index
Return
Else
Item S[Top-I+1]
Return (Item)
End if
End
Change Operation:
Change operation allows changing the Ith element from the top of the stack by a
new value. The Index I will gets validated by checking the result of expression (Top-I+1).
If the result of the expression is less than zero then Invalid Index Message will gets
displayed and the control gets returned. If the index is valid then appropriate element gets
replaced by a new element.

If the second element has to be replaced by a new element say 67 then the
expression (top-I+1) gets evaluated. Since the result is greater than zero the respective
element gets replaced by a new element
ALGORITHM CHANGE(S,TOP,I,X)
// S is the stack name
// TOP is the index of the top most element
// I is the position of the element to be peeped
// X is the element which is going to replace
Begin
If ((Top-I+1)< 0 ) Then
Write Invalid Index
Return
Else
S[Top-I+1] X
End if
End
If arrays are used for implementing the stacks, it would be very easy to manage
the stacks. However, the problem with an array is that we are required to declare the size
of the array before using it in a program. This means the size of the stack should be
fixed. We can declare the array with a maximum size large enough to manage a stack.
As result, the stack can grow or shrink within the space reserved for it. The following
program implements the stack using array.
Program:
// Stack and various operations on it
#include <stdio.h>
#include <conio.h>
char S[10];
int top=-1,N=10;
push(char x)
{
if (top==N-1)
{
printf(\nStack is full!");
}
else
4

top++;
S[top]=x;

char pop()
{
char c;
if (top==-1)
{
printf("\nStack is empty!");
return (-1) ;
}
else
{
c=S[top];
top--;
return (c);
}
}
char peep(int i){
if((top-i+1)<0){
printf(\n Invalid Index);
return(-1);
}
else
{
return(S[top-i+1]);
}
}
change(int i,char x)
{
if((top-i+1)<0){
printf(\n Invalid Index);
}
else
{
S[top-i+1]=x;
}
}
display(){
int i;
if(top==-1)
printf(\n The stack is empty);
else{
printf(\nThe content of the stack is\n);
for(i=top;i>=0;i--)
5

}
}
main()
{

printf(%c ,S[top]);

char c;
clrscr();
display();
push(a);
push(b);
display();
c=pop();
display();
push(b);
push(c);
display();
c=peep(2);
printf("\nPeeped item:%c",c);
change(2,g);
display();

Output:
The stack is empty
The content of the stack is
b a
The content of the stack is
a
The content of the stack is
c b a
Peeped item b
The content of the stack is
c g a
LINKED LIST IMPLEMENTATION OF STACK
Stack is said to be a linked stack if it gets implemented using linked list. In this
implementation the list will be treated as a stack. While doing the operations either front
end or the rear end may be used as a top end. It is always preferable to use the front as a
top end in order to save the time of traversal operation to visit the last node for doing the
respective operation.
Initially, when the stack is empty, HEAD variable points to NULL. The push
operation in the linked stack is similar to the first node addition in the linked list. When
an element is added using the push operation, the variable HEAD is made to point to the
latest element whichever is added and the present first element will be made as a second
element.
Push operation:
Create a temporary node and store the value of x in the data part of the node.
Now make link part of temp point to HEAD and then HEAD point to Temp. That will
make the new node as the topmost element in the stack.
6

ALGORITHM PUSH(HEAD,X)
BEGIN
Info(temp) X
Link(temp) HEAD
HEAD temp
End
Pop operation
The data in the topmost node of the stack is first stored in a variable called item.
Then a temporary pointer is created to point to top most node. The HEAD is now safely
moved to the next node below it in the stack. Temp node is deleted and the item is
returned. If the list is empty then stack underflow message will gets displayed and the
control will be returned.

ALGORITHM POP(HEAD )
BEGIN
If (HEAD = NULL)Then
Write Stack is empty
Return
Else
Item info(top)
Temp HEAD
HEAD link(HEAD)
Link(Temp) NULL
Return item
End if
End
Peep operation
If the list contains some node in the I th position then the data in the I th node
from the top of the stack is first stored in a variable called item. Finally the value in the
variable item will be returned.

If the second element has to be peeped then the value of I is equal to 2. The
information part of the second element 80 will be returned to the invoking side.
ALGORITHM PEEP(HEAD,I)
BEGIN
If (HEAD = NULL)Then
Write Stack is empty
Return
Else
Count 1
P HEAD
While (Count<I) and (P<>NULL)
Begin
P Link(P)
Count Count+1
End
If (P=NULL) Then
Write(Invalid Index)
Quit
Else
Return(Info(P))
End if
8

End if
End
Change operation
If the list contains some node in the I th position then the data in the I th node
from the top of the stack will be replaced by the new value supplied by the user.

If the second element has to be changed by a new value 65 then the value of I is
equal to 2 and X is equal to 65. The information part of the second element 80 will be
replaced by a new value 65.
ALGORITHM CHANGE(HEAD,I,X)
BEGIN
If (HEAD = NULL)Then
Write Stack is empty
Return
Else
Count 1
P HEAD
While (Count<I) and (P<>NULL)
Begin
P Link(P)
Count Count+1
End
If (P=NULL) Then
Write(Invalid Index)
Quit
Else
Info(P) X
End if
End if
End

The following program implements the stack using linked lists.


Program:
// Stack implemented using linked list
#include <stdio.h>
#include <conio.h>
struct node
{
char data;
struct node *link;
};
struct node *HEAD=NULL;
push(char x)
{
struct node *temp;
temp=malloc(sizeof(struct node)*1);
temp->data=x;
temp->link=HEAD;
HEAD=temp;
}
char pop()
{
char c;
if (HEAD==NULL)
{
printf(Stack is empty!");
return(-1);
}
c=HEAD->data;
HEAD=HEAD->link;
return c;
}
char peep(int i){
struct node *p;
int c;
p=HEAD;
if(p==NULL){
printf(\nStack is empty);
return(-1);
}
c=1;
while((c<i)&&(p!=NULL)){
10

p=p->link;
c++;

}
if(p!=NULL){
printf(\nInvalid Index);
return(-1);
}
else
return(p->info);

change(int i,char x){


struct node *p;
int c;
p=HEAD;
if(p==NULL){
printf(\nStack is empty);
}
c=1;
while((c<i)&&(p!=NULL)){
p=p->link;
c++;
}
if(p!=NULL){
printf(\nInvalid Index);
}
else
p->info=x;
}
display()
{
struct node *temp;
temp=HEAD;
if(temp==NULL)
printf(\nStack is empty);
else{
printf(\nThe content of the stack is);
while (temp!=NULL)
{
printf(%c,temp->data);
temp=temp->link;
}
}
}
main()
{

clrscr();
char n;
display();
11

push(a);
push(b);
push(c);
display();
n=pop();
n=peep(2);
printf(\nPeeped item:%c",n);
push(d);
change(2,h);
display();
getch();

Output:
Stack is empty
The content of the stack is
c b a
Peeped item b
d h b a
APPLICATIONS OF STACK
Conversion of Infix Expression to Postfix Expression
The stacks are frequently used in evaluation of arithmetic expressions. An
arithmetic expression consists of operands and operators. The operands can be numeric
values or numeric variables. The operators used in an arithmetic expression represent the
operations like addition, subtraction, multiplication, division and exponentiation.
There are 3 different ways by which an expression can be written. They are
1. Infix notation
2. Prefix notation
3. Postfix notation
The arithmetic expression expressed in its normal form is said to be Infix
notation, as shown:
A+B
The above expression in prefix form would be represented as follows:
+ AB
The same expression in postfix form would be represented as follows:
AB +
Stack is having the capability to evaluate the postfix expression. Hence the given
expression in infix form is first converted to postfix form and then evaluated to get the
results. An algorithm called POSTFIX parse the given expression and give the postfix
notation of the given expression. Parsing is the process of breaking the given expression
into various tokens. A token is a small element of an expression it may be operand or
operator or any special symbol.

12

ALGORITHM POSTFIX(E)
// Convert the infix expression E to postfix. Assume the last character of E is a , which
will also be the last character of the postfix. Procedure NEXT TOKEN returns the next
operator, operand or delimiter-whichever comes next. A special symbol - is pushed
into the stack initially. The priority of the special symbol is less than any token.//
Begin
Loop
X NEXTTOKEN(E)
Case
X= :
While top>1 do
Print(Stack[Top])
Top Top-1
End while
Return
X is an operand
Print(X)
X=)
While Stack[top]<>( do
Print(Stack[Top])
Top Top-1
End while
Top Top-1
Else
While Priority(Stack[Top])>=Priority(X) do
Print(Stack[Top]);
Top Top-1
End while
Call Push (Stack,N,Top,X)
End forever
End
Example:
Let the given expression be (a+b)*c. It will be given as an input to the algorithm
after appending special symbol to it.
Initially Stack contains Stack:

Output:

Next Token is ( (Since it is operator and its priority is greater than top of the stack is
will be pushed in to the stack)
Output:
Stack:

13

Next Token is a (Since it is a operand it will be printed)

Output: a

Next Token is + (Since it is operator and its priority is greater than top of the stack is will
be pushed in to the stack)
Output: a
Stack:

Next Token is b (Since it is a operand it will be printed)

Output: ab

Next Token is ) (All tokens up to ( will be popped and printed) Output: ab+
Stack:

Next Token is * (Since it is operator and its priority is greater than top of the stack is will
be pushed in to the stack)
Output: ab+
Stack:

Next Token is c (Since it is a operand it will be printed)


Output: ab+c
Next Token is (Till the stack becomes empty all the symbols will be popped and
printed)
Output: ab+c*

Evaluation of Expression entered in postfix form


The program takes the input expression in postfix form. This expression is
scanned character by character. If the character scanned is an operand, then first it is
converted to a digit form and then it is pushed onto the stack. If the token scanned is an
operator, then the respective number of operands will be popped from the stack An
arithmetic operation is performed between the popped operands. The type of arithmetic
operation depends on the operator scanned from the postfix expression. The result is then
pushed back onto the stack. These steps are repeated as long as the string s is not
exhausted. Finally the value in the stack is the required result and is shown to the user.

14

ALGORITHM EVALUATE(EXPN)
//EXPN is the postfix notation of the given expression
Begin
While some token exist to parse
X NEXT TOKEN(EXPN)
Case
X=Operand
Push the operand into the stack
X=operator
Pop the respective operands from the stack and
Perform the respective operation on it and push the
result again into the stack.
End while
Print (Stack[Top])
End.
TOWERS OF HANOI
In the towers of Hanoi problem, we are given n disks and three towers. The disks
are initially stacked on tower 1 in decreasing order of size of bottom to top. We are to
move the disks to tower 2, one disk at a time, such that no disk is ever on top of a smaller
one. You may wish to attempt a solution to this problem for n=2,3 and 4.
A very elegant solution results from the use of recursion. To get the largest disk to
the bottom of tower 2, we move the remaining n-1 disks to tower 3 and then move the
largest to tower 2. Now we are left with the task of moving the n-1 disks from tower 3 to
tower 2. To perform this task, we can use towers 1 and 2. We can safely ignore the fact
that tower 2 has a disk on it because this disk is larger than the disks being moved from
tower 3. Therefore, we can place any disk on top of it. In order to transfer n disks from
source tower to destination tower 2n-1 moves are required.

ALGORITHM TOWERS OF HANOI(N,A,C,B)


//N represents the total number of disks to be transferred
//A is a source tower
//B is an auxiliary tower
//C is the destination tower
Begin
If (n==1) then
Move Disk 1 from A to C
Return
Else
15

End

TOWERS OF HANOI(N-1,A,B,C)
Move Disk n from A to C
TOWERS OF HANOI(N-1,B,C,A)

QUEUE
Queue: Queue is a linear data structure that permits insertion of new element at one end
and deletion of an element at the other end. The end at which the deletion of an element
take place is called front, and the end at which insertion of a new element can take place
is called rear. The deletion or insertion of elements can take place only at the front or
rear end of the list respectively.
The first element that gets added into the queue is the first one to get removed
from the list. Hence, queue is also referred to as First-In-First-Out list (FIFO). Queues
can be represented using both arrays as well as linked lists.
ARRAY IMPLEMENTATION OF QUEUE
If queue is implemented using arrays, the size of the array should be fixed
maximum allowing the queue to expand or shrink.
Operations on a Queue
There are two common operations done in a queue. They are addition of an
element to the queue called insertion and deletion of an element from the queue. Two
variables front and rear are used to point to the either ends of the queue. The front points
to the front end of the queue where deletion takes place and rear points to the rear end of
the queue, where the addition of elements takes place. Initially, when the queue is empty,
the front and rear is equal to -1.
Insert()
An element can be added to the queue only at the rear end of the queue. Before
adding an element in the queue, it is checked whether queue is full. If the queue is full,
then addition cannot take place. Otherwise, the element is added to the end of the list at
the rear side.

16

ALGORITHM INSERT(Q,N,FRONT,REAR,X)
BEGIN
If (rear = N1) Then
Write Queue is full
Return
Else
Rear = rear + 1
Q[rear] = x
If (front = -1) Then
Front = 0
End if
End if
End
Deletion( )
The deletion( ) operation deletes the element from the front of the queue. Before
deleting and element, it is checked if the queue is empty. If not the element pointed by
front is deleted from the queue and front is now made to point to the next element in the
queue.

ALGORITHM DELETION(Q,N,FRONT,REAR )
BEGIN
If (front = -1)Then
Write Queue is Empty
Return
Else
Item = Q[front]
If (front = rear)Then
Front = rear = -1
Else
Front = front + 1
End if
Return item
End if
End

17

Program:
// Queues and various operations on it Using arrays
#include <stdio.h>
#include <conio.h>
char Q[10];
int front=-1,rear=-1,n=10;
insert(char x)
{
if (rear==n-1)
{
printf(\nQueue is full!");
}
rear++;
Q[rear]=x;
if (front==-1)
front=0;
}
char deletion()
{
char c;
if (front==-1)
{
printf("\nQueue is empty!");
return (-1);
}
c=Q[front];
if (front==rear)
front=rear=-1;
else
front++;
return c;
}
display()
{
int i;
if (front==-1)
printf(\nThe queue is empty);
else{
printf(\nThe content of queue is \n);
for (i=front; i<=rear; i++)
printf(%c ,Q[i]);
}
}
main()
{

char c;
clrscr();
18

display();
insert(a);
insert(b);
insert(c);
display();
c=deletion();
display();
getch();

}
Output:
The Queue is empty
The content of queue is
a b c
The content of queue is
b c
LINKED LIST IMPLEMENTATION OF QUEUE
Queue is said to be linked queue if it gets implemented using linked list. Queue
can be represented using a linked list. Linked lists do not have any restrictions on the
number of elements it can hold. Space for the elements in a linked list is allocated
dynamically; hence it can grow as long as there is enough memory available for dynamic
allocation. The queue represented using linked list would be represented as shown. The
end which is pointed by the variable HEAD is used for deletion and the another end will
be used for insertion.

INSERT()
In linked list representation of queue, the addition of new element to the queue
takes place at the rear end. It is the normal operation of adding a node at the end of a list.
ALGORITHM INSERT(HEAD,X)
BEGIN
Info(Temp) X
Link(Temp) NULL
If (HEAD = NULL)Then
HEAD Temp
Else
P HEAD
While(Link(P)<>NULL)
P Link(P)
Link(P) Temp
End if
End
19

DELETION( )
The deletion( ) operation deletes the first element from the front end of the queue.
Initially it is checked, if the queue is empty. If it is not empty, then return the value in the
node pointed by front, and moves the front pointer to the next node else displays the
queue empty message.
ALGORITHM DELETION(HEAD )
BEGIN
If (HEAD = NULL)Then
Write Queue is empty
Else
Temp HEAD
HEAD Link(HEAD)
Link(Temp) NULL
Return(Info(Temp))
End if
End
Program:
// Queue implemented using linked lists
#include <stdio.h>
#include <conio.h>
struct node
{
char data;
struct node *link;
};
struct node *HEAD=NULL;
insert(char x)
{
struct node *temp,*p
temp=malloc(sizeof(struct node)*1);
temp->data=x;
temp->link=NULL;
if (HEAD==NULL)
HEAD=temp;
else
{
p=HEAD;
while(p->link!=NULL)
p=p->link;
p->link=temp;
}
}
char deletion()
20

char c;
struct node *temp;
if (HEAD==NULL)
{
printf(\nQueue is empty!");
return -1;
}
else{
temp=HEAD;
HEAD=HEAD->link;
temp->link=NULL;
return temp->data;

display()
{
struct node *temp;
temp=HEAD;
if(HEAD==NULL)
printf(\nThe queue is empty);
else{
printf(\nThe content of the queue is \n);
while (temp!=NULL)
{
printf( %c ,temp->data);
temp=temp->link;
}
}
}
main()
{
char c;
clrscr();
display();
insert(a);
insert(b);
insert(c);
display();
c=deletion();
display();
getch();
}
Output:
The queue is empty
The content of queue is
a b c
The content of queue is
b c
21

APPLICATIONS OF QUEUE
IMAGE COMPONENT LABELING
A digitized image is m*m matrix of pixels. In a binary image each pixel is either
0 or 1. A pixel with value 0 represents image background, while a pixel with value 1
represents a point on an image. A pixel is said to be a component pixel if its value is 1.
Two pixels are adjacent if one is to the left, right, above or below to other. Two
component pixels that are adjacent are pixels of the same image component. The
objective of component labeling is to label the component pixels so that two pixels get
the same label iff they are pixels of the same image component.
1
1

2
1

1
1
1

1
1

3
3

5
5
5

7*7 Image
Labeled Components
In the above figure the blank squares represent background pixels, and the 1s
represent component pixels, pixels (1,3) and (2,3) are pixels of same component because
they are adjacent. Since (2,3) and (2,4) are adjacent, they are also of the same component.
Hence the three pixels (1,3), (2,3) and (2,4) are from the same component. Since there are
no other image pixels adjacent to these three pixels, these three define an image
component. The image has four components. The first component is defined by the pixel
set{(1,3),(2,3),(2,4)}, the second is {(3,5),(4,4),(4,5),(5,5)}, the third is
{(5,2),(6,1),(6,2),(6,3),(7,1),(7,2),(7,3)}; and the fourth is {(5,7),(6,7),(7,6),(7,7)}. The
labeled components diagram the component pixels have been given labels so that two of
them have the same label iff they are part of the same component.
To move around the image with ease, we surround the image with a wall of blank
i.e, pixels. We use the offset array to determine the pixels adjacent to a given pixel. The
components are determined by scanning the pixels by rows and within rows by columns.
When an unlabeled component pixel is encountered, it is given a component label. The
pixel forms the seed of a new component. We determine the remaining pixels in the
component by identifying and labeling all component pixels that are adjacent to the seed.
Call the pixels that are adjacent to the seed the distance 1 pixels. Then unlabeled
component pixels that are adjacent to the distance 1 pixels are identified and labeled. The
processes get repeated till all the components get labeled.

22

ALGORITHM IMAGELABELING()
Begin
For I=0 to M+1
Pixel[0][i]
Pixel[M+1][i] Pixel[i][0] Pixel[i][M+1] 0
Rows[4]={0,1,0,-1}
Columns[4]={1,0,-1,0}
Label 2
For R=1 to M
For C=1 to M
If (Pixel[R][C] = 1) Then
Pixel[R][C] label
Cur.Row=R
Cur.Col=C
Do
begin
For I=1 to 4
Adj.row Cur.Row + Row[I]
Adj.col Cur.Col + Columns[I]
If (Pixel[Adj.Row][Adj.col]=1) then
Pixel[Adj.Row][Adj.col]=label
Qinsert(Adj)
If (Qempty()=True) Then
Break;
Else
Cur Qdelete()
End while
Label label+1
End for
End for
End

23

UNIT III
TREES
A tree is a non-linear data structure that is used to represents hierarchical
relationships between individual data items.
Tree: A tree is a finite set of one or more nodes such that, there is a specially designated
node called root. The remaining nodes are partitioned into n>=0 disjoint sets T1,
T2,..Tn, where each of these set is a tree T1,Tn are called the subtrees of the root.
Branch: Branch is the link between the parent and its child.
Leaf: A node with no children is called a leaf.
Subtree: A Subtree is a subset of a tree that is itself a tree.
Degree: The number of subtrees of a node is called the degree of the node. Hence nodes
that have degree zero are called leaf or terminal nodes. The other nodes are referred as
non-terminal nodes.
Children: The nodes branching from a particular node X are called children of X and X
is called its parent.
Siblings: Children of the same parent are said to be siblings.
Degree of tree: Degree of the tree is the maximum of the degree of the nodes in the tree.
Ancestors: Ancestors of a node are all the nodes along the path from root to that node.
Hence root is ancestor of all the nodes in the tree.
Level: Level of a node is defined by letting root at level one. If a node is at level L, then
its children are at level L + 1.
Height or depth: The height or depth of a tree is defined to be the maximum level of any
node in the tree.
Climbing: The process of traversing the tree from the leaf to the root is called climbing
the tree.
Descending: The process of traversing the tree from the root to the leaf is called
descending the tree.

BINARY TREE
Binary tree has nodes each of which has no more than two child nodes.
Binary tree: A binary tree is a finite set of nodes that either is empty or consists of a root
and two disjoint binary trees called the left subtree and right subtree.
Left child: The node present to the left of the parent node is called the left child.
Right child: The node present to the right of the parent node is called the right child.

Skewed Binary tree: If the new nodes in the tree are added only to one side of the binary
tree then it is a skewed binary tree.
Strictly binary tree: If the binary tree has each node consisting of either two nodes or no
nodes at all, then it is called a strictly binary tree.
Complete binary tree: If all the nodes of a binary tree consist of two nodes each and the
nodes at the last level does not consist any nodes, then that type of binary tree is called a
complete binary tree.
It can be observed that the maximum number of nodes on level i of a binary tree
is 2i - 1, where i 1. The maximum number of nodes in a binary tree of depth k is 2k 1,
where k 1.

REPRESENTATION OF BINARY TREES


There are two ways in which a binary tree can be represented. They are:
(i)
(ii)

Array representation of binary trees.


Linked representation of binary trees.

ARRAY REPRESENTATION OF BINARY TREES


When arrays are used to represent the binary trees, then an array of size 2k is
declared where, k is the depth of the tree. For example if the depth of the binary tree is 3,
then maximum 23 - 1 = 7 elements will be present in the node and hence the array size
will be 8. This is because the elements are stored from position one leaving the position
0 vacant. But generally an array of bigger size is declared so that later new nodes can be
added to the existing tree. The following binary tree can be represented using arrays as
shown.

Array representation:

The root element is always stored in position 1. The left child of node i is stored in
position 2i and right child of node is stored in position 2i + 1. Hence the following
formulae can be used to identify the parent, left child and right child of a particular node.
Parent( i ) = i / 2, if i

1. If i = 1 then i is the root node and root does not has parent.

Left child( i ) = 2i, if 2i n, where n is the maximum number of elements in the tree. If
2i > n, then i has no left child.
Right child( i ) = 2i + 1, if 2i + 1

n. If 2i + 1 > n, then i has no right child.

The empty positions in the tree where no node is connected are represented in the array
using -1, indicating absence of a node.
Using the formula, we can see that for a node 3, the parent is 3/ 2 1. Referring to the
array locations, we find that 50 is the parent of 40. The left child of node 3 is 2*3
6.
But the position 6 consists of -1 indicating that the left child does not exist for the node 3.
Hence 50 does not have a left child. The right child of node 3 is 2*3 + 1
7. The
position 7 in the array consists of 20. Hence, 20 is the right child of 40.
LINKED REPRESENTATION OF BINARY TREES
In linked representation of binary trees, instead of arrays, pointers are used to
connect the various nodes of the tree. Hence each node of the binary tree consists of
three parts namely, the info, left and right. The info part stores the data, left part stores
the address of the left child and the right part stores the address of the right child.
Logically the binary tree in linked form can be represented as shown.

The pointers storing NULL value indicates that there is no node attached to it.
Traversing through this type of representation is very easy. The left child of a particular
node can be accessed by following the left link of that node and the right child of a
particular node can be accessed by following the right link of that node.

BINARY TREE TRAVERSALS


There are three standard ways of traversing a binary tree T with root R. They are:
( i ) Preorder Traversal
(ii ) Inorder Traversal
(iii) Postorder Traversal
General outline of these three traversal methods can be given as follows:
Preorder Traversal:
(1) Process the root R.
(2) Traverse the left subtree of R in preorder.
(3) Traverse the right subtree of R in preorder.
Inorder Traversal:
(1) Traverse the left subtree of R in inorder.
(2) Process the root R.
(3) Traverse the right subtree of R in inorder.
Postorder Traversal:
(1) Traverse the left subtree of R in postorder.
(2) Traverse the right subtree of R in postorder.
(3) Process the root R.

Observe that each algorithm contains the same three steps, and that the left
subtree of R is always traversed before the right subtree. The difference between the
algorithms is the time at which the root R is processed. The three algorithms are
sometimes called, respectively, the node-left-right (NLR) traversal, the left-node-right
(LNR) traversal and the left-right-node (LRN) traversal.
Now we can present the detailed algorithm for these traversal methods in both
recursive method and iterative method.
Traversal algorithms using recursive approach
Preorder Traversal
In the preorder traversal the node element is visited first and then the right subtree
of the node and then the right subtree of the node is visited. Consider the following case
where we have 6 nodes in the tree A, B, C, D, E, F. The traversal always starts from the
root of the tree. The node A is the root and hence it is visited first. The value at this node
is processed. The processing can be doing some computation over it or just printing its
value. Now we check if there exists any left child for this node if so apply the preorder
procedure on the left subtree. Now check if there is any right subtree for the node A, the
preorder procedure is applied on the right subtree.
Since there exists a left subtree for node A, B is now considered as the root of the
left subtree of A and preorder procedure is applied. Hence we find that B is processed
next and then it is checked if B has a left subtree. This recursive method is continued
until all the nodes are visited.

The algorithm for the above method is presented in the pseudo-code form below:
Algorithm
PREORDER( ROOT )
Begin
Temp = ROOT
If temp = NULL
Return
End if
Print info(temp)
PREORDER( left(temp))
PREORDER(right(temp))
End if
End PREORDER
Inorder Traversal
In the Inorder traversal method, the left subtree of the current node is visited first
and then the current node is processed and at last the right subtree of the current node is
visited. In the following example, the traversal starts with the root of the binary tree.
The node A is the root and it is checked if it has the left subtree. Then the inorder
traversal procedure is applied on the left subtree of the node A. Now we find that node D
7

does not have left subtree. Hence the node D is processed and then it is checked if there
is a right subtree for node D. Since there is no right subtree, the control returns back to
the previous function which was applied on B. Since left of B is already visited, now B is
processed. It is checked if B has the right subtree. If so apply the inroder traversal
method on the right subtree of the node B. This recursive procedure is followed till all
the nodes are visited.

Algorithm
INORDER( ROOT )
Begin
Temp = ROOT
If temp = NULL
Return
End if
INORDER(left(temp))
Print info(temp)
INORDER(right(temp))
End INORDER
Postorder Traversal
In the postorder traversal method the left subtree is visited first, then the right
subtree and at last the current node is processed. In the following example, A is the root
node. Since A has the left subtree the postorder traversal method is applied recursively
on the left subtree of A. Then when left subtree of A is completely is processed, the
postorder traversal method is recursively applied on the right subtree of the node A. If
right subtree is completely processed, then the current node A is processed.

Algorithm
POSTORDER( ROOT )
Begin
Temp = ROOT
If temp = NULL
Return
End if
POSTORDER(left(temp))
POSTORDER(right(temp))
Print info(temp)
End POSTORDER

SIGNAL BOOSTER PROBLEM


In a distribution network a resource is distributed from its origin to several other
sites. For example electrical power may be distributed from a source to various
consumption sites using a network of wires. While distributing a signal (Power) to
various sites through some medium it may experience a loss in or degradation of one or
more of its characteristics. So there may be a voltage drop along a transmission line.
Between the signal source and point of consumption certain amount of signal drop will be
tolerated. To guarantee a degradation that does not exceed this amount, signal boosters
are placed at strategic places in the network. A signal booster might, increase the signal
voltage so that it equals that at the source or may enhance the signal so that the signal to
noise ratio is the same as that as the source. Our objective is to develop an algorithm to
determine where to place the signal boosters and to minimize the number of boosters.
The distribution network is assumed as a tree with the source as a root. Each node
in the tree represents a substation where we can place a booster. The signal flows to
various nodes along the branches. Each edge is labeled by the amount of signal
degradation that takes place when a signal flows between the corresponding parent and
child. The units of degradation are assumed to be additive. The degradation is 5 at the
node v for the signal flowing from p.

10

Let d(i) denote the degradation from node I and its parent. According to our
example d(w)=2, d(p)=0. Since signal boosters can be placed only at nodes of the
distribution tree, the presence of a node I with d(i)> tolerance implies that no placement
of boosters can prevent signal degradation from exceeding tolerance. For any node i in a
graph, let D(i) denote the maximum signal degradation from node I to any leaf in the
subtree rooted at i. If I is a leaf node then D(i)=0. For the remaining nodes D(i) may be
computed using the following equality
D(i) =

max
{D(j)+d(j) }
j is a child of i

So D(s)=2. To use this equation, we must compute the D value of a node after
computing that of its children. Therefore, we must traverse the tree so that we visit a node
after we visit its children. We can compute the D value of a node when we visit it.
Suppose that during the computation of D as described above, we encounter a node I with
a child j such that D(j) + d(j) > tolerance. If we do not place a booster at j, then signal
degradation from I to a lead will exceed tolerance even if a booster is placed at i.
Algorithm:
Begin
D(i)=0
For (each child j of I )
If (D ( j ) + d ( j )>tolerance) then
Place a booster at j
Else
D( I )= max{ D(i), D( j ) + d ( j )}
End if
End for
End

11

GRAPHS
Graph: A graph G is a defined as a set of objects called nodes and edges.
G = (V, E)
A graph G consists of two things:
1. A set V of elements called nodes (or points or vertices)
2. A set E of edges such that each edge e in E is identified with a unique pair [u,v] of
nodes in V, denoted by e = [u,v]
Node: A node is a data element of the graph.
Edge: An edge is a path between two nodes.
There are two types of graph. They are
1. Undirected graph
2. Directed graph
Undirected graph: An undirected graph is a graph in which the edges are not
directionally oriented towards a node.
Directed graph: A Directed graph or a Digraph is a graph in which the edges are
directionally oriented towards any node.

Arc: The directed edge in a directed graph is called an arc.


Strongly connected graph: A Directed graph is called a strongly connected graph if for
any two nodes I and J, there is a directed path from I to J and also from J to I.
12

Weakly connected graph: A Directed graph is called a weakly connected graph if for
any two nodes I and J, there is a directed path from I to J or from J to I.
Outdegree : The number of arcs exiting from the node is called outdegree of that node.
Indegree: The number of arcs entering the node is called indegree of that node.
Source node: A node where the indegree is 0 but has a positive value for outdegree is
called a source node. That is there are only outgoing arcs to the node and no incoming
arcs to the node.
Sink node: A node where the outdegree is 0 and has a positive value for indegree is
called the sink node. That is there is only incoming arcs to the node and no outgoing
arcs the node.
Cycle: A cycle in a directed graph is a directed path that originates and terminates at
the same node.
Degree of a node: In an undirected graph, the degree of a node is the number of edges
connected directly to the node.
Length of the path: The length of the path between node I and K is the number of edges
between them in a path from I to K.
For example,
In the directed graph shown above, the outdegree of A is 3. The indgree of B is 1. The
node A is the source node. The node D is the Sink node. The length of the path between
A to D is 2.
Degree: The degree of the node B in the undirected graph shown above is 3.
REPRESENTATION OF GRAPHS
There are two possible ways by which the graph can be represented.
1. Matrix representation (Array Representation)
2. Linked representation
The graphs can be represented using Adjacency matrix or otherwise called the
incidence matrix. Since the matrix is so sparse it is also called as sparse matrix.
The adjacency matrix is a N X N matrix where N is the number of nodes in the
graph. Each entry (I, J) in the matrix has either 1 or 0. An entry 1 indicates that there is a
direct connection from I to J. An entry 0 indicates that there is no direct connection from
I to J.
If an adjacency matrix is written for the above directed graph as shown:

13

Since the matrix is so sparse in nature the second method of representation will be
preferred if the number of edges is very less compared to the number of vertices.
In Linked representation it is required to maintain N linked list. Each linked list
has the adjacent vertices for the particular vertex. Since the graph contains N vertices it is
required to maintain a list for each vertex. Suppose any of the vertexes is not at all having
any adjacent vertices then the respective index will have Null Value.

Linked Representation

14

GRAPH TRAVERSALS
There are two methods for traversing through the nodes of the graph. They are:
(1) Breadth First Search Traversal (BFS)
(2) Depth First Search Traversal (DFS)
Breadth First Search Traversal (BFS)
As the name implies, this method traverses the nodes of the graph by searching
through the nodes breadth-wise. Initially let the first node of the graph be visited. This
node is now considered as node u. Now find out all the nodes which are adjacent to this
node. Let all the adjacent nodes be called as w. Add the node u to a queue. Now every
time an adjacent node w is visited, it is added to the queue. One by one all the adjacent
nodes w are visited and added to the queue. When all the unvisited adjacent nodes are
visited, then the node u is deleted from the queue and hence the next element in the queue
now becomes the new node u. The process is repeated on this new node u. This is
continued till all the nodes are visited.
The Breadth First Traversal (BFT) algorithm calls the BFS algorithm on all the nodes.
Algorithm
BFT(G, n)
Repeat for i = 1 to n
Visited[i] = 0
End Repeat
Repeat for i = 1 to n
If visited[i] = 0
BFS(i)
End if
End Repeat
BFS(v)
u=v
visited[v] = 1
Repeat while(true)
Repeat for all vertices w adjacent to u
If visited[w] = 0
Add w to queue
Visited[w] = 1
End if
End Repeat
If queue is empty
Return
End if
Delete u from queue
End while
End BFS

15

16

Now the following diagrams illustrate the BFS on a directed graph.

Depth First Search Traversal (DFS)


In the Depth First Search Traversal, as the name implies the nodes of the graph
are traversed by searching through all the nodes by first going to the depth of the graph.
The first node is visited first. Let this be node u. Find out all the adjacent nodes of u.
Let that be w. Apply the DFS on the first adjacent node recursively. Since a recursive
approach is followed, the nodes are traversed by going to the depth of the graph first.
The DFT algorithm calls the DFS algorithm repeatedly for all the nodes in the graph.

17

Algorithm
DFT(G, n)
Repeat for i = 1 to n
Visited[i] = 0
End Repeat
Repeat for i = 1 to n
If visited[i] = 0
DFS(i)
End if
End Repeat
DFS(v)
Visited[v] = 1
Repeat for each vertex w adjacent from v
If visited[w] = 0
DFS(w)
End if
End for

18

NETWORKS
Weight of an edge: Weight of an edge is just of the value of the edge or the cost of the
edge. For example, a graph representing cities, has the distance between two cites as the
edge cost or its weight.
Network: A graph with weighted edges is called a network.
Spanning Tree: Any tree consisting of edges in the graph G and including all vertices in
G is called a spanning tree.

19

SINGLE SOURCE SHORTEST PATH ALGORITHM:


DIJKSTRAS ALGORITHM
The Djikstras algorithm finds out the shortest path between the single source and
every other node in the graph. For example consider the following graph. Let the node 5
be the source. Let solve this using Djikstas algorithm to find the shortest paths between
5 and every other node in the graph.

A Distance array Dist[] is initially filled with infinity. The entry corresponding to the
source node 5 alone is made 0. Now find out the adjacent nodes of 5 and update their
values using the cost matrix. In the next iteration the node with minimum distance is the
vertex selected and again the above process is repeated. The Column S shows the set of
vertices already selected. In every iteration the node with minimum distance and which
is not yet selected is taken as the new vertex.
The solution is obtained as follows.
Iteration

Vertex
Dist[ ]
Selected
1
2
3
4
5
Initial
1500 0
5
6
1250 0
5,6
7
1250 0
5,6,7
4
2450 1250 0
5,6,7,4
8
3350
2450 1250 0
5,6,7,4,8
3
3350 3250 2450 1250 0
5,6,7,4,8,3
2
3350 3250 2450 1250 0
Now we can see that the values in the last row, gives the distance
between the source node 5 and every other node in the graph.

6
250
250
250
250
250
250
250
of the

1150 1650
1150 1650
1150 1650
1150 1650
1150 1650
1150 1650
shortest path

The shortest paths corresponding to this can also be generated. The paths are represented
using linked lists. Whenever a value in the distance array is updated, the shortest path
linked lists are also adjusted.
The shortest paths are represented using linked lists as shown.
20

Algorithm
DJIKSTRA(v, cost, dist, n)
For i = 1 to n
S[i] = false
Dist[i] =
End for
S[v] = true
Dist[v] = 0
Create n lists each beginning with v
For num = 1 to n 1
Choose u from among those vertices not in S such that dis[u] is minimum
S[u] = true
For each w adjacent to u with s[w] = false
If Dist[w] > Dist[u] + cost[u, w]
Dist[w] = Dist[u] + cost [u, w]
List[w] = List[u] + w
End if
End for
End for
21

ALL PAIRS SHORTEST PATH ALGORITHM (FLOYD ALGORITHM)


The All pairs shortest path algorithm is used to find the shortest path between every pair
of nodes in the graph. Consider the following example.
We will use the following condition solve the problem
A[i, j] = min(A[i, j], A[i, k] + A[k, j])
Solution is derived as follows using the above condition.

Cost Matrix
1
1
2
3
4
5

0 20
20 0 10
10 0
5
15
5 10 10

5
10
15 10
0 5
5 0

Iteration 1
1
1
2
3
4
5

Iteration 2
3

0 20
20 0 10
10 0
5 25 15
5 10 10

5
10
15 10
0 5
5 0

1
2
3
4
5

0
20
30
5
5

20
0
10
25
10

30
10
0
15
10

5
10
15 10
0 5
5 0

22

Iteration 3
1
2
3
4
5

Iteration 4

0
20
30
5
5

20
0
10
25
10

30
10
0
15
10

5
25
15
0
5

5
10
10
5
0

1
2
3
4
5

Iteration 5
1
2
3
4
5

0
20
20
5
5

20
0
10
25
10

20
10
0
15
10

5
25
15
0
5

5
10
10
5
0

Final Output matrix

0
15
15
5
5

15
0
10
15
10

15
10
0
15
10

5
15
15
0
5

5
10
10
5
0

1
2
3
4
5

0
15
15
5
5

15
0
10
15
10

15
10
0
15
10

5
15
15
0
5

5
10
10
5
0

The output matrix gives the shortest path distance between all pairs of nodes.
Algorithm
ALLPAIRSHORTESTPATH(cost, A, n)
For i = 1 to n
For j = 1 to n
A[i, j] = cost[i, j]
End for
For k = 1 to n
For i = 1 to n
For j = 1 to n
A[i, j] = min(A[i, j], A[i, k] + A[k, j])
End for
End for
End for

23

4. SEARCHING AND SORTING


SEARCHING

Searching and sorting are fundamental operations in computer science. Searching


refers to the operation of finding the location of a given item in a collection of items.
Sorting refers to the operations of arranging data in some given order, such as increasing
or decreasing, with numerical data, or alphabetically, with character data.
Searching : Searching is an operation which finds the location of a given element in a
list. The search is said to be successful or unsuccessful depending on whether the
element that is to be searched is found or not.

The two standard searching techniques are:


Linear search
Binary search.

LINEAR SEARCH
Linear search is the simplest method of searching. In this method, the element to
be found is sequentially searched in the list (Hence also called sequential search). This
method can be applied to a sorted or an unsorted list. Hence, it is used when the records
are not stored in order.
Principle : The algorithm starts its search with the first available record and proceeds to
the next available record repeatedly until the required data item to be searched for is
found or the end of the list is reached.
Algorithm :
ALGORITHM LINEARSEARCH(K, N, X )
// K is the array containing the list of data items
// N is the number of data items in the list
// X is the data item to be searched
Repeat For I = 0 to N -1 Step 1
If K( I ) = X
Then
WRITE(ELEMENT IS PRESENT AT LOCATION I)
QUIT
Else
I I+1
End If
End Repeat
WRITE(ELEMENT NOT PRESENT IN THE COLLECTION)
End LINEARSEARCH
In the above algorithm, K is the list of data items containing N data items. X is
the data item, which is to be searched in K. If the data item to be searched is found then
the position where it is found will be displayed. If the data item to be searched is not
1

found then the appropriate message will be displayed to indicate the user, that the data
item is not found.
The data item X is compared with each and every element in the list K During
this comparison, if X matches with a data item in K, then the position where the data item
was found will gets displayed and the control comes out of the loop and the procedure
comes to an end. If X does not match with any of the data items in K, then finally the
element not found will be displayed.
Example:
X

Number to be searched : 40

i=0

i =1

i=2

i=3

i=4

i=5

i=6

i=7

i=8

i=9

45

56

15

76

43

92

35

40

28

65

15

76

43

92

35

40

28

65

15

76

43

92

35

40

28

65

15

76

43

92

35

40

28

65

15

76

43

92

35

40

28

65

15

76

43

92

35

40

28

65

15

76

43

92

35

40

28

65

15

76

43

92

35

40

28

65

X K[0]
45

56

X K[1]
45

56

X K[2]
45

56

X K[3]
45

56

X K[4]
45

56

X K[5]
45

56

X K[6]
45

56

X = K[7]

th

I = 7 : Number found at location 7 i.e., as a 8 element

Program:
//Linear Search
#include <stdio.h>
#include <conio.h>
int k[10],n=10;
search(int x)
{
for (int i=0; i<n; i++)
{
if (k[i]==x){
printf(Element present at location %d, i);
exit(0);
}
}
printf(\nElement not found in the collection);
}
void main()
{
clrscr();
int i,x;
printf(\nEnter the elements);
for (i=0; i<10; i++)
scanf(%d,.&k[i]);
printf(\nEnter the element that you want to search);
scanf(%d,&x);
search(x);
}
The search( ) function gets the number to be searched in the variable x as a
argument and compares it with each and every element in the array K. If the number x
is found in the array, then the position i, where it is found will gets printed. If the
number is not found in the entire list, then the function will display the not found
message to the user.
In the main( ) function receives the n values from the user and stored in the array
K. The user is prompted to enter the number to be searched and is passed to the search( )
function as a argument. The search which receives the value x will give the appropriate
message.
Advantages:
1. Simple and straight forward method.
2. Can be applied on both sorted and unsorted list.
Disadvantages:
1. Inefficient when the number of data items in the list increases.

BINARY SEARCH
Binary search method is very fast and efficient. This method requires that the list
of elements be in sorted order. Binary search cannot be applied on an unsorted list.
Principle: The data item to be searched is compared with the approximate middle entry
of the list. If it matches with the middle entry, then the position will be displayed. If the
data item to be searched is lesser than the middle entry, then it is compared with the
middle entry of the first half of the list and procedure is repeated on the first half until the
required item is found. If the data item is greater than the middle entry, then it is
compared with the middle entry of the second half of the list and procedure is repeated
on the second half until the required item is found. This process continues until the
desired number is found or the search interval becomes empty.
Algorithm:
ALGORITHM BINARYSEARCH(K, N, X)
// K is the array containing the list of data items
// N is the number of data items in the list
// X is the data item to be searched
Lower 0, Upper N 1
While Lower Upper
Mid ( Lower + Upper ) / 2
If (X < K[Mid])Then
Upper Mid -1
Else If (X>K[Mid]) Then
Lower Mid + 1
Else
Write(ELEMENT FOUND AT, MID)
Quit
End If
End If
End While
Write(ELEMENT NOT PRESENT IN THE COLLECTION)
End BINARYSEARCH
In Binary Search algorithm given above, K is the list of data items containing N
data items. X is the data item, which is to be searched in K. If the data item to be
searched is found then the position where it is found will be printed. If the data item to be
searched is not found then Element Not Found message will be printed, which will
indicate the user, that the data item is not found.
Initially lower is assumed 0 to point the first element in the list and upper is
assumed as N-1 to point the last element in the list because the range of any array is 0 to
N-1. The mid position of the list is calculated by finding the average between lower and
upper and X is compared with K[mid]. If X is found equal to K[mid] then the value mid
will gets printed, the control comes out of the loop and the procedure comes to an end. If
4

X is found lesser than K[mid], then upper is assigned mid 1, to search only in the first
half of the list. If X is found greater than K[mid], then lower is assigned mid + 1, to
search only in the second half of the list. This process is continued until the element
searched is found or the collection becomes becomes empty.
Example:
X
U
L
M

Number to be searched : 40
Upper
Lower=N-1
Mid

i=0

i =1

i=2

i=3

i=4

i=5

i=6

i=7

i=8

i=9

22

35

40

43

56

75

83

90

98

L=0
X< K[4]
1

22

U=41=3
35

M = (0+9)/2 =4

40

U=9

43

56

75

83

90

98

43

56

75

83

90

98

43

56

75

83

90

98

L = 0 M = (0+3)/2=1 U = 3
X > K[1] L = 1 + 1 = 2
1

22

K > A [2]
1

22

K = A[3]

35

40

L, M = 2 U = 3
L=2+1=3
35

40

L, M, U = 3
P = 3 : Number found at position 3

Program:
#include<stdio.h>
#include<conio.h>
int K[10],N=10;
binarysearch(int x)
{
int mid, lower=0, upper=N-1;
while (lower<=upper)
{
mid=(lower+upper)/2;
if (K[mid]>X)
upper=mid-1;
else if(K[mid]<X)
lower=mid+1;
else
Write(Element Found at location, MID);

Quit
}
Write(Element not found in the collection)

main(){
int i,x;
printf(\nEnter the elements);
for(i=0;i<N;i++)
scanf(%d,&K[i]);
printf(\nEnter the element to search);
scanf(%d,&x);
binarysearch(x);
}
The binarysearch( ) function gets the element to be searched in the variable X.
Initially lower is assigned 0 and upper is assumed N 1. The mid position is calculated
and if K[mid] is found equal to X, then mid position will gets displayed. If X is less than
K[mid] upper is assigned mid 1 to search only in first half of the list else lower is
assigned mid + 1 to search only in the second half of the list. This is process is continued
until lower is less than or equal to upper. If the element is not found even after the loop
is completed, then the Not Found Message will be displayed to the user indicating that
the element is not found.
Advantages:
1. Searches several times faster than the linear search.
2. In each iteration, it reduces the number of elements to be searched from n to n/2.
Disadvantages:
1. Binary search can be applied only on a sorted list.

HASH SEARCH
Hash search is one of the fastest searching mechanisms used to locate the given
element in the collection. This searching method uses the concept called Hashing to get
the address of the location in the table to store/retrieve the element.
Hashing is the process of applying the hashing function to the given value to get
the address of the location for its storage or retrieval. There are so many hashing
techniques which can be used or a user defined function may also be used. These
functions may do some arithmetic manipulation on the given value and return the result.
The result will be treated as an address for the given element. Some of the hashing
functions are
1. Division method
2. Mid Square Method
3. Folding method
The table where the values get stored is called Hash Table. The Hash table is the
collection of several buckets say HT(0),HT(1). Each bucket has the capacity to hold
any number of values which will be decided by the designer of the table. The buckets
may have the respective number of slots and each slot being large enough to hold one
element. If the bucket size=1 then each bucket can hold only one element.
6

Insert X into Hash table:


The given value X which has to be inserted into the hash table will be given as an
input to the hashing function. The function will return the address for its storage. While
storing the record/element, if the address calculated is the one which already contain
some data, the collision said to be occurred. In order to overcome this problem any of the
collision resolution techniques will be used. One of the most widely used techniques is
linear probing. The sequential search is made in the linear probing to find out the next
empty location & the value gets stored there. If all the locations are occupied by some
elements then overflow is said to be occurred.
Algorithm:
ALGORITHM INSERTHT(HT, N, X)
// HT is the Hash table
// N is the number of buckets
// X is the data item to be insert
Begin
I 1
Y X MOD N
While(I<=N)
Begin
IF (HT(Y)= ) THEN
HT(Y) X
Quit
Else
Y (Y+1)MOD N
I I+1
End
Write(Table is Full)
End
In the above algorithm HT is the Hash table which has been initialized with a
special value say . The algorithm receives three values as arguments. The given value X
will be given to hashing function to get the address for its storage. The search is made in
the location Y of the hash table HT. If the specified location is empty then it will be
stored. The search for the next empty location will be made if the location is having some
element with it.
Search X in the Hash table:
The value X will be given to the hashing function to get the address for the
search. If the corresponding location of the hash table contains the value X means the
successful search message will be displayed. The search will be made on the remaining
buckets if the first search gets failed. The Unsuccessful search message will be given to
the user if the element cannot be found in the remaining N-1 buckets.

Algorithm:
ALGORITHM SEARCHHT(HT, N, X)
7

// HT is the Hash table


// N is the number of buckets
// X is the data item to be search
Begin
I 1
Y X MOD N
While(I<=N)
Begin
IF (HT(Y)=X) THEN
Write(X IS PRESENT )
Quit
Else
Y (Y+1)MOD N
I I+1
End
Write(X IS ABSENT)
End

INDEXED SEQUENTIAL SEARCH


Indexed Sequential Files:
The sequential file structures are inefficient during the searching process. But all
the data base activities involve searching of a particular record and then doing some
process over it. But in case of sequential files, the delay in retrieving the records is so
high particularly for those which are stored at the end of the files. Hence to overcome
this difficulty, a technique called indexing is adopted where the records are stored as
blocks in the memory and the highest key value of each block is stored in an index file.
Whenever a record is to be searched, its key value is compared with the index file and the
control is taken directly to the particular memory block where the record is present. This
eliminates the need of searching through all the records which are stored in other memory
blocks before that. Now the sequential search is done only within the block where the
record is present whereas the block is directly accessed using the index value. This
greatly reduces the number of comparisons before searching a particular record.

An index file consists of three areas. They are


Prime area
Index area
Overflow area

The prime area is where the records of the file are stored when the sequential file is
initially created. Consider that the external storage device is a hard disk which consists
of many cylinders. Each cylinder in a hard disk consist so many tracks and sectors. The
prime area is starts from track 1 leaving the track 0 empty. All the records in the file are
stored in the prime area starting from track 1.
At the end of the prime area in every cylinder, some extra space is left for
accommodating extra records which may come in the future. This area is called the
overflow area. This is used when in each cylinder there is an overflow of records after
the prime area is completely filled. In some cases, there is a master overflow area which
is used to hold the overflow of records when all the overflow areas are also filled up.
8

The third important area in an indexed sequential file is called index area which
occupies track 0 in every cylinder. The highest key value in every track of the prime area
is stored in the index area along with the track number. Thus the index area maintains the
index of records in stored in all the tracks of a cylinder. Hence this type of index is also
called track index. There is another index maintained for the track indexes of all
cylinders. This index stores the highest key value of each track index along with the
cylinder number and this type of index is called the cylinder index. Some type of file
systems even maintains an index called master index, where the highest key value of each
row in the cylinder index is stored along with the row number. This makes the searching
even more efficient.
INDEXED SEQUENTIAL ACCESS METHOD
The file structure described above is uses a method called indexed sequential
access method to search for a given record. Given a key, the program first compares the
key value with the values in the entries of the master index. If the key value is greater
than the entry in the master index, then the comparison is made with the next cell entry.
If the key value is found to be lesser than the value present in the cell of the master index,
then the row number corresponding to that is retrieved and the control taken to that
particular row directly in the cylinder index.
Now the key value is again compared with each and every value in the cylinder
index and stops when a greater value is found. After a greater value than the key value is
found in the cylinder index, the cylinder number corresponding to that is retrieved and
the control is directly taken to that particular cylinder. Now the key value is compared
with each and every value in the track index and when a greater value is found, the
corresponding track number is retrieved and control is taken to that track directly. This is
the lowest level in the hierarchy and now a sequential search is made for the key value
within this track alone. If the record matching to this key value is found then, the record
is retrieved and loaded to the memory other wise record not found error is displayed.

In the above example, a key value is 923 is given and is searched using ISAM
technique. First the key value is compared with the values in the master index. Since the
first value in the master index (4000) is greater than 923, the control is transferred to the
row one in the cylinder index. Now, 923 is compared with each value in the row 1 of
cylinder index. The first value in the row 1 of cylinder index (1000) is greater than 923.
Hence the control is transferred to track 10 where 923 is sequentially searched and
retrieved. In this case the number of comparisons required to search for the key value
923 is 23 in track 10 + 10 in track index + 1 in row 1 of cylinder index + 1 in master
index = 35 comparisons. But if the same data is stored as ordinary sequential file, then
the number of comparisons that would have taken to find out the record 923 is 923
comparisons. This shows that the ISAM has drastically reduced the searching time when
compared to the ordinary sequential file.

10

SORTING

Practically, all data processing activities require data to be in some order.


Ordering or sorting data in an increasing or decreasing fashion according to some linear
relationship among data items is of fundamental importance.
Sorting : Sorting is an operation of arranging data, in some given order, such as
ascending or descending with numerical data, or alphabetically with character data.
Let A be a list of n elements A1, A2,An in memory. Sorting A refers to the operation of
rearranging the contents of A so that they are increasing in order (numerically or
lexicographically), that is, A1 A2 A3 .An
Sorting methods can be characterized into two broad categories:
Internal Sorting
External Sorting
Internal Sorting : Internal sorting methods are the methods that can be used when the
list to be sorted is small enough so that the entire sort can be carried out in main
memory.
The key principle of internal sorting is that all the data items to be sorted are
retained in the main memory and random access in this memory space can be effectively
used to sort the data items.
The various internal sorting methods are:
1.
2.
3.
4.
5.
6.

Selection Sort
Insertion Sort
Quick Sort
Merge Sort
Heap Sort
Shell Sort

External Sorting : External sorting methods are the methods to be used when the list to
be sorted is large and cannot be accommodated entirely in the main memory. In this
case some of the data is present in the main memory and some is kept in auxiliary
memory such as hard disk, floppy disk, tape, etc.
Objectives involved in design of sorting algorithms.
The main objectives involved in the design of sorting algorithm are:
1. Minimum number of exchanges
2. Large volume of data block movement
This implies that the designed and desired sorting algorithm must employ minimum
number of exchanges and the data should be moved in large blocks, which in turn
increase the efficiency of the sorting algorithm.

INTERNAL SORTING
Internal Sorting: These are the methods which are applied on the list of data items,
which are small enough to be accommodated in the main memory.
11

There are different types of internal sorting methods. The methods discussed here
sort the data in ascending order. With a minor change we can sort the data in descending
order.

SELECTION SORT
One of the easiest ways to sort a list is by selection. Beginning with the first
element in the list, a search is performed to locate the smallest element. When this
element is found, it is interchanged with the first element in the list. This interchange
places the smallest element first. A search for the second smallest key is then carried out.
This is accomplished by examining the list from second element onwards. The second
smallest element is interchanged with the element present in the second position of the
list. This process of searching for the smallest element and placing it in proper position
continues till the first N-1 elements are gets positioned so automatically the Nth element
will be placed in the respective place.
Principle: The Selection sort algorithm searches for the smallest element in the list and
places it in the first position. Then it searches for the second smallest element and places
that in the second position. This is repeated until all the elements are sorted.
Algorithm:
ALGORITHM SELECTIONSORT(K, N)
// K is the array containing the list of data items
// N is the number of data items in the list
Repeat For I = 0 to N 2
Min I
Repeat For J = I + 1 to N-1
If K[I] < K[Min]
Then
Min J
End If
End Repeat
If Min I
Then
K[I] K[Min]
End If
End Repeat
End SELECTIONSORT
In Selection sort algorithm, in every pass the min is made to point to where I is
pointing. Therefore initially in every pass K[I]=K[min]. Now K[min] is compared with
rest of the elements and if any of the element from the rest of the list is found lesser than
K[min], then min is made to point to that element. This process is continued till the last
element after which the min points to the smallest element. If min is not equal to I then
K[min] and K[I] gets swapped. Now the smallest element comes to the first position.
Now I is incremented and the same process is repeated to get the smallest number which
12

is placed in the second position. This is repeated until I is moved to the last element.
Finally, a sorted list of elements is obtained.
Example:
N = 10 Number of elements in the list
L N-1
M Min
i=0

i =1

i=2

i=3

i=4

i=5

i=6

i=7

i=8

i=9

65

58

94

36

99

87

M=3
42

23

74
IM

I=0

11

swap K[I] and K[M]

L=9

M=1
11

23

74

I=1

I=M

42

65

58

94

36

99

No change

87
L=9

M=7
11

23

74

42

I=2

IM

65

58

94

36

99

swap K[I] and K[M]

87
L=9

M=3
11

23

36

42

65

I=3

I=M

58

94

74

99

No change

87
L=9

M=5
11

23

36

42

65

58

I=4 I M

94

74

99

swap K[I] and A[M]

87
L=9

M=5
11

23

36

42

58

65

94

I=5

I=M

74

99

No change

87
L=9

M=7
11
IM

23

36

42

58

65

swap K[I] and K[M]

94

74

99

I=6

87
L=9
M=9

11
IM

23

36

42

swap K[I] and K[M]

58

65

74

94
I=7

99

87
L=9
M=9
13

11
IM

23

36

42

58

65

74

87

swap K[I] and K[M]

99

94

I=8

L=9

94

99

Sorted List:
11

23

36

42

58

65

74

87

Program:
#include<stdio.h>
#include<conio.h>
int K[10],N=10;
selectionsort()
{
int temp, min,i,j;
for (i=0; i<=N-2;i++)
{
min=i;
for (j=i+1; i<=N-1;i++)
{
if (K[j]<K[min])
min=j;
}
if (min!=i)
{
temp=K[min];
K[min]=K[i];
K[i]=temp;
}
}
}
main(){
int I;
printf(\nEnter the values);
for(i=0;i<N;i++)
scanf(%d,&K[i]);
selectionsort();
printf(\nThe sorted values are\n);
for(i=0;i<N;i++)
printf(%d ,K[i]);
}
In the above program, min is a variable used to point to the minimum number in
the list. In each pass, the min is assigned I. Now K[min] is compared with all the other
elements in the list and if any other number is found to be minimum then min is made to
point to that element. After every pass it is checked if min is equal to I. If not, then K[I]
is swapped with K[min] and the next pass is continued. Finally a sorted list of elements
is obtained.
14

Advantages:
1. It is simple and straight forward. The algorithm just selects the smallest element
every time and places it in the correct position.
2. Reduces the number of exchanges and hence efficient.
3. Faster than Bubble sort algorithm.
Disadvantages:
1. Requires an extra variable to keep track of the minimum number in every pass.

INSERTION SORT
The main idea behind the insertion sort is to insert the ith element in its correct
place in the ith pass. Suppose an array K with n elements K[1], K[2],K[N] is in
memory. The insertion sort algorithm scans K from K[0] to K[N-1], inserting each
element K[I] into its proper position in the previously sorted subarray K[0], K[1],..K[I-1].
Principle: In Insertion Sort algorithm, each element K[I] in the list is compared with all
the elements before it ( K[1] to K[I-1]). If any element K[J] is found to be greater than
K[I] then K[J] is inserted in the place of K[J}. This process is repeated till all the
elements are sorted.
Algorithm:
ALGORITHM INSERTIONSORT(K, N)
// K is the array containing the list of data items
// N is the number of data items in the list
Repeat For I = 1 to N-1
Repeat For J = 0 to I 1
If (K[I] < K[J])Then
Temp K[I]
Repeat For L = I-1 to J
K[L +1] K[L]
End Repeat
K[J] Temp
End If
End Repeat
End Repeat
End INSERTIONSORT
In Insertion Sort algorithm, N represents the total number of elements in the array
K. I is made to point to the second element in the list. In every pass the J is incremented
to point to the next element and is continued till it reaches the last element. During each
pass K[I] is compared all elements before it. If K[I] is lesser than K[J] in the list, then
K[I] is inserted in position J. Finally, a sorted list is obtained.
For performing the insertion operation, a variable temp is used to safely store K[I]
in it and then shift right elements starting from K[J] to K[I-1].
15

Example:
N = 10 Number of elements in the list
L Last
i=0

i =1

i=2

i=3

i=4

i=5

i=6

i=7

i=8

i=9

42

23

74

11

65

58

94

36

99

87

I=1
23

42

74

K[I] < K[0]

Insert K[I] at 0

11

58

65

94

36

L=9
99

I=2
K[I] is greater than all elements before it. Hence No Change

23

42

74

11

65

58

I=3 K[I] < K[0]


11

23

K[I] < K[3]


11

23

K[I] < K[3]

11

23

42

74

65

58

94

36

99

65

74

Insert K[I] at 3

42

58

65

94

36

99

23

K[I] < K[2]


11

23

42

58

65

58

94

36

99

I=5

42

58

74

94

36

99

74

94

36

99

I=7

65

23

K[I] < K[7]

36

42

58

Insert K[I] at 7

65

87

74

94

74

94

87
L=9

87
L=9

99

I=8
K[I] is greater than all elements before it. Hence No Change

11

87

L=9

Insert K[I] at 2
36

87

L=9

I=6
K[I] is greater than all elements before it. Hence No Change

11

L=9

Insert K[I] at 0 L=9

I=4
Insert K[I] at 3
42

87

99

87
L=9

87
I, L=9
16

Sorted List:
11

23

36

42

58

65

74

87

94

99

Program:
#include<stdio.h>
#include<conio.h>
int K[10],N=10,temp;
insertionsort(){
int i,j,l
for (i = 1;i<= N-1;i++){
for(j = 0;j<=i 1 ;j++){
if (K[i] < K[j]){
Temp = K[i];
For(l = i-1;l>=j;l--)
K[l +1] = K[l];
K[j] = Temp;
}
}
}
}
main(){
int i;
printf(\nEnter the values);
for(i=0;i<N;i++)
scanf(%d,&K[i]);
selectionsort();
printf(\nThe sorted list is);
for(i=0;i<N;i++)
printf(%d ,K[i]);
}
In the selectionsort function, the first pass starts with the variable i pointing to the
second element and continues till i reaches the last element. In each pass, K[i] is
compared with all the elements before it and if K[i] is lesser than K[j], then it is inserted
in position j. Before inserting it, the elements K[j] to K[i-1] are shifted right using a
temporary variable by one position in order to get an empty slot.
Advantages:
1. Sorts the list faster when the list has less number of elements.
2. Efficient in cases where a new element has to be inserted into a sorted list.
Disadvantages:
1. Very slow for large values of n.
2. Poor performance if the list is in almost reverse order.
17

QUICK SORT

Quick sort is a very popular sorting method. The name comes from the fact that,
in general, quick sort can sort a list of data elements significantly faster than any of the
common sorting algorithms. This algorithm is based on the fact that it is faster and easier
to sort two small lists than one larger one. The basic strategy of quick sort is to divide
and conquer. Quick sort is also known as partition exchange sort.
The purpose of the quick sort is to move a data item in the correct direction just
enough for it to reach its final place in the array. The method, therefore, reduces
unnecessary swaps, and moves an item a great distance in one move.
Principle: A pivotal item near the middle of the list is chosen, and then items on either
side are moved so that the data items on one side of the pivot element are smaller than
the pivot element, whereas those on the other side are larger. The middle or the pivot
element is now in its correct position. This procedure is then applied recursively to the 2
parts of the list, on either side of the pivot element, until the whole list is sorted.
Algorithm:
ALGORITHM QUICKSORT(K, Lower, Upper)
// K is the array containing the list of data items
// Lower is the lower bound of the array
// Upper is the upper bound of the array
If (Lower < Upper) Then
BEGIN
I Lower + 1
J Upper
Flag 1
Key K[Lower]
While (Flag)
BEGIN
While (K[I] <= Key)
I I+1
End While
While (K[J] > Key)
J J1
End While
If (I < J)Then
K[I] K[J]
I I+1
J J-1
Else
Flag 0
End If
End While
K[J] K[Lower]
QUICKSORT(K, Lower, J 1)
QUICKSORT(K, J + 1, Upper)
End If
End QUICKSORT
18

In Quick sort algorithm, Lower points to the first element in the list and the Upper
points to the last element in the list. Now I is made to point to the next location of Lower
and J is made to point to the Upper. K[Lower] is considered as the pivot element and at
the end of the pass, the correct position of the pivot element will be decided. Keep on
incrementing I and stop when K[I] > Key. When I stops, start decrementing J and stop
when K[J] < Key. Now check if I < J. If so, swap K[I] and K[J] and continue moving I
and J in the same way. When I meets J the control comes out of the loop and K[J] and
K[Lower] are swapped. Now the element at position J is at correct position and hence
split the list into two partitions: (K{Lower] to K[J-1] and K[J+1] to K[Upper] ). Apply
the Quick sort algorithm recursively on these individual lists. Finally, a sorted list is
obtained.
Example:
N = 10 Number of elements in the list
U Upper
L Lower
i=0

i =1

i=2

i=3

i=4

i=5

i=6

i=7

i=8

i=9

42

23

74

11

65

58

94

36

99

87

L=0 I=0
Initially I=L+1 and J=U, Key=K[L]=42 is the pivot element.
42

23

74

11

65

58

94

36

99

L=0
I=2
J=7
K[2] > Key hence I stops at 2. K[7] < Key hence J stops at 7
Since I < J Swap K[2] and A[7]
42

23

36

11

65

58

94

74

99

U, J=9

87
U=9

87

L=0
J=3
I=4
U=9
K[4] > Key hence I stops at 4. K[3] < Key hence J stops at 3
Since I > J Swap K[3] and K[0]. Thus 42 go to correct position.
The list is partitioned into two lists as shown. The same process is applied to these lists
individually as shown.
List 1
11

23

List 2
36

42

65

58

94

74

99

87

65

58

94

74

99

87

L=0,
I=1 J,U=2
(applying quicksort to list 1)
11

23

36

42

L=0, I=1 U=2 J=0 Since I>0 K[L] &K[J] gets swapped i.e., K[0] gets swapped with
same element because L,J=0

19

11

23

36

42

65

58

94

74

99

L=4 J=5
I=6
(applying quicksort to list 2)
(after swapping 58 & 65)
11

23

36

42

58

65

94

11

23

36

42

58

65

94

23

36

42

58

65

L=6

Sorted List:
11

23

87

36

42

58

65

74

99

87

I=8

U, J=9

87

99

J=8

U, I=9

94

99

94

99

74

L=6
11

U=9

74

L=6

87

74
U, I, J=7
87

Program:
#include<stdio.h>
#include<conio.h>
int K[10],lower,upper;
quicksort(int lower,int upper){
int flag=1,i,j,key,temp;
if(lower<upper){
i=lower+1;
j=upper;
key=K[lower];
while(flag){
while(K[i]<=key)
i++;
while(K[j]>key)
j--;
if(i<j){
temp=K[i];
K[i]=K[j];
K[j]=temp;
i++;
j--;
}
else
flag=0;
}
temp=K[lower];
K[lower]=k[j];
K[j]=temp;
quicksort(lower,j-1);
quicksort(j+1,upper);
}}
20

void main(){
int i;
clrscr();
printf(\nEnter the elements);
for(i=0;i<10;i++)
scanf("%d",&k[i]);
quicksort(0,9);
printf(\nSorted Values are);
for(i=0;i<10;i++)
printf("\n%d",k[i]);
getch();
}
In the above program the function quicksort( ) is invoked by passing the lower
bound and the upper bound values of the array. This is a recursive function and hence it
is checked initially if lower is greater than equal to upper because the splitting of table is
possible only if has atleast two elements with it. If so, the function is terminated. This is
checked in the beginning itself to avoid endless loop. Initially i assigned lower+1 and j is
assigned upper. i is incremented until a bigger number than the pivot element (K[lower])
is found. j is decremented until a smaller number than the pivot element is found. If both
i and j stops, then it is checked whether i < j. If i < j then K[i] and K[j] are swapped and
the process is continued. When i and j cross each other, the exits and K[lower] is
swapped with K[j]. The position of element at j is fixed and hence the list is partitioned
into two subtables ( K[Lower] to K[j-1] and K[j+1] to K[upper]). The quick sort
algorithm is applied recursively on these two lists. Finally, a sorted list is obtained.
Advantages:
1. Faster than any other commonly used sorting algorithms.
2. It has a best average case behavior.
Disadvantages:
1. As it uses recursion, stack space consumption is high.

MERGE SORT
Principle: The given list is divided into two roughly equal parts called the left and the
right subfiles. These subfiles are sorted using the algorithm recursively and then the two
subfiles are merged together to obtain the sorted file.
Given a sequence of N elements K[0],K[1] .K[N-1], the general idea is to
imagine them split into various subtables of size is equal to 1. So each set will have a
individually sorted items with it, then the resulting sorted sequences are merged to
produce a single sorted sequence of N elements. Thus this sorting method follows Divide
and Conquer strategy. The problem gets divided into various subproblems and by
providing the solutions to the subproblems the solution for the original problem will be
provided.

21

Algorithm:
ALGORITHM MERGE(K, low, mid, high)
// K is the array containing the list of data items
// Low is the lower bound of the collection
//high is the upper bound of the collection
//mid is the upper bound for the first collection
I low, J mid+1, L 0
While (I mid) and (J high)
If (K[I] < K[J]) Then
Temp[L] K[I]
I I+1
L L+1
Else
Temp[L] K[J]
J J+1
L L+1
End If
End While
If (I > mid) Then
While (J high)
Temp[L] K[J]
J J+1
L L+1
End While
Else
While (I mid)
Temp[L] K[I]
L L+1
I I+1
End While
End If
Repeat for m = 0 to L step 1
K[Low+m] Temp[m]
End Repeat
End MERGE

ALGORITHM MERGESORT(A, low, high)


// K is the array containing the list of data items
If (low < high) Then
mid (low + high)/2
MERGESORT(low, mid)
MERGESORT(mid + 1, high)
MERGE(low, mid, high)
End If
End MERGESORT
22

The first algorithm MERGE can be applied on two sorted lists to merge them.
Initially, the index variable I points to low and J points to mid + 1. K[I] is compared with
K[J] and if K[I] found to be lesser than K[J] then K[I] is stored in a temporary array and I
is incremented otherwise K[J] is stored in the temporary array and J is incremented. This
comparison is continued till either I crosses mid or J crosses high. If I crosses the mid
first then that implies that all the elements in first list is accommodated in the temporary
array and hence the remaining elements in the second list can be put into the temporary
array as it is. If J crosses the high first then the remaining elements of first list is put as it
is in the temporary array. After this process we get a single sorted list. Since this method
merges 2 lists at a time, this is called 2-way merge sort.
In the MERGESORT algorithm, the given unsorted list is first split into N number
of lists, each list consisting of only 1 element. Then the MERGE algorithm is applied for
first 2 lists to get a single sorted list. Then the same thing is done on the next two lists
and so on. This process is continued till a single sorted list is obtained.
Example:
Let L

low, M

mid, H

high

i=0

i =1

i=2

i=3

i=4

i=5

i=6

i=7

i=8

i=9

42

23

74

11

65

58

94

36

99

87

In each pass the mid value is calculated and based on that the list is split into two. This is
done recursively and at last N number of lists each having only one element is produced
as shown.

Now merging operation is called on first two lists to produce a single sorted list, then the
same thing is done on the next two lists and so on. Finally a single sorted list is obtained.

23

Program:
#include<stdio.h>
#include<conio.h>
int K[10],N=10;
merge(int low, int mid, int high)
{
int i=low, j=mid+1, l=0, temp[N];
while (i<=mid && j<=high){
if (K[i]<K[j]){
temp[l]=K[i];
l++;
i++;
}
else{
temp[l]=K[j];
l++;
j++;
}
if (i>mid)
while (j<=high){
temp[l]=K[j];
l++;
j++;
}
else
while (i<=mid){
temp[l]=K[i];
l++;
j++:
}
for (m=0; m<=l; m++)
K[low+m]=temp[m];
}
mergesort(int low, int high)
{
int mid;
if (low<high)
{
mid=(low+high)/2;
mergesort(low,mid);
mergesort(mid+1, high);
merge(low, mid, high);
}
}

24

main(){
int i;
printf(\nEnter the values);
for(i=0;i<N;i++)
scanf(%d,&K[i]);
mergesort(0,N-1);
printf(\nThe Sorted Values);
for(i=0;i<N;i++)
printf(%d,K[i]);
}
Advantages:
4. Very useful for sorting bigger lists.
5. Applicable for external sorting also.
Disadvantages:
1. Needs a temporary array every time, for storing the new sorted list.

HEAP SORT
Heap: A Heap is a compete binary tree with the property that the value at each node is
at least as large as the values of its children (if they exist). If the value at the parent node
is larger than the values on its children then it is called a Max heap and if the value at
the parent node is smaller than the values on its children then it is called the Min heap.
Heap Sort is the sorting technique based on the interpretation of the given
sequence of elements as a binary tree. For interpretation the principle given below has to
be used.
If a given node is in position I then the position of the left child and the right child
can be calculated using Left (L) = 2I and Right (R) = 2I + 1.
To check whether the right child exists or not, use the condition R N. If true,
Right child exists otherwise not.
The last node of the tree is N/2. After this position tree has only leaves.
Principle: The Max heap has the greatest element in the root. Hence the element in the
root node is pushed to the last position in the array and the remaining elements are
converted into a max heap. The root node of this new max heap will be the second
largest element and hence pushed to the last but one position in the array. This process is
repeated till all the elements get sorted.
Algorithm:
ALGORITHM HEAP(K, N)
// K is the list of unsorted elements
// N is the number of elements in the array
For Q=2,3,.N
BEGIN
I Q

25

END

J I/2
Key K[Q]
While(I>1 and Key > K[J])
Begin
K[I] K[J]
I J
J I/2
End
K[I] Key

ALGORITHM HEAPSORT(K, N)
// K is the list of unsorted elements
// N is the number of elements in the array
For I=N TO 2
Begin
HEAP(A,I)
K[1] K[I]
End Repeat
End HEAPSORT
The HEAP procedure is used to convert a tree into a heap. If this algorithm is
applied to the interpreted tree, then the tree will gets converted to a max heap. In the
above given HEAP algorithm, the element at the given node is compared with it parent
and is swapped if the parent is less the element that we have considered the process gets
repeated for the all the upper levels till the root node gets considered else we got some
node whose parent is having greater value. The process has to be repeated for all the
elements under consideration. After completion of a pass the largest element will be
placed in the root of the heap. The largest element will gets pushed to the last position by
exchanging the values. Since the heap property gets affected try to include it among N-1
elements so once again the largest among N-1 elements will be pushed to the root. The
process has to be repeated till the total number of elements under consideration becomes
one.
Example:
Given a list A with 8 elements:
42

23

74

11

65

58

94

36

The given list is first converted into a binary tree as shown.

26

Binary tree
Phase 1:
The rearranged tree elements after the first phase is

Phase 2:

27

Program:
#include<stdio.h>
#include<conio.h>
int K[10],N=10;
heap(int N){
int q,i,j,key;
for(q=2;q<N;q++){
i=q;
j=i/2;
key=K[q];
while(i>1 && key>K[j]){
K[i]=K[j];
i=j;
j=i/2;

28

}
K[i]=key;

heapsort(int N){
for(i=N;i>=2;i--){
heap(i);
temp=K[i];
K[i]=K[1];
K[1]=temp;
}
}
main(){
int i;
printf(\nEnter the values);
for(i=1;i<=N;i++)
scanf(%d,&K[i]);
heapsort(N);
printf(\nThe sorted values are);
for(i=1;i<=N;i++)
printf(%d,K[i]);
}
In the above program heap is a function which receives the N value as an
argument. N represents the total number of elements among which the heap has to be
constructed. So once the heap gets constructed the largest element among N element will
be pushed to the root position. The function heapsort is used to exchange the first element
i.e, root and the last element. The same function invokes the heap function repeatedly till
it gets 2 elements under its consideration.

SHELL SORT
Principle: This method sorts separate subfiles of the original file using insertion sort.
Each subfiles contain every Jth element of the original file. The value of J is called an
increment.
A more significant improvement on the simple insertion sort, as compared to
binary or list insertion can be achieved using the Shell sort. It is also called as
Diminishing increment sort. This method divides the given set of elements into various
subsets and each subset contains the element which was selected from the table at the
regular interval. The interval is called the increment value. For example, if J is 5, the
subtable consisting of K[0],K[5],K[10],.. is first sorted by applying the insertion sort.
Subtable 1 contains K[0],K[5],K10],.
Subtable 2 contains K[1],K[6],K11],.
Subtable 3 contains K[2],K[7],K12],.
Subtable 4 contains K[3],K[8],K13],.
Subtable 5 contains K[4],K[9],K14],.
29

After the first J subtables are sorted, a new smaller value of J is chosen, and the
table is again partitioned into a new set of subtables, Each of these larger subtables is
sorted, and the process is repeated yet again with an even smaller value of J. Eventually,
the value of J is set to 1, so that the subtable consisting of the entire table to be sorted. A
decreasing sequence of increments is fixed at the start of the entire process. The last value
in the sequence must be 1
Algorithm:
ALGORITHM SHELLSORT(K, N,INC)
// K represents the array name where the list of elements are available
//N represents the total number of elements
//INC represents the initial increment value
WHILE(INC>=1)
Begin
For I=INC to N-1
Begin
Key K[I]
L I
While(L>=INC and Key<K[L-INC])
Begin
K[L] K[L-INC]
L L-INC
End
K[L] Key
End
INC INC/2
END
The procedure SHELLSORT given above receives the list of elements to be
sorted in K and the total number of elements in the list N. The variable INC is used to
denote the initial increment value which will help to create the various subtables.
For each value of increment the value that is going to be inserted will gets
compared with the previous elements of the same subtable. Whenever the element is
found which is greater than the value which is going to inserted then an empty slot will
gets inserted. The element has to be inserted in the empty slot by shifting all the
subsequent elements towards right by one position. After completion of each pass the
increment value gets decreased by a considerable amount. The same process gets
repeated for various values of increment till it reaches one.
Example:
i = 0 i =1
42

23

i=2

i=3

i=4

i=5

i=6

i=7

i=8

i=9

74

11

65

58

94

36

99

87

INC=5
30

i = 0 i =1
42

23

i=2

i=3

i=4

i=5

i=6

i=7

i=8

i=9

74

11

65

58

94

36

99

87

Sub Table 1

After applying insertion sort to the above 5 sub tables


i=0

i =1

i=2

i=3

i=4

i=5

i=6

i=7

i=8

i=9

42

23

36

11

65

58

94

74

99

87

INC=3 (After decrementing the interval value)


i = 0 i =1
42

23

i=2

i=3

i=4

i=5

i=6

i=7

i=8

i=9

36

11

65

58

94

74

99

87

Sub Table 1

After applying insertion sort to the above 5 sub tables


i=0

i =1

i=2

i=3

i=4

i=5

i=6

i=7

i=8

i=9

11

23

36

42

65

58

94

74

99

87

INC=1 (After decrementing the interval value)


i=0

i =1

i=2

i=3

i=4

i=5

i=6

i=7

i=8

i=9

11

23

36

42

65

58

94

74

99

87

The entire table will be treated as a subtable and insertion sort gets applied. Therefore the
entire table gets sorted in the ascending order.
31

i=0

i =1

i=2

i=3

i=4

i=5

i=6

i=7

i=8

i=9

11

23

36

42

58

65

74

87

94

99

Program:
#include<stdio.h>
#include<conio.h>
int K[10],N=10;
shellsort(int N,int inc){
int key,i,l;
while(Inc>=1){
for(i=inc;i<=N-1;i++){
key=K[i];
l=i;
While(l>=inc && key<K[l-inc]){
K[l]=K[l-inc];
l=l-inc;
}
K[l]= key;
}
Inc=Inc/2;
}
}
main(){
int i;
printf(\nEnter the values);
for(i=0;i<N;i++)
scanf(%d,&K[i]);
shellsort(N,5);
printf(\nThe sorted values are);
for(i=0;i<N;i++)
printf(%d,K[i]);
}

32

UNIT V
GREEDY METHOD
In Greedy algorithm,
(i)
(ii)
(iii)
(iv)
(v)

We attempt to construct an optimal solution in stages.


At each stage we make decision that appears to be the best at that
time.
A decision made in one stage is not changed in a later stage.
The criterion used to make the greedy decision at each stage is
called the Greedy criterion.
At each stage, a decision is made regarding whether a particular
input is an optimal solution. This is done by considering the inputs
in an order determined by some selection procedure. If the
inclusion of the next input into the partially constructed optimal
solution results in an infeasible solution, then this input is not
added to the partial solution, otherwise it is added.

KNAPSACK PROBLEM
In the knapsack problem, you are given with a sack of capacity m. There is n
number of objects provided. The weights of each object is given in the form of an array
w[ ]. The profit of each object is provided using the array p[ ]. Now you have to fill the
sack with these objects, in such a way that the total weight of the objects put into the sack
should be lesser than or equal to the capacity of the sack. We should select the objects in
such a way that we get maximum profit.
Given:

n
Number of objects
m Total capacity of the sack
w[ ] weights of the objects
p[ ] profits of the objects

Aim of the problem:

Fill the sack up to maximum capacity such that the total profit of selected
objects is maximized.
i=n
i =1

Constraint:

xi p i

is maximized

Total weight of the selected objects should not exceed the maximum
capacity of the sack.

i=n
i =1

xi wi m

where x = { 0.. 1} or x = {0, 1}

0/1 Knapsack problem.

Solution:
Consider for example the following inputs for the Knapsack problem.
n =3
m = 20
w = {5, 10, 15}
p = {50, 30, 30}
Please note that the inputs for the w[ ] and p[ ] are given in such a way that p/w is in
descending order. That is the object with maximum profit per unit weight will appear
first. Since this problem used a greedy approach, the objects are taken in the order of
their profit per unit weight, so that maximum profit can be obtained.
Now select the objects one by one.
Iteration 1
Initially the total weight TW and the total profit TP are zero. Now select the first
object. Compare its weight with the capacity of the sack.
5 < 20
Since the weight of the object does not exceed the capacity of the sack, this can be put
inside the sack. To indicate this set the first position of X[ ] as 1.
X = { 1, 0, 0 }
Now the remaining capacity of the sack becomes m = 15.
Iteration 2
Take the second object. Compare its weight with the available capacity of the
sack.
10 < 15
Since the weight of the object does not exceed the capacity of the sack, this can be put
inside the sack. To indicate this set the second position of X[ ] as 1.
X = { 1, 1, 0 }
Now the remaining capacity of the sack becomes m = 5.

Iteration 3
Take the third object. Compare its weight with the available capacity of the sack.
15 > 5
Since the weight of the object is exceeding the available capacity of the sack, we cannot
put the whole object inside the sack. But a fraction of that which fits into the sack
exactly can be taken. That is 5 / 15
1/3 of the third object can be put in the sack.
Hence the final solution is,
X = { 1, 1, 0.33 }
Total profit TP = 90, Total weight = 20
Some Knapsack problems does not allow objects to be taken as fraction. The values of X
allowed are only 0 and 1. These type of knapsack problems are called the 0/1 Knapsack
problem. For these the solution for the above problem may appear like this.
X = { 1, 1, 0 }
Total profit TP = 80, Total weight = 15
Algorithm
GREEDYKNAPSACK( n, m, w[ ], p[ ], x[ ] )
For i = 1 to n
x[i] = 0
End for
u=m
For i = 1 to n
If w[i] > u
Break
Else
x[i] = 1
u = u w[i]
End if
End for
If i

x[i] = u / w[i]

End if
End GREEDYKNAPSACK

DIVIDE & CONQUER METHOD


The divide and conquer methodology is very similar to the modularization
approach to software design. Small instances of problem are solved using some direct
approach. To solve a large instance, we first divide it into two or smaller instances solve
each of these smaller problems and combine the solutions of these smaller problems to
obtain the solution to the original instance. The smaller instances are often instances of
the original problem and may be solved using divide and conquer strategy recursively.
MERGE SORT:
The divide and conquer method can be applied to the sorting problem. In this
problem we must sort n elements into increasing order. The divide and conquer method
suggests sorting algorithms with the following general structure. If the number of
elements to be sorted is one, terminate, otherwise, partition the collection of elements into
two or more subcollections: sort each, combine the sorted subcollections into a single
sorted collection.
For principle and algorithm refer the Unit 4 merge sort topic
BACKTRACKING METHOD
Backtracking is a systematic way to search for the solution to a problem.
In Backtracking method,

We begin by defining a solution space for the problem. The solution space is
the collection all possible solutions to the given problem. The solution space
is usually represented as a tree or a graph.
Organize solution space so that it can be easily searched.
Once we have defined an organization for the solution space, this is searched
in a depth first manner (DFS).
During the search if infeasible solution is sensed then backtrack to previous
node.
The search terminates when we have found the answer.

8 QUEENS PROBLEM
The solution for the 8 queens problem is easily obtained using the backtracking
algorithm.
Given,

An 8 X 8 matrix representing a chessboard.


8 queens

Aim of the problem:


Place 8 queens on the chessboard in such a way that none of the queens hit each other.

Constraint:

No two queens should be in the same column.


No two queens should be in the same diagonal.

Solution:
If a queen is placed in position (i, j ). Now a new queen is placed in the position (k, l)
then the two queens are said to be in the same diagonal if following conditions are
satisfied.
i+j=k+l
ij=kl
The above two equations can be rearranged as follows:
ik=lj
ik=jl
Combining the above two equations,
Abs(i k) = Abs(j l)
Abs indicates the absolute value. If this condition is true, then the queens are in the same
diagonal. To check whether the queens are in the same column we just check whether
j = l.
Now queens are placed one by one in the chessboard by checking the above conditions.
If at any stage we are unable to place a queen, then we have to backtrack and change the
position of the previous queen. This is repeated till we place all the 8 queens on the
board.
The algorithm Place checks and tells whether the new position of the queen is correct or
not. If it is correct, then it returns true otherwise it returns false.
Example:
We try to place the queens as shown.

Solution is:
1

Algorithm
PLACE( k, L )
For i = 1 to k 1
If x[i] = L or ABS(x[i] l ) = ABS( i k )
Return FALSE
End if
End for
Return TRUE
NQUEEN( k, n )
For i = 1 to n
If PLACE( k, i ) = TRUE
x[k] = i
if k = n
print x[ ]
else
NQUEEN( k + 1, n )
End if
End if
End for
End NQUEEN

DYNAMIC PROGRAMMING
Dynamic Programming: Dynamic programming is an algorithm that can be used when
the solution to a problem can be viewed as the result of a sequence of decisions.
In dynamic programming, we examine the decision sequence to see whether an
optimal decision sequence contains optimal decision subsequence.
TRAVELING SALESMAN PROBLEM
The traveling salesman problem presents a graph showing n number of cities
which are connected using edges. The cost or distance of each edge is given using the
cost matrix.
Given:

A graph showing n number of cities connected by edges.


Cost of each edge is given using the cost matrix.

Aim of the problem:


Find the shortest path to cover all the cities and come back to the same city.
Constraints:

All the cities should be covered.


Each city should be visited only once.
The starting and the ending point should be the same.

Solution:
1) Find all possible feasible solutions by taking the permutation of the cities which is
to be covered. By this all possible paths connecting the cities and satisfying the
constraints are generated.
2) Find the cost of each path using the cost matrix.
3) Find out the path with minimum cost. That is selected as the optimum solution.
Example:
Consider the following example. There are 4 cities given. These are connected with
edges as shown. The cost of the edges are shown.

The cost matrix for the given graph is


1

20

10

20

15

25

15

10

25

Let us start visiting from the node 1. Then the remaining 3 cites are 2, 3 and 4. By
applying the permutation function we generate the following possible paths.
1
1
1
1
1
1

2
2
3
3
4
4

3
4
2
4
2
3

4
3
4
2
3
2

1
1
1
1
1
1

50
55
55
55
55
50

Now calculate the cost of each path and select the minimum of these. If there more than
one path having the same cost, then first occurring path is selected.
As per the results shown above, the shortest path selected is the first path.
Therefore the final solution may be,
1

The cost of the path is 50

Algorithm
TRAVEL(cost[ ], n )
x=2
for s = 1 to n 1
list[s] = x
x=x+1
end for
for i = 1 to (n 1)!
for j = 2 to n
path[i][j] = perm(list)
path[i][j] = path[i][n] = 1
pathcost[i] = 0
end for
end for
for i = 1 to (n-1)!
for j = 1 to n
pathcost[i] = pathcost[i] + cost[path[i][j]][path[i][j+1]]
end for
end for
min = 0, minpos = 0
for i = 1 to (n-1)!
If pathcost[i] < min
min = pathcost[i]
minpos =i
end if
end for
print Shortest path is path[minpos][ ]
print Shortest path cost is pathcost[i]
end Travel

Vous aimerez peut-être aussi