Vidhya Institute Data Structure
Vidhya Institute Data Structure
DATA STRUCTURE
Data is simply values or sets of values that is utilized in calculation or manipulation. When we process this
data then it becomes information. Data can be distinguished in different data types like integer, floating or character
type. A student’s name, age, class, marks are the examples of data. When these data can be collected and organized,
in some way, it is called record. For example, 18 is a data, because we don’t know its significance, while if we say
“Age of pearl is 18”. Now this becomes information. This statement has some significance. Also, if we store it in
computer as a ser <Name, age> then it is record e.g. <pearl, 18>, <John, 24> etc.
Data structure is representation of the logical relationship existing between individual elements of data. In
others words, a data structure is a way of organizing all data items that considers not only the elements stored but
also their relationship to each other.
A data structure is said to be linear if its elements form linear sequence. Example of linear data structure
are Arrays, Stacks, Queues and linear Linked lists.
A data structure is said to be non – linear if its elements does not form linear sequence. Example of non –
linear data structure are Trees and Graphs.
The possible operations on data structures are Traversal, Insertion, Deletion, Searching, Sorting and Merging.
Traversing
Traversing means accessing each record exactly once, so that each record may be processed.
Insertion
Adding a new data into the list any where at the specified location is called insertion.
Deletion
Removing the existing data from the list is called deletion.
Searching
It is a process of finding and element and its location in a collection of elements.
Sorting
Sorting can be defined as rearranging the elements into a desired sequence either in
increasing or decreasing order.
Merging:
Combining two different records into a single one.
ALGORITHMS
An algorithm is a step by step procedure to solve a particular problem. It means, it is a set of instructions
written to carry out certain tasks. It creates the logic of program. An algorithm is thus a sequence of instructions
that transform some input data into some output in a finite number of steps.
An algorithm is said to be correct, if for every input instance, it halts with the correct output. We say that a
correct algorithm solves to given computational problem. An incorrect algorithm might not halt at some input
instances.
Rules for writing an algorithm
There are following certain rules for writing an algorithm.
Rule 1. Begin: An algorithm should begin with ‘begin’ statement.
Rule 2. Variable Names: Variable names should be in capital letters.
For example, A, B, SUM or Sum
Rule 3. Assignment Statement: Assignment of values to variable should be in following manners:
Set A = 10 or Set A:10
Rule 4. Input Statement: Data may be print using following statement:
Read: A, B
Rule 5. Output Statement: Data may be print using following statement:
Write: A or Print: A
Rule 6. Declaration of variable: Variable should be declared using following statement:
Declare: A, B, SUM
Rule 7. Comments: Each step may contain a comment in bracket which indicates the main purpose of
the step. The comment will usually appear at the beginning or the end of step.
Rule 8. End or Exit Statement: The algorithm is completed when the statement ‘Exit’ or ‘End’ is
encountered.
COMPLEXITY
The complexity of an algorithm M is the function f(x), which gives the running time and /or storage space
requirement of the algorithm in terms of the size ‘n’ of input data.
Mainly there are two types of complexity.
1. Space complexity
2. Time complexity
Space Complexity
The space complexity of an algorithm is the amount of computer’s memory it needs to run and compute
results. The space needed by algorithms is the sum of the following components
1. A fixed part that is independent of the characteristics (e.g. no. and size) of the Inputs and outputs. This
part includes the space needed by
Instruction space
Space for simple variables and fixed size components variables
Space for constants
2. A variable part that consist of the space needed by
Component variable whose size is dependent on the particular problem being solved.
Referenced variable (this depends on instance characteristics)
The recursion stack space.
Therefore the space complexity S(p) for any algorithm may be written as
S(p) = C + Sp(n)
Where C = Constance
n = instance characteristics
Example 1.2: Function to compute the sum of elements of an array having N elements.
1. Sum (ARR, N)
2. {
3. S:=0;
4. for I = 0 to N – 1 by 1
5. set S: = S + ARR[I]
6. return S;
7. }
Here the problem instance are characterized by ‘N’ the number of elements to be summed
The space needed by n is 1 Word
The space needed by ARR is at least N Word
(Space ARR must be large enough to hold N elements)
The space needed by I 1 Word
The space needed by S 1 Word
Therefore total space needed by algorithm is (n+3).
Time Complexity
Time complexity of an algorithm is the amount of time that computer needs to run and compute the
result. The time taken by an algorithm is the sum of the compile time and the run or execution time. The
compile time dose not depend on the instance characteristics.
The time complexity of an algorithm is given by the number of steps taken by the algorithm to
compile the function it is designed for. The number of steps that are assigned to any program statement
depends on the kind of statement for example,
Comments counts as zero steps.
Assignment statement which does not involve any cells to other algorithm is counted as one step.
In step iterative statement such as for, while, repeat- until etc. we consider the step counts only for the
control part of the statement.
Example 1.3: When the statement to increment count are introduced in above example the function becomes:
1. Sum (ARR, N)
2. {
3. S:=0
4. count:=count +1; //count is global initially zero
5. for I = 0 to N – 1 by 1
{
count := count +1; // for “for loop”
6. s:=s + ARR[1];
7. count := count +1; // for “Assignment”
}
8. count := count +1; // for “last time of for loop”
9. count := count +1; // for “return”
10. return S;
11. }
We are only interested in determining the changes in the value of count. For any initial value of count above
algorithm compute the final value for count.
In For loop value of count will increase by a total of 2N. If count is zero initially, then it will be 2N+3 on
termination. So each invocation of above algorithm executes total of 2N+3 step.
1. Best case
Generally most of the algorithm be have sometimes in best case. Best case means it should take shortest
time to execute the algorithm with the last amount of work. For example, for a searching algorithm he best case
would be if the element we are searching for is found in the first time. As a result this algorithm would need only
one composition irrespective how large is the input.
2. Worst case
Generally we see the complexity of algorithm in it’s worst case behavior. When an algorithm takes most
time, it represents the worst case. For example, in liner search, when we find the element at the end or when
searching fails, then it behaves as worst case.
3. Average case
Analyzing the average case of behavior of algorithm is little bit complex than best case and worst case.
Average case of algorithm should be the average number of steps.
Asymptotic Notations
Asymptotic Notations are used to describe the time complexity in numerical form. This notation is called
“ASYMPTOTIC” because it deals with the behavior of functions in the limit, that is for sufficiently, large value of
its parameter.
Various asymptotic notations are
1. Big oh(0) notation
2. Omega (Ω) notation
3. Theta(θ) notation
4. Little 0 notation
5. Little omega notation
f(n) = 0 (g(n))
Cn(g(n)
f(n)
n
f(n)
Example 1.4: Let us say that f(n) = 2n +8 and g(n) = (n)2 we have to find an integer n0 and a constant C such that
for integer n > n0 , fn ≤ cn2
Suppose we choose C = 1 then
f(n) ≤ cn2
2n + 8 ≤ n2
0 ≤ n2 -2n – 8
0 ≤ (n+2) (n-4)
f(x) = Ω (g(n)).
f(n)
C(g)(n)
n
n0
Example 1.5: Consider that f(n) = 5n2 – 64n + 256 and g(n) = n2 we have to find an integer n0 and a constant
c such that for all integer n > n0; f(n) ≥ cn2
f(n)
C1(g(n))
n
n0
In other words, for n ≥ n0, the function f(n) belongs n, lies between c1 (g(n)) and c2(g(n)) i.e. lower bound and
upper bound of function. We say that g(n) is n asymptotically tight bound for f(n).
This is basically saying that the function, f(n) is bounded both from the top and bottom by the same
function g(n).
Little – 0 Notation
For non – negative functions, f(n) and g(n), f(n) is little 0 of g(n) if and only if f(n) = 0 (g(n)), but
f(n) ≠ (g(n)). This is denoted as
n) = 0 (g(n))
This represents a loose bounding version of Big 0. g(n) bounds form the TOP but it does not bound the
bottom.
ARRAY
A single variable which can hold multiple values of the same type.
No. of values specified in subscript [square Bracket]
int [10] Integer Array
Subscript
It is also called linear array or 1-D array.
When multiple subscript is used is called multidimensional array.
When 2 subscript is used is called 2-D array.
Array is a “Contiguous Memory Allocation”.
Address of 1-D Array
Loc (LA (K)) = Base Address (LA) + W (k-1)
It is a formula by which we can find out the address of a given location K in Array.
Here
LA Linear array
Base (LA) Base Address of LA
W Word Length (Database size)
K Location of element
2-D ARRAY
Multiple Dimension can be Specified
When 2 Dimension is used is called 2-D Array
Two Subscript is used
One is specify Rows .(i) int a [3][3]
Second Specify No. of Column. (j)
1. Row major form
2. Column major form
Formula 1:
For Column Major Order
Loc (A[i, j]) = Base (A) + W [M (i-1) + (j-1)]
Formula 2:
For Row Major Order
Loc (A [i, j]) = Base (A) + W [N (j-1) + (i-1)]
For Example:
MxN 25*4
Base (A) 200
W 4
Row Major A [12, 3] = ?
j=12, k=3
MATRIX
2-D Array is also Called as matrix.
Algo
Matrix – Addition (mat a, mat b, mat c, r,c)
Here
mat a Matrix a
mat b Matrix b
mat c Addition of mat a & mat b
r No. of Rows.
c No. of Columns.
Algo: -
SQUARE MATRIX
A Matrix where no of Rows & No. of Column are always equal.
A [r][c], Where r=c
Diagonal Matrix
A Diagonal Matrix is a matrix whose all diagonal elements are zero (0)
Matrix A is Diagonal
If A[i,j]=0 for all i ≠ j
Tridiagonal Matrix
A Tridiagonal Matrix is a matrix who all diagonal, lower Diagonal, upper
Diagonal element are not zero (0)
Matrix, A is Diagonal
SPARSE MATRIX
A matrix is a sparse matrix if no. of elements are zero (0).
A matrix which is not sparse is called Dense matrix.
DENSE MATRIX
When any M X N Sparse Represent in the memory then it occupy M X N blocks.
But No. of element are zero.
So that is wasting of memory.
For Example: - Diagonal, Lower Triangular, etc. are comes under the category of sparse
matrix.
So representing the sparse matrix is so much wasting of memory.
That’s why different-2 types of technique is used to represent the sparse matrix
(A). By Array.
(B). By Linked List.
(A) By Array
For Representing the sparse matrix using array 2-D Array is used with fixed format.
No. of columns are always 3.
No. of rows are : = No. of Non Zero elements of sparse matrix + 1
First Row represent No of Rows, No of Columns and No of Non Zero Elements.
Remain rows contains Row no, Columns No. and Non Zero Element value.
For Example:-
Consider Sparse Matrix
Value
Column No.
No. of Data part= 2
No. of Data part = 1
Element Value
Now as per Requirement with in this representation new Node [Element] can be inserted Or
Deleted.
STACK
Different – different types of data structure we have, Stack is also one of the most important and most
useful data structure.
Stack is a special data structure which is based on LIFO [Last In First Out] technique.
Stack is a Linear Data Structure.
When we insert number of balls with in a pipe which is closed from one side, that type of structure is
called as “Stack”.
In case of stack, any type of operation or task will be done at one point. Means insertion & deletion will be
done at same location, generally we call this location as Top.
Concept of LIFO
LIFO refers to Last In First Out, means element which comes or inserted at last in structure, will be
moved out first from structure. That is LIFO.
Suppose we insert red ball then blue ball and then green ball in a pipe.
Now if we want to access or move out any ball from that pipe, then
Only green will be moved out first, than blue and then red.So the element which is inserted at the last in
structure is moved out first. That concept is LIFO and stack is based on this concept.
Stack Implementation
stack can be implemented in two ways:
1 static implementation
2 Dynamic implementation
Static Implementation
It uses array to create stack. Static implementation is the most widely used technique but it is not too
efficient with respect to memory utilization, because in static implementation the size of stack has to be declare
during the program design. now suppose if there are few elements to be stored in the stack, some allocated memory
will be wasted. on the other hand if there are a large number of element to be stored in the , then we cant change
the size of array and our purpose is not solved in both ways.
Dynamic Implementation
It is achieved using linked list that uses pointers to implement the stack. Dynamic implementation is the
most widely used technique and it is too efficient with respect to memory utilization, because in Dynamic
implementation the size of stack has to be declare during the execution. now suppose if there are few elements to
be stored in the dynamic stack, some allocated memory will not be wasted. on the other hand if there are a large
number of element to be stored in the, then we can change the size of linked list and we can release the memory.
our purpose is solved in both ways.
Note
As we know that stack is based on LIFO fashion/ technique, means all operation (push / pop / peek) will be
done at same location that is top. So all above operations will be done at top location.
Diagrammatically Representation Of Stack Operation
Initially top will be -1, because, initially stack will empty and top can be 0, but in case of array 0(zero) is a valid
location of element that’s why we initialize top by 0.
When we PUSH element in stack, then top increase by one.
When we POP element from stack, then top decrease by one.
1. Push Operation Representation 4 10
Initial stack of 5 elements:
3 20
2 32
1 25
0 52
top = -1
Pushing of 10, 20, 30, 40, & 50 one by one.
PUSH PUSH PUSH PUSH PUSH
10 20 30 40 50
4 10 10 4 10 4 10 4 10 4 50 4top
10
top = top+1
40 3
top = top+1
top = top+1
top = top+1
top = top+1
3 20 20 3 20 3 20 3 40 3top
10
2 32 32 2 32 2 30 2top 30 2 30 2
1 25 25 1 20 1top 20 1 20 1 20 1
0 52 10 0top 10 0 10 0 10 0 10 0
top = -1
50 104 50 4 50 4 50 4 50 4
40 3top 40 3 40 3 40 3
top = top-1
top = top-1
top = top-1
top = top-1
40 3
top = top-1
10
30 2 30 2top 30 2 30 2 30 2
20 1 20 1 20 1top 20 1 20 1
10 0 10 0 10 0 10 0top 10 0
PUSH COADING
void push(void)
{
if(top==MAX-1)
printf(“\n stack overflow ”);
else
{
top=top+1;
printf(“\n Enter the element ”);
scanf(“%d”,&a[top]);
}
}
Algorithm of push operation in the stack
let Stack is an array having MAX elements for implementing the stack.
Step 1 : start.
step 2 : [check for stack overflow ?]
if top=MAX-1 ,then :
(a) print “overflow”
step 3: set top=top+1 [increase top by 1]
step 4: [add num in stack] set stack[top]=num [read num on stack[top]]
[end of if structure]
step 5: stop.
POP CODING
void pop(void)
{
if(top==-1)
printf(“\n stack underflow ”);
else
{
printf(“\n poped element %d”,a[top]);
top=top-1;
}
}
step 5: stop.
PEEK CODING
void peek(void)
{
if(top==-1)
printf(“\n stack underflow ”);
else
printf(“\n peeked element %d”,a[top]);
}
TRAVERSE OPERATION
void traverse(void)
{
if(top==-1)
printf(“\n underflow”);
else
{
for(i=top;i>=0;i--)
printf(“ %d”,a[i]);
}
}
Algorithm of traverse operation in the stack
let Stack is an array having MAX elements for implementing the stack.
Step 1 : start.
step 2 : [check for stack overflow ?]
if top=-1 ,then :
print “underflow”
otherwise
step 3 : repeat step 4 for i=top to 0 by step -1
step 4: print a[i]
[end of loop]
[end of if]
step 5: stop.
4 50 top 4 4
3 40 3 3
2 30 2 30 top 2 s
1 20 1 20 1
0 10 0 10 0
Display: -50 40 30 20 10 30 20 10 stack underflow
In Calling Function
When any function calls another function then control again comes back to calling function. So at this time for
coming back, the address of this calling function stored by stack.
Function Recursion
During recursion, when function calls itself then passing values and intermediate values are maintained within Stack.
Recursion always maintain stack.
In Parenthesis Checking
Parenthesis checker is a program which is used to find out that entered equation is properly parenthesized or not,
this program is implemented with the help of stack.
“Our system also check that the equation with the same type program.”
((3+2) *4 wrong
{(3+2}) *4 wrong
{(3+2}) *4] wrong
[{(3+2)} *4] right
Practical Implementation
#include<stdio.h>
#include<process.h>
#include<conio.h>
void main()
{
char s[100],stack[50],ch1,ch2;
int i,top=-1;
clrscr();
printf("\nEnter Expression for Paranthesis Checker : ");
gets(s);
for(i=0;s[i]!=NULL;i++)
{
if(s[i]=='(' || s[i]=='{' || s[i]=='[')
stack[++top]=s[i];
else
{
if(top==-1)
{
printf("\nInvalid Expression");
getch();
exit(0);
}
else
{
if(s[i]==')' || s[i]=='}' || s[i]==']')
{
ch1=s[i];
ch2=stack[top--];
switch(ch2)
{
case '(': ch2=')'; break;
case '{': ch2='}'; break;
case '[': ch2=']'; break;
}
if(ch1!=ch2)
{
printf("\nInvalid Expression");
getch();
exit(0);
}
}
}
}
}
if(top==-1)
printf("\nCorrect Expression");
else
printf("\nInvalid Expression");
getch();
}
Expression evaluation
An Expression is made of operands. operators and delimiters. In most programming language , arithmetic expressions
are written as :
X=A*B-C-D/E.
this expression have five operands : A B C D E
PRECEDENCE OF OPERATORS IN C
PRIORITY OPERATOR
1. [],{},<>,()
2. ^
3. *,/,%
4. +,-
5. <,>,<=,>=
6. ==,!=
7. &&
8. ||
TYPE OF NOTATION
INFIX in infix notation operators are placed in between the operands.
a+b (infix)
Evaluation of Postfix
For evaluation of postfix expression, we maintain the stack. The stack should be used to store the
operations. For evaluation, the postfix expression is scanned from left to right. When an operand is found, it is
pushed onto the stack and when an operator is found, the last two operands are popped from the stack. Then
required operations is applied to them and their result is pushed onto the stack. Hear we have no need of
information of operator precedence.
Let us take an array postfix which has arithmetic expression in postfix from. The steps involved to
evaluate postfix expression eill be :-
Step 1- Scan the symbols of array postfix one by one from left to right.
Step 2- If symbol is opened, then push it to stack.
Step 3- If symbol is operator then pop last two elements of stack and evaluate it as
[top-1] operator [top]
Step 4- Do the same process unit scanning of postfix array not ends.
Step 5- Pop the element of stack which will be the value of evaluation of postfix arithmetic expression.
Step 1- Add the symbol ‘(‘into stack &’)’ at the end of array infix.
Step 2- Scan the symbols of array postfix one by one from left to right.
Step 3- If symbol is left parenthesis ‘(‘ then add it to stack.
Step 4- If symbol is operand then add it to array postdix.
Step 5-
(i) if symbol is operator then pop the operators which have same precedence or higher precedence
then operator which occurred.
(ii) Add the popped operator to array postfix.
(iii) Add the scanned symbol operator into stack.
Step 6-
(i) If symbol is right parenthesis ‘)’ then pop all the operators from stack until left parenthesis ‘(‘ in
stack.
(ii) Remove the left parenthesis ‘(‘ in stack..
Step 7-
Do the same process until scanning of array infix not ends
Let us take an infix expression and convert it into postfix
A*(B+C^D)-E^F*(G/H)
Initially ‘(‘ will be added in stack and ‘)’ at the end of infix expression.
So now the infix expression will be-
A*(B+C^D)-E^F*(G/H)
Step Symbol in stack Operator Expression postfix
1. A ( A
2. * (* A
3. ( (*( A
4. B (*( AB
5. + (*(+ AB
6. C (*(+ ABC
7. ^ (*(+^ ABC
8. D (*(+^ ABCD
9. ) (* ABCD^+
10. - (- ABCD^+*
11. E (- ABCD^+*E
12. ^ (-^ ABCD^+*E
13 F (-^ ABCD^+*EF
14. * (-* ABCD^+*EF^
15. ( (-*( ABCD^+*EF^
16. G (-*( ABCD^+*EF^G
17. / (-*(/ ABCD^+*EF^G
18. H (-*(/ ABCD^+*EF^GH
19. ) (-* ABCD^+*EF^GH/
20. ) ABCD^+*EF^GH/*-
So now the postfix expression is-
A B C D ^ + * E F ^ G H / * -
We know that the result postfix expression is parentheses free and operators are in order of sequence of evaluation
with operands.
TOWER OF HANOI
#include<stdio.h>
#include<conio.h>
void tower(char , char ,char ,int );
void main()
{
int n;
clrscr();
printf("\n Enter the Number Of Plates ");
scanf("%d",&n);
tower('A','B','C',n);
getch();
}
void tower(char ch1, char ch2, char ch3, int n )
{
if(n==1)
printf("\n %c => %c",ch1,ch3);
else
{
tower(ch1,ch3,ch2,n-1);
tower(ch1,ch2,ch3,1);
tower(ch2,ch1,ch3,n-1);
}
}
It is a menu driven program. When we run this program, then a menu will be displayed in front of us
which provide us various options to perform operation of the stack selected by us.
In this program maximum 10 elements can be pushed and if we want to increase this capacity, then
increase the value of n, which is defined as a Symbolic Constant along with header files with the
help of # define.
This program will not close or stop until you press 6(exit) button.
QUEUE
In number of data structure, we have a Queue Data Structure also. Queue is also one of the most
important and useful data structure.
Queue is a special data structure which is based in FIFO [FIRST IN FIRST OUT] technique.
Stack is a linear data structure.
When we insert number of balls with in a pipe which is open from both sides, that type of structure or
arrangement of element is known as queue.
This queue data structure is exact similar to our queue just as queue of student for purchasing examination
form.
Queue of passengers waiting for bus.
In case of queue, any type of operation or task will be done at two different- different points, means
Insertion &Deletion will be done at two locations. These are f [Front] & r [Rear]
Front location is used for deletion of element.
Rear location is used for insertion of element.
Concept of FIFO
FIFO refers to First In First Out, means element which comes or inserted first in structure, then it will
move out or deleted first from structure [same as queue of persons] that is [FIFO].
Suppose we insert red ball then blue ball and then green ball in the pipe which is open from both side.
Now if we want to access or move out any ball from this pipe, then only red will move out first, then blue
and then green because queue is based on FIFO concept.
So the element which is inserted first in the structure then it will be move out first from the structure, that
concept is FIFO and queue is based on FIFO concept.
Various Operations On Queue
If we implement any data structure then numbers of operations are needed to be performed on that
structure. So operations which can be performed on queue are specified below:
1 ENQUEUE 2 DEQUEUE
3 PEEK 4 DISPLAY
ENQUEUE
“Insertion of element in Queue”
When we insert element in queue, that operation is called as Enqueue. It is done at the rear location of
queue.
else
{
printf(“\n dequeued element %d”,a[front]);
Front++;
}
}
PEEK/PEEP
“Only accessing the element from the queue without removing it from Queue”
When we want to know that which element is present or stored at front location or which
element wii be removed when we do so, that’s why just for accessing the element from queue from the front
location without removing it from queue. This is known as PEEP operation.
void peek(void)
{ Step 1: start.
If(front>rear) Step 2: check if (front>rear) then,
printf(“\n underflow”); Print “underflow”
Else Otherwise
printf(“\n peeked element %d”,a[front]); Step 3: print “peeked element” a[front]
} [end of if]
Step 4: Stop.
Display
It is the process of showing all the element of queue within FIFO fashion. Display doesn’t
remove the element from the queue; it only shows all the elements. Display always done from front to rear location.
Isempty
It is optional operation. It is basically used for internal processing and find out the validity of operation
either it can be performed or not. This process identifies whether the queue is empty or not.
If(front>rear)
printf(‘\n underflow”);
isfull
It is basically used to find out whether the queue is full or not. So that Insertion like operation can be
performed or not.
if(rear==max-1)
printf(“\n underflow”);
4 10
3 20
2 32
1 25
front 0 52
rear = -1
104 4 4 4 50 4r
rear=rear+1
rear=rear+1
rear=rear+1
rear=rear+1
40
rear=rear+1
3 3 3 3r 40 3
10
2 2 30 2r 30 2 30 2
1 20 1 r 20 1 20 1 20 1
10 0 r 10 0 10 0 10 0 10 0
During Enqueue,10 front will always be pointed to first element in above case it is 0 th location and rear (r) will be
increased by one with every insertion.
10
After that if we insert or enqueue the element, stack will be “overflow” (when n=r)
DEQUEUE Operation Representation
Technique 1: -
rear 4 50
3 40
2 30
1 20
front 0 10
front=front+1
front=front+1
front=front+1
front=front+1
40 3 40 3 40 3 f 40 3 40 3
30 2 30 2 f 30 2 30 2 30 2
20 1f 20 1 20 1 20 1 20 1
10 0 10 0 10 0 10 0 10 0
Here element is dequeuing from front (f) that’s why front increasing by one when every element is
removed or dequeue from queue.
Dotted elements represent deleted element.
Ques: When any element is removed from queue and in last stage all elements have been removed
from Queue; even it is showing queue overflow (why)?
As rule when r arrive at n means queue is full or overflow.
And in every stage, when element is removing queue always is located at n. So queue will always full
even its locations are empty.
It is major drawback of queue, that when every element removes from queue, than at this time also
queue is flow, or no space for new element.
But naturally it is a genuine reason. That when one is removed, surely another can be stored here.
So now we will remove or dequeue the element with other technique. (Shown below)
TECHNIQUE – 2
In this special technique when we remove any element then it will be replaced by its next location, and in
this way all elements will be replaced by their next element.
So in last, a block will become empty and new element can be stored here and rear (r) will decrease by
one.
So with the help of this technique when queue element dequeued, the new element can be inserted into
the queue, not like before. (technique)
Suppose we have a following queue with 5 elements
rear 4 50
3 40
2 30
1 20
front 0 10
If element dequeued from queue
front=front+1
front=front+1
front=front+1
3r
front=front+1
30 2 30 2 30 2 40 2 40 2
20 1 20 1 30 1 30 1 30 1
10 0 f 20 0f 20 0f 20 0f 20 0f
default:
printf(“\n invalid choice”);
printf(“\n try again with menu based values”);
}// closing of switch();
getch();
}// closing of while loop
}closing of main function & program .
Technique 2
Implementation of technique 2 is exactly similar to technique -1 only case 2 will change that is specified
below (dequeue case)
case 2:
if (r= = -1// f= = n)
printf (“\n queue underflow”);
else
{
printf(“\n %d element is going to technique, ” a[f]);
for (i=f; i<r;i++)
a[i] = a[i+1];
r--;// decrease rear
}
break;
So after the execution of this case loop every element shifted to its down location and r will be
decreased by one, so the capacity of queue will increase because in this case now r not equal to n.
That’s why it is better than technique – 1.
Applications / Uses Of Queue
In our real life
Queue of exam forms
Queue at window of ticket etc.
System Queue
System perform various tasks, for processing system maintain different – different types
of queues.
For example.
Instruction Queue
This queue maintains the current instructions which are going to be executed by the
processor.
Device Queue(I/O queue)
This queue stores id of all the devices which are currently available within the system.
Waiting Queue
When processor executes any processing, and at same times another process comes into
existence, and then it has to wait, so these waiting processes are hold by waiting queue.
Queue is used in BFS (Breadth First Search) of graph.
Queue is used in client server computing
Printing Queue
This queue holds all the process which is waiting for their turn when any other process
is using printer.
Queue is also used in level order traversal of binary tree
Queue plays very important role in processing [by processor]
ALGO
Enqueue (queue, front, rear, max, item)
Step 1: [chek for overflow]
If rear = max-1 then
Display “queue overflow”
Exit
End if
Step2:
[increase one by one]
Set rear = rear +1
Step 3:
[store item at rear location]
Set queue [rear] := item
Step 4 exit
ALGO
Dequeue [queue, front, rear, and item]
PRIOITY QUEUE
Special type of queue
Follow all the rules of queue
Insert done at rear
Deletion is not directly specified.
Deletion is based on priority of element.
Deletion can be performed any where.
So when any element is entered, then its priority must be entered.
Two types of priority queue are here
(1) Ascending Priority Queue
it effect deletion of element
lowest priority element will removed
(2) Descending Priority Queue
It also effect deletion of element.
Highest priority element will removed
Representation of priority queue
By Linked List
By 2-D Array
By Structure
By Linked List
every node have three part
Two data part
Part 1 : element (e)
Part 2 : priority (d)
one address part
Link/ next : point to the next node
By 2-D Array
Two sub script is used
M one for number element.
N priority of each element
For example
int p[4][2] ;
10 4
20 1
30 3
40 2
By Structure
As we know, that > structure is an user define data type
It is a collection of different data type.
Here, we can use the structure.
We create a structure
With two integer elements
One for element (e)
One for priority (p)
For e.g.,
Struct queue
{
int e;
int p:
};
struct queue q [4];
0[10][500]
1[20][-40]
2[30][2]
3[40][50] priority
CIRCULAR QUEUE
It is a special type of queue like priority queue .
queue will cyclic form is called circular queue.
When front and rear combine together it forms circular queue.
used to eliminate overflow situation.
Endless queue.
Front & rear is used.
#include<stdio.h>
#include<conio.h>
#include<process.h>
#define max 5
int a[max],front=-1,rear=-1;
void enqueue(void);
void dequeue(void);
void peek(void);
void traverse(void);
void main()
{
int ch;
while(1)
{
clrscr();
printf("\n 1. Enqueue");
printf("\n 2. Dequeue");
printf("\n 3. Peek");
printf("\n 4. Traverse");
printf("\n 5. Exit");
printf("\n Enter the choice....");
scanf("%d",&ch);
switch(ch)
{
case 1: enqueue(); break;
case 2: dequeue(); break;
case 3: peek(); break;
case 4: traverse(); break;
case 5: exit(0);
default: printf("\n INVALID CHOICE...");
}
getch();
}
}
ALGO FOR INSERTIION
void enqueue(void) Step 1: start.
{ Step 2: check if (front=0 And rear=max-1)
if((front==0 && rear==max-1)||(front==rear+1))
OR (front=rear+1)) then,
printf("\n overflow");
Print “overflow”
else
Otherwise
{ if(rear==-1)
Step(a) check if(rear=-1) then,
{
set rear=0.
rear=0;
front=0; set front=0.
} Again check if(rear=max-1) then,
else if(rear==max-1) Set rear=0.
rear=0; Otherwise
else Set rear=rear+1;
rear++; [end of if]
printf("\n enter the element "); Step 3: read an element a[rear].
scanf("%d",&a[rear]); [end of if]
} Step 4: stop.
void dequeue(void)
{ ALGO FOR DELETION
if(front>rear) Step 1: start.
printf("\n underflow "); Step 2: check if (front=-1) then,
else Print”underflow”
{ Otherwise
printf("\n Dequeued element %d",a[front]); Step 3: print “dequeued element ”a[front].
if(front==rear) Step 4: check if (front=rear) then,
{ Set front=-1;
front=-1; Set rear=-1.
rear=-1; Again check (front=max-1) then,
} Set front =0.
else if(front==max-1) Otherwise
front=0; Set front=front+1.
else [end of if structure]
front++; Step 5: stop.
}
}
void peek(void)
{ ALGO FOR TRAVERSE
if(front>rear)
printf("\n underflow "); Step 1: start.
else Step 2: check if front=-1 then,
printf("\n Dequeued element %d",a[front]); Print “ underflow”.
} Otherwise
Step 3: check if (front<=rear) then,
void traverse(void) Step 4: Repeat step (a) for i=front to rear ,
{ Step (a) print a[i]
int i; [End of loop]
if(front>rear) Otherwise
printf("\n underflow "); Step 5: repeat for step (6) for i=front to max-1
else Step 6: print a[i]
{ [End of loop]
if(front<=rear) Step 7: repeat for step (8) for i=0 to rear
{ Step 8: print a[i]
for(i=front;i<=rear;i++) [End of loop]
printf(" %d",a[i]); [end of if]
} Step 9: Stop.
else
{
for(i=front;i<=max-1;i++)
printf(" %d",a[i]);
for(i=0;i<=rear;i++)
printf(" %d",a[i]);
}
}
}
Application of Queue
MEMORY ALLOCATION
We write our program to perform any task our program will always store some amount of data and for
storing these values memory is required so, here memory must be allocation before its use.
There are two types of memory allocation:
DRAW BACK
When the size of memory block means if number of blocks is not known before then static is not better to use.
Size is not known it is based on run time
So either we specify less or higher size.
If we specify less size:
Then no more data can be interred at run time we can not increase its size so our program will
become failure in case of input data.
We specify huge size:
Then if user entered less amount of data and we are not able to decrease the size of memory at
runtime then,
“Wastage of memory” our memory will become waste, no any another program can use it so
this thing reduce the performance of our system so we can not specify large size.
If contains memory is not available in memory then static memory allocation become fail,
That’s why because of this drawback dynamite memory allocation is used.
Basically used to save the large amount of memory it size of memory is not
known.
DRAW BACK
Increase complexity of our program.
Decrease readability of program.
Concept of pointer is always used, which make program compiler.
No. easy to implement.
Specially functioning is required to allocate or deallocate the blocks memory like.
malloc, calloc, realloc, or free.
Because memory already allocated at compile time.
Increase the readability of our program.
Reduce the complexity of our program.
No burden of programs of memory management easy to implement..
Generally no use of pointers.
Array type of memory allocation is called static memory allocation.
Data can be accessed directly with unique position number called index no.
No. specially functioning is required.
When the size of memory block means it number of block are not known before the static is not
better to use.
Because When we static memory allocations then we have to specify the size.
Size in not known it is based on run time.
So either we specify less size or higher size.
If we specify less size.
Then no more data can be entered run time we can not increase its size so our program will
become failure in case of input data.
SOME CONCEPT
Question How dynamically memory is allocated?
Answer Here we will first of all
Specify the structures of memory block where we want to store data these blocks are called
NODE.
As per requirement multiple NODES are created.
We cannot these NODES one by one or when we create the block at the same time we can
connect blocks.
For memory allocation different types of function are used.
Malloc : for allocating single block.
Calloc : for allocation multiple blocks [increase].
Free: remove allocated blocks from member.
Here we made the blocks after that we have connect these NODES.
So for connecting special types of NODE structure is required [as follow]
DATA PART
This part contain all those which we want to store in memory.
Data part can also further divided in multiple data part
such as stud roll no, name, percentage because generally
we create node to hold multiple data about any entity
like student book, EMP.
ADDRESS PART
It we say that after creating the NODES we have to connect them so for connecting always
pointer is required here these above address part is pointer which hold the address of next
NODE so generally it is named next pointer.
So any always have these above two parts data part and address part these both parts can be
multiple but depend on requirement.
Question what will be the type of pointer next either int long float char.?
Answer Here NODE address part hold the address of next entire node it does not hold address of
individual data part so that‘s why
The type of next pointer is node type itself and it is a part of node itself means it is a member of
NODE structure.
Such type of structure called Self Referential Structure.
X represent NULL
The move structure is called Linked List
Sizeof()
The size of function is a unary argument function. This function the size of argument in the term of bytes.
The argument can be a variable , array or any data type(int, float, char…)
Example:- sizeof(int);
malloc()
This function is used to allocate the memory space. Of specified size or data type and gives the starting
address to pointer variable.
Example:- ptr=(int*)malloc(10);
This allocate 10 bytes of memory space area to the pointer variable ptr of int type.
ptr=(int*)malloc(10*sizeof(int));
This allocate the memory space 10 times, that holds an int data types. The based address is stored in the pointer
variable ptr.
Example
Void main()
{
Int i,*a;
a=(int*) malloc(5*sizeof(int));
for(i=0;i<5;i++)
{
printf(“\n enter the %d number”,i+1);
scanf(“%d”,(a+i));
}
for(i=0;i<5;i++)
printf(“ %d”,*(a+i));
getch();
}
Calloc()
The calloc() function is used to allocate multiple blocks of memory. This has two arguments.
ptr=(int *) calloc(5,2);
This allocate 5 blocks of memory, each block contain 2 byte memory and the starting address is stored in
the pointer variable ptr which is of type int.
It is use for allocating the memory space for array and structure.
struct student
{
int roll;
char name[30];
};
int rec=50;
ptr=(student *)calloc(rec,sizeof(student));
This allocate the memory space for 100 blocks and each block contain memory space the occupied by the
structure.
Free()
for effective use of the memory we can release the memory space that is not required. We can use free
function for releasing the memory space.
Example :- free(ptr);
realloc()
there are two possibilities when we want to change the size of the block.
In the first case we want the more memory space comparatively to allocate memory space.
In the second case the allocate memory space is more then the required memory space.. For the changing
size of memory block we can use the function realloc();
LINKED LIST
A linked list is a collection of connected nodes, where each node information about an
entity.
Some concepts
Here every node the address of next node but who will hold the address of first node
So here we have to define another pointer that point to first node here we use start and t name
pointer that hold the address of first node.
When t move to next node or another node then how they can move again to first node so start
pointer is used always pointer to first node.
Here X null represent ending of list because last node does not hold address of any node.
step 1: Begin.
step 2: declare struct node *n,*t.
step 3: if STAR=NULL, then: {if list is empty ‘START’ contains NULL}
(a) set start=assign memory address using malloc function
(b) set start->info =data
(c) set start-> next=NULL;
step 4: else
(a) set t=start.(assign the address of first node in another pointer)
(b) repeat while loop t->next !=NULL
t:=t->next;
(End of while loop)
(c) (add node at the end) set n=(assign the memory using malloc function)
(d) set n->info =data;
(e) set n->next=NULL;
(f) set t->next=n.
[end of if structure]
step 5: stop.
Function Definition
void create(void)
{
struct node *t=start;
struct node *n=(struct node*)malloc(sizeof(struct node));
printf(“\n enter the information”);
scanf(“%d”,&n->info);
n->next=NULL;
if(start==NULL)
start=n;
else
{
while(t->next!=NULL)
t=t->next;
t->next=n;
}
}
10 20 30 40 50
start A B C D E
With the help of add last concept we can create a linked list.
Insert at mid
Before defining the procedures consider following points:
Starts & t always point to the first node of a list if list does not exist these pointers contain
NULL
for operational purpose start or t can be moved in linked list at a node and for convenient t is
used to perform operations so it is moved in linked list
[according to choice this pointers can used]
[n] pointer is also used it contain the want to insert in a linked list.
structure is :
struct node
{
int info;
struct node * next;
};
//typedef struct node slist;
Insert at front
function
void addfront(void) Algorithm for insert at the front of the linked list
{ step 1 : create a new node n.
struct node *n=(struct node*)malloc(sizeof(struct node)); Step 2 : check if (start=NULL) then,
printf(“\n enter the information ”); set Start : = n.
scanf(“%d”,&n->info); ohterwise
n->next=start; Step 3: set n -> next : = start.
start=n; Step 4: set start : = n.
printf(“\n inserted at front”); [end of if structure]
} step 5: stop.
n Start(t)
5 X 10 B 20 C 30 D 40 X
A B C D
n -> next = start
5 A 10 B 20 C 30 D 40 X
A B C D
Step 3: start=n
start is maintained to hold the address of first node before first node was 10 but after
insertion n is become first node so start must also point to the first node that’s why move t to the n , after that
structure will be:
5 A 10 B 20 C 30 D 40 X
n A B C D
start
Insertion at last
View at list point we want to insert the node at the last then we follow given step
step 1: create a new node n(by malloc function). and insert the information in info part
step 2: set n ->next:=NULL;
Step 3: check if (start =NULL) then,
Start = n;
otherwise
Step 2: repeat step a while (t ->next ! =NULL)
(a) set t = t ->next;// move t to next node
[end of while]
Step 3: set t ->next = n;
[end of if structure ]
step 4: stop.
void addlast(void)
{
struct node *t;
struct node *n=(struct node*)malloc(sizeof(struct node));
t=start;
printf(“\n enter the information ”);
scanf(“%d”,&n->info);
n->next=NULL;
if(start==NULL)
start=n;
else
{
while(t->next!=NULL)
t=t->next;
t->next=n;
}
}
INSERT AT MID
Node can be easily inserted in the linked list at mid also (dynamic memory allocation)
Node can be inserted by two techniques.
By node value
By node number
In this technique two nested technique also used
By node value [before node value, node][after node value ,node]
By node number [before node number, node] [after node number, node]
Generally “After Node Value” technique is preferred.
For node values & variable is used which hold the value of node after which node is inserted.
void addaftcons(void)
Algorithm: after node value new node insertion {
step 1: Create a new node n by malloc function.
int data;
insert the information in info part.
struct node *n=(struct node*) malloc(sizeof(struct node));
step 2: Read data value after which you want to
struct node *t=start;
insert the node. printf(“\n enter the information”);
Step 3: Check if (start = NULL) then,
scanf(“%d”,&n->info);
set Start : = n.
printf(“\n enter the information after which you
otherwise
want to insert ”);
Step 4: Repeat step (a) while (t!=NULL) scanf(“%d”,&data);
step a: check if(t->info=data) then,
while(t!=NULL)
stop searching/ break;
{
otherwise
if(t->info==data)
set t:=t->next; break;
[end of if structure]
else
[end of while]
t=t->next;
step 5: check If(t=NULL) then,
}
print ” not found the data ” if(t==NULL)
goto step 7.
{
[end of if structure]
printf(“\n constant not fount ”);
step 6: set n->next:=t->next.
return;
step 7: set t->next=n. }
[end of if structure]
n->next=t->next;
step 8: stop.
t->next=n;
Description printf(“\n node inserted…….”);
}
1 2 3 4 5
ptr, pointer may be used to hold intermediate addresses of node just like pointer in insertion
if start is NULL , means no node is available for delete
If start ->next = NULL means it is only a single node directly delete it with out consider first last mid
locations.
Delete from first
void delfront(void)
{ Step 1 check if (start = NULL) then,
struct node *t=start; Print ”list is empty”.
if(start==NULL) Step 2 Again check if (start ->next = NULL) then,
printf(“\n empty linked list”); free (t).
else set Start := NULL.
{ otherwise
start=start->next; set Start := start ->next.
free(t); [end of if structure]
printf(“\n node deleted from front ”); Step 4 free (t).
} Step 5 stop.
}
Description
Step 1: if start is NULL then
No node to delete
Step2: if it is single node
Directly delete it
PICTORIAL REPRESENTATION
Description
Step 1: if start is NULL then
No node to delete
Step 2: if start of next = NULL means
Free start or remove it
Step 3: otherwise
Move start to second last node
By using loop
We move last to second last because when we arrive at second last node we will directly remove
its address part node
Assign its next to NULL, so it will become the last node of linked list
Note: If we move to last node then for assigning NULL to second last node then how we will move
backward.
start
(t)
start
(t)
PTR T T->NEXT
void delfrmpos(void)
{
struct node *t=start,*ptr; Algorithm
int pos, ctr=1; Step 1: start.
printf(“\n Enter The Position Of Step 2: set pointer struct node *t=start and *ptr.
Node You Want To Delete”); Step 3: set ctr=1 and read pos.
scanf(“%d”,&pos); Step 4: check if(pos>count()) then,
if(pos>count()) Print ”invalid position”.
printf(“\n invalid position”); Otherwise
else Step 5: repeat step 6,7 while(ctr<pos)
{ Step 6: Set ptr=t.
while(ctr<pos) Step 7: set t:=t->next.
{ [end of loop]
ptr=t; Step 8: set ptr->next:=t->next.
t=t->next; Step 9: free(t).
} [end of loop]
ptr->next=t->next; Step 10: stop.
free(t);
printf(“\n node deleted…”);
}
}
Start=start->next
Then start=NULL.
LINKED LIST DELETED
void reverse(void)
{ algorithm
struct node *t=start,*start1=NULL; step 1: start.
while(start!=NULL) step 2: declare *t=start,*start1=NULL.
{ step 3: repeat step () while(start!=NULL),
t=start; step (a) set t:=start.
step (b) set start:=start->next
start=start->next;
step (c) set t->next:=start1;
t->next=start1; step (d) set satrt1=t.
start1=t; [end of loop]
} step 4: set start=start1.
start=start1; step 5: stop.
}
start
start1
start1
start1
start1
start1
ADVANTAGE
From the last node we can directly move to first node because here last node hold’s the address of first value.
So here direct movement of pointer from fast node to first node is easily possible .
INSERT AT LAST
Procedure:
void addlast(void)
{ step 1: start.
struct node *t=start; step 2: declare struct node *t.
struct node *n=(struct node *)malloc(sizeof(struct node)); step 3: set t=start.
printf(“\n enter the information ”); step 4: create a new node n by malloc function.
scanf(“%d”,&n->info); and enter the information in info part.
if (start = = NULL) step 5: check if(start=NULL) then,
{ set start=n.
start = n; set start->next=start
start->next=start; otherwise
} step 6: set n->next=start.
else step 7: repeat step (a) while(t!=NULL)
{ step (a) set t:=t->next.
n->next=start; [end of loop]
while(t->next!=start) step 8: set t->next=n.
t=t->next; [end of if structure]
t->next=n; step 9: stop.
}
}
INSERT AT MID
This concept is exact similar to the insertion singly linked because in mid three is no any difference
So same procedure can be followed
Node can be easily inserted in the linked list at mid also (dynamic memory allocation)
Node can be inserted by two techniques.
(i.) By node value
(ii.) By node number
By node value
Generally “After Node Value” technique is preferred
For node values & variable is used which hold the value of node after which node is inserted.
Algorithm: after node value new node insertion
step 1: create a new node n by malloc function. Insert the information in info part.
step 2: read data value after which you want to insert the node.
Step 3: check if (start = NULL) then,
set Start : = n;
set start->next=start
otherwise
Step 4: Repeat step (a) while (t->next!=start)
step a: check if(t->info=data) then,
stop searching/ break;
otherwise
set t:=t->next;
[end of if structure]
[end of while]
step 5: check If(t->next=start and t->info !=data) then,
print ” not found the data ”
goto step 8.
[end of if structure]
step 6: set n->next:=t->next.
step 7: set t->next=n.
[end of if structure]
step 8: stop.
Function
void addaftcons(void)
{
int data;
struct node *n=(struct node*) malloc(sizeof(struct node));
struct node *t=start;
printf(“\n enter the information”);
scanf(“%d”,&n->info);
printf(“\n enter the information after which you want to insert ”);
scanf(“%d”,&data);
while(t->next!=start)
{
if(t->info==data)
break;
else
t=t->next;
}
if(t->next==start && t->info!=data)
{
printf(“\n constant not fount ”);
return;
}
n->next=t->next;
t->next=n;
printf(“\n Node Inserted…….”);
}
Step 4: delete next node from t pointer means delete the first node.
Description:
Step1: For back ward traversals:
First of all we have to move any pointer at the last node of the linked list so we can move in
backward direction.
Here one point should consider that moves to last node not its address part because
Address part of last node is always NULL
And when we arrive at NULL not possible to move back ward.
Step 2: loop for move to the NULL of First Node back (Previous) address part.
Step 3: t = t-> back;
Statement move from previous node to current node one by one until NULL occurs.
“TECHNIQUE 2”
Previous technique 1 takes more time and require two steps.
One loop move for forward.
One loop for move backward.
Time consuming process if no. of node increases
Generally one loop must be there to traversals the data parts of nodes.
This is accomplished by technique 2
In this technique
We have to maintain a pointer that always point to last node,
Similar to cur that always point to first node.
This pointer can be named like tail, end, last etc.
So these pointers can be used to hold the address of last node of doubly linked list.
So with the help of that pointer we can directly move in backward direction with the help of pre
pointer part of a node.
Procedure:
While (t! = NULL)
{
Printf (“\n %d”, t ->info);
t = t ->back;
}
After the execution of this procedure all element will print or processed.
But last will point to the NULL, so again we have to move last pointer to the last node.
So here ptr named pointer or any norary pointer can be used to move to backward rather then
last move.
So after the execution the last till now will point to last node.
PRACTICALLY STRUCTURE OF NODE
struct list
{
int no;
Struct list * next;
Struct list * back;
};
typedef struct list dlist; // dlist ->doubly list
In this implementation two or three pointers may be used.
start = always point to first node of list.
T = performing operation helper pointer
last = always point to last node of list
Note:- various operations on doubly linked list can be performed:
With the help of last pointer
Or with out help of last pointer (memory save)
o Generally for memory saving last is not used.
o But it increase complexity, Reduce readability.
o Last pointer may be used to:
o Decrease complexity
o Increase readability of our procedures.
“Operations With Out Last Pointer”
1. INSERTION
2. DELETIONS
Both procedures are almost similar to the singly one but here in doubly we have to consider or
maintain both next or pre pointer of a node.
First node pre pointer contains NULL, because these are no any previous node it is first one.
Last nodes next pointer contain NULL, because then is no any next node, it is last one.
INSERTION IN DOUBLY LINKED LIST
Node can be inserted three different points in list
1. Insert at first
2. Insert at last
3. Insert at mid
Consider n pointer here, which points to the node which is new and which we want to insert in our linked list.
Structure or Syntax of doubly linked list:
n = (dlist*) malloc (sizeof(dlist));
n ->info = data;
n ->next = NULL;
n ->back = NULL;
Insert at first
Step 1. start.
step 2: create a new node n. void addfront(void)
step 3: check if (start = NULL) then, {
set n->info=data struct node *n=(struct nod*)malloc(sizeof(struct node));
set n->next=NULL. printf(“\n enter the information ”);
set n->back=NULL. scanf(“%d”,&n->info);
set Start = n if(start==NULL)
Step 2. otherwise {
set n->next = start; start=n;
set start->back = n; start->back=NULL;
set start=n; start->next=NULL;
[end of if] }
step 3: stop else
{
n->next=start;
start->back=n;
Description: n->back=NULL;
start=n;
}
}
Insert at last
Step 1: start.
step 2: create a new node n. by malloc and insert the information.
step 3: check if (start = NULL) then,
set n->info=data void addlast(void)
set n->next=NULL. {
set n->back=NULL. struct node *n=(struct node*)malloc(sizeof(struct node));
set Start = n printf(“\n enter the information ”);
Step 4. otherwise scanf(“%d”,&n->info);
repeat step (a) while(t->next!=NULL) if(start==NULL)
step(a) set t:=t->next. {
[end of loop] start=n;
set t->next = n; start->back=NULL;
set n->back = t; start->next=NULL;
set n->next=NULL; }
[end of if] else
step 5: stop {
while(t->next!=NULL)
Description: t=t->next;
Step1: if start is NULL then t->next=n;
Make n as initial node n->back=t;
n->next=NULL;
Start & t both point to the n node
}
Step2: otherwise
}
Move t to last node not at its address part
Step3: start ->next = n change
Now start pointing to last node connects this last node with n new node.
Procedure:
Last ->next = n;
n->back = last;
last =n;
n
n->back=last & last=n
Node can be deleted easily from mid but we have to takes case of both next & back pointer.
Node can be deleted by node number or by node value so any one technique is used.
Generally node after given value technique is used for deletion.
Procedure:
Step 1: if (start = = NULL)
Print “node to delete”
Step 2: otherwise void delmid(void)
repeat step (a) While (t!=NULL), {
step (a) check if(t->info=data) then, int data;
goto step struct node *t=start;
otherwise printf(“\n enter the data you want to delete ”);
Step 3: set t=t->next. scanf(“%d”,&data);
[end of if structure] if (start = = NULL)
printf (“\n list is empty”);
Step 4: check if t=NULL then,
else
print “constant not found”
[end if stucture]
[end of loop]
A doubly linked list in circular from is known as doubly circular linked list.
It is similar to the singly circular linked list but addresses are different here.
In out doubly linked list previous pointer of first node is NULL , and next pointer of last node
is also NULL.
We use this pointer to hold addresses rather then NULL value.
Structure:
In doubly circular linked list:
First node pre pointer hold the addresses of last node and last node next pointer hold the addresses of
first node .
Pictorial representation:
void addfront(void)
{
struct node *t=start;
struct node*n=(struct node *)malloc(sizeof(struct node));
printf(“\n enter the information ”);
scanf(“%d”,&n->info);
if(start==NULL) II logic
{ t=start->back;
start=n;
start->next=start;
n->next=t->next;
start->back=start; t->next->back=n;
} t->next=n;
else n->back=t;
{ start=n;
n->next=start;
start->back=n;
while(t->next!=start)
t=t->next;
t->next=n;
n->back=t;
start=n;
}
printf(“\n node inserted at front…..”);
}
We Provide …
Specialization in All IT Languages
C C++
DS DBMS
VB Android
Java Advance Java
Struts, Hibernate, Spring J2ME
VB.Net ASP.Net with C#
PHP Advance PHP
Sun Certified Java (SCJP) Oracle (OCP)
C++
DBMSIndustrial Training by VHS2 Pvt. Ltd.
Android
Advance Java M.Tech. Subjects Coaching
B.Tech,
J2MEIndustrial Training by VHS2 Pvt. Ltd.
BCA,with
ASP.Net MCA C#& All IT Subjects Coaching
Advance PHP
MCA Entrance
Oracle (OCP) Course with 100% Selection
VIDHYA INSTITUTE
3, Durga Nursery Road, Nr. Sukhadia House, Manglam Mall, Udaipur-313001.
Vidhya Institute of
Ph.: 0294-6451362, Information
9214465362, Technology
9251420811.
67
Ideal ‘Data Structure’
Insert at last
In a circle there is no any fast and last point.
So insertion at last is similar to the insert at first in this technique step 7 will not used.
Because cur makes node first we don’t move t then 10 nodes always first and 5 ns treat at last because they
are in circle.
And generally previous node of first node in circle is a last node.
Procedure:
Step1: check if (start = NULL) then
set Start = n;
set start->back=start
set start->next=start
Step2: otherwise
Step 3: set n->next=start.
step 4: set start->back=n.
step 5: repeat step (a) while(t->next!=start) then,
step(a) t=t->next;
step 6: set t->next=n.
step 7: set n->back=t.
[end of if]
step 8: stop.
void addlast(void)
{
struct node *t=start;
struct node*n=(struct node *)malloc(sizeof(struct node));
printf(“\n enter the information ”);
scanf(“%d”,&n->info);
if(start==NULL)
{ II logic
start=n;
start->next=start; t=start->back;
start->back=start; n->next=t->next;
}
else
t->next->back=n;
{ t->next=n;
n->next=start; n->back=t;
start->back=n;
while(t->next!=start)
t=t->next;
t->next=n;
n->back=t;
}
printf(“\n node inserted at front…..”);
}
If we see the diagram it is looking like insertion at first but cur is not moved and if we traverse it output
will be 10---20---30 40---5
It is circular so diagram of this type is possible here n is at last because Previous node of first node in a
circle is last node so n is a last node.
Now we can represent with the following diagram.
Insert at mid
Insert at mid is exact similar to as in normal doubly because at mid these is no any concept of linear or
circular.
t->next
2. PUSH 40
3. PUSH 30
4. PUSH 20
5. PUSH 10
First pop
Popped element is 10
Second pop t
Popped element is 20
Third pop
Popped element is 30
Fourth pop
Fifth pop
{
case 1:
n = (stack *) malloc (sizeof (stack));
n ->next = NULL;
printf (“\n enters value to be push”);
scanf (“%d”, & n ->no);
if (start ==NULL)
start=n;
else
{
n ->next = start;
start = n;
}
printf (“\n elements push successfully”);
break;
case 2:
if (start = = NULL)
printf (“\n stack underflow”);
else
{
printf (“\n popped element is %d”, start ->no);
t = start;
start = start ->next;
free (t);
printf (“\n element popped successfully”);
}
break;
case 3:
if (start = = NULL)
{
printf (“\n stack underflow”);
printf (“\n no. element to traverse”);
}
else
{
printf (“\n elements of stack are”);
t = start;
while (t! = NULL)
{
printf (“\n %d”, t ->no);
t = t->next;
}
/* here n is used so start does not move from its actual location*/
/*t is only temprary pointer*/
break;
case 4:
exit (0);
}// closing of switch ()
getch ();
}//closing of infinite while loop
}//closing of main () function
ENQUEUE(insertion in queue)
This operation will insert the node at last in list
DEQUEUE (deletion in queue)
This operation will remove the node from first in list because if node insert at first then it will
remove from last or
If node is inserted at last then it will remove from first.
#include<stdio.h>
#include <conio.h>
#include<process>
struct list
{
int no;
struct list * next;
};
typedef struct list queue;
void main ()
{
queue * start ,* n, *t;
int n;
t = start = n = NULL;
while (1)
{
clrscr ();
printf (“\n 1. Enqueue”);
printf (“\n 2. display”);
printf (“\n 3. exit”);
printf (“\n \t enters your choice”);
scanf (“%d”, &n);
switch (n)
{
case 1:
t = start;
n = (queue*) malloc (sizeof( queue));
n ->next = NULL;
printf (“\n enters value for enqueue”);
scanf (“%d”, & n ->info);
if (start = = NULL)
start = n;
else
{
while (t ->next! =NULL)
t = t ->next;
t ->next = n;
}
printf (“\n element queue successfully”);
break:
case 2:
t = start;
if (start = =NULL)
printf (“\n queue underflow”);
else
{
printf (“\n dequeue element is %d”, start ->no);
start = start ->next;
free (start);
start = t;
printf (“\n element dequeuesuccesfully”);
}
break;
case 3;
t=start;
if (start = =NULL)
printf (“\n queue underflow”);
else
{
printf (“\n elements of queue are”);
while (start! =NULL)
{
printf (“\n %d”, t ->no);
t = t ->next;
}
}
break;
case 4;
exit (0);
}// closing of switch
getch ();
}// closing of while loop
}//closing of main ()
ENQUEUE 10
ENQUEUE 20
ENQUEUE 30
ENQUEUE 40
ENQUEUE 50
DEQUEUE 10
DEQUEUE 20
DEQUEUE 30
DEQUEUE 40
Polynomials Representation
poly 2; 8x7-6x5+2x4-2x
Step 1: begin.
Step 2: scan the list 1 and list 2 one by one.
Step 3: compare the exponent of the list1 with exponent of the list2
(i) If one node has higher exponent than another node then add the higher
exponent node in the list3 and scan the next node in higher exponent node.
(ii) If the nodes have same exponent value then add the coefficient of both
nodes and add the result in list3 and scan the next nodes in both the lists.
Step 4. Repeat the same process until one list finished.
Step 5. Add the remaining nodes of another unfinished list in list3.
Step 6. Stop.
Polynomials Representation
struct node
{
int coef;
int expo;
struct node *next;
};
struct node *first,*sec,*new;
struct node * create(struct node *start);
void display(struct node *start);
struct node * addpoly(struct node *first,struct node *sec);
void main()
{
int num,I,choice,pos;
first=NULL,sec=NULL,new=NULL;
clrscr();
do()
{
printf(“\n 1. Create first poly”);
printf(“\n 2. display first”);
printf(“\n 3. Create second poly”);
printf(“\n 4. display second”);
printf(“\n 5. add polynomials”);
printf(“\n 6. display”);
printf(“\n 7. exit”);
printf(“\n enter the choice…..”);
scanf(“%d”,&choice);
switch(choice)
{
case 1:
first=create(first);
break;
case 2:
display(first);
break;
case 3:
sec=create(sec);
break;
case 4:
display(sec);
break;
case 5:
new=addpoly(first,sec);
break;
case 6:
display(new);
break;
case 7:
exit(0);
default: printf(“\n invalid choice…….”);
}
getch();
}while(1);
}
sec=sec->next;
}
else if(first->expo> sec->expo)
{
n->coef=first->coef;
n->expo=first->expo;
first=first->next;
}
else
{
n->coef=sec->coef;
n->expo=sec->expo;
sec=sec->next;
}
n->next=NULL;
if(third==NULL)
{
third=n;
last=n
}
else
{
last->next=n;
last=n;
}
}
while(first!=NULL)
{
n=(struct node *)malloc(sizeof(struct node));
n->coef=first->coef;
n->expo=first->expo;
n->next=NULL;
}
if(third==NULL)
{
third=n;
last=n
}
else
{
last->next=n;
last=n;
}
}
while(sec!=NULL)
{
n=(struct node *)malloc(sizeof(struct node));
n->coef=sec->coef;
n->expo=sec->expo;
n->next=NULL;
}
if(third==NULL)
{
third=n;
last=n
}
else
{
last->next=n;
last=n;
}
}
return(third);
}
Header Linked List
A header linked list always contains a special node, called the header node, at the beginning of the list. there are
following two kinds of widely used header lists…
1. A grounded list
It is a header list where the last node contains NULL pointer.
START
header node
START
header node
Representation of Polynomials:-
As we say that linked list is used to manipulate polynomials, manipulation refers to addition, subtraction
Or multiplication of polynomials
First of all how a polynomial represented using Linked list:
Any polynomial Contain:
Coefficient of base (x)
Suppose Polynomial is
5x 3 5 + 9x 2 - 7x +2
Here only x is used so structure of node:
5x3 +9x2-7x+2
5 3 9 2 -7 1 2 0 x
4x 3 y 2 +9x 2 +1 0x y - 3x +7
4 x 3 y2 9 x2 y 10 x1 y1 -3 x1 y0
7 x0 y0
4 3 2 9 2 1 10 1 1 -3 1 0 7 0 0
x
X Coeff. In this Way any type of polynomials can be represented easily.
The Structure of node will depend on polynomials.
Power of x.
So first, it must decide then it should implement.
Power of y
Some Questions
Q. 1 What is link list ? What are the advantages of link list over array ?
Q. 2 Write an algorithm to create a single linked list ?
Q. 3 Write a C program to create a singly linked list of records sorted in ascending order.
Q. 4 Suppose the names of few students of a class are as below : Pankaj, Manoj, Sohan, Ram, Payal. It is
assumed that the names of students are represented as singly linked list.
(A) Write a C Function to reach whether the name Payal is present or not.
(B)Write an algorithm to delete the name Sohan.
Q. 5 What are the various operators possible in a singly linked list ? Explain all of them with algorithm.
Q. 6 Write a C program to delete a node containing a give information in a doubly linked list.
Q. 7 Write a algorithm to insert a sorted singly linked list so that the resultant list would also be sorted.
Q.18 Write an algorithm to perform each of the following operations on singly link list :
(1) Add an element to the end of a list.
(2) Concatenate two lists.
(3) Delete the nth element from a list.
(4) Mack a second copy of a list.
Q.19 What is the difference between Static and Dynamic data structure. Give their merits and demerits. Explain
with suitable example of both.
Q,20 Write an algorithm to insert an element into a single link list.
Q.21 Write an algorithm to count the total no. of nods in Circular linked list.
Q.22 Write short notes on followings :
(A) Header linked list
(B) Implementation of linked list in memory
Q.23 Write the difference between array and linked list. Also explain the applications of linked list.
Q.24 Write an algorithm to reverse a given linked list.
Q.25 What do you mean by sparse matrices ? Explain the different ways to represent sparse matrices in memory
allocation by giving example.
Q.26 What are the advantages and disadvantages of representing queue as a linked list rather then an array ?
X X X X
#include<stdio.h>
#include<conio.h>
#include<process.h>
#include<alloc.h>
struct node
{
struct node *left;
int info;
struct node *right;
};
struct node *root=NULL;
struct node* insert(struct node *root,int data);
case 2:
if(root==NULL)
printf("\n underflow");
else
inorder(root);
break;
case 3:
if(root==NULL)
printf("\n underflow");
else
preorder(root);
break;
case 4:
if(root==NULL)
printf("\n underflow");
else
postorder(root);
break;
case 5:
printf("\nEnter the data you want to delete ");
scanf("%d",&data);
del(data);
break;
case 6: exit(0);
}
getch();
}
}
{
root=(struct node*)malloc(sizeof(struct node));
root->info=data;
root->left=NULL; ALGORITHM
root->right=NULL; STEP 1 : START.
} Step 2: check if root= NULL then,
else Assign memory to root block and
{ Set root->info:=data.
if(data<root->info) Set root->left=NULL
root->left=insert(root->left,data); Set root ->right=NULL
else Otherwise
root->right=insert(root->right,data); Step 3: check if (data<root->info) then,
} Call root->left=insert(root->left,data)
return(root); Otherwise
} Call root->right=insert(root->right,data)
( (End of if)
Step 4 stop.
void inorder(struct node *root)
{
if(root!=NULL) Step 1: function inorder(root)
{ Step 2: check if (root!=NULL) then,
inorder(root->left); Call inorder(root-.left);
printf(" %d",root->info); Print root->info
inorder(root->right); Call inorder root-.right.
} [end of if]
} Step 3: Stop.
}
else if(root->right==NULL && root->left!=NULL)
{
root=t->left;
free(t);
} Step 1: start.
else if(root->right==NULL && root->left==NULL) Step 2: check if root!=NULL then,
{ Print “empty tree.”.
free(t); Step 3: check if root->info=data then,
Step (a): check if(root->right!=NULL
root=NULL;
AND root->left=NULL) then,
} Set root=t->right.
} Set free(t).
else Step (b):again check if(root->right=NULL
{ AND root->left!=NULL) then,
while(t->info!=data && t!=NULL) Set root=t->left.
{ Set free(t)
ptr=t; Step (c):again check if(root->right=NULL
if(data<t->info) AND root->left=NULL) then,
Set root=NULL.
t=t->left;
Set free(t)
else Otherwise
t=t->right; Step 4 : repeat step(5,6) while(t->info!=data AND
} t!=NULL)
if(t==NULL) Step 5: set ptr:=t.
{ Step 6: check if data<t->info then,
printf("\n data not found...."); Set t:=t->left.
return; Else
} Set t:=t->right.
[end of if]
if(t->left==NULL && t->right==NULL)
[end of loop]
{ Step 7: check if t=NULL then,
if(data <t->info) Print”data not found”.
ptr->left=NULL; Return.
else Step 8: check if(t->left=NULL AND t->right=NULL) then,
ptr->right=NULL; Step 9 check if data<t->info then
free(t); Set ptr->left:=NULL.
} Else
else if(t->left==NULL && t->right!=NULL) Set ptr->right=NULL.
[End of if]
{
Free node t.
if(data <t->info) Step 10: check if(t->left=NULL AND t->right!=NULL) then,
ptr->left=t->right; Step 11:check if data<t->info then
else Set ptr->left:=t->right.
ptr->right=t->right; Else
free(t); Set ptr->right=t->right.
} [End of if]
else if(t->left!=NULL && t->right==NULL) Free node t.
{ Step 12: check if(t->left!=NULL AND t->right==NULL) then,
Step 13:check if data<t->info then
if(data <t->info)
Set ptr->left:= t-> left
ptr->left=t->left; Else
else Set ptr->right= t-> left
ptr->right=t->left; [End of if]
free(t); Free node t.
} Step 14: check if(t->left!=NULL AND t->right!=NULL) then,
else if(t->left!=NULL && t->right!=NULL) Set temp:= t->right
{ Repeat step(a) while(temp->left!=NULL),
temp=t->right; Step (a) set temp:=temp->left.
[end of loop]
while(temp->left!=NULL)
Set save:=temp->info.
temp=temp->left; Call del(temp->info).
save=temp->info; Set t->info:=save.
del(temp->info); [End of if]
t->info=save;
}
}
}
Vidhya Institute of Information Technology
109
Ideal ‘Data Structure’
Without Recursion
void add(void)
{
int data;
struct node *t=root,*ptr;
struct node *n=(struct node*)malloc(sizeof(struct node));
printf("\n Enter the information ");
scanf("%d",&data);
n->left=NULL;
n->right=NULL; Step 1: start.
n->info=data; Step 2: set struct node *t=root.
if(root==NULL) Step 3: create a new node n and read information in data..
{ Step 4: set n->left=NULL, n->right=NULL,n->info=data
root=n; Step 5: check if (root= NULL) then,
} Set root:=n.
else Otherwise
{ Repeat step while(t!=NULL AND t->info!=data)
while(t!=NULL && t->info!=data) Set ptr:=t.
{ Check if data<t->info then,
ptr=t; Set t:=t->left.
if(data<t->info) Otherwise
t=t->left; Set t:=t->right.
else [end of if ]
t=t->right; [end of loop]
} Step 6: check if t->info=data then,
if(t->info==data) Print “already present”
{ return
printf("\n already present "); End if
return; Step 7: check if (data < ptr-> info) then,
} Set ptr->left=n.
if(data<ptr->info) Otherwise
ptr->left=n; Set ptr->right=n.
else End if
ptr->right=n; Step 8: stop.
printf("\n node inserted.....");
}
}
struct tree
{
int no;
struct tree *left;
struct tree *right;
};
typedef struct tree stree;
stree * insert (stree *root,int n);
void inorder(stree *root);
void preorder(stree *root);
void postorder(stree *root);
void mirror(stree *root);
int height(stree*);
int enode(stree*);
int inode(stree*);
int total(stree*);
stree* min(stree*);
stree* max(stree*);
void main()
{
int t;
stree *root=NULL,*temp;
int n;
while(1)
{
clrscr();
printf("\n1. Insert Node");
printf("\n2. Inorder");
printf("\n3. Preorder");
printf("\n4. Postorder");
printf("\n5. Total Nodes");
printf("\n6. External Node");
printf("\n7. Internal Node");
printf("\n8. Height");
printf("\n9. Minimum");
printf("\n10. Maximum");
printf("\n11. Mirror");
printf("\n12. Exit");
printf("\n\n\t\t\tEnter Your Choice.....");
scanf("%d",&n);
switch(n)
{
case 1:
printf("\nEnter Value For Insertion : ");
scanf("%d",&n);
root=insert(root,n);
printf("\nNode Inserted Successfully");
break;
case 2:
if(root==NULL)
printf("\nTree Is Empty");
else
{
printf("\nInorder Traversal Of Tree Is \n");
inorder(root);
}
break;
case 3:
if(root==NULL)
printf("\nTree Is Empty");
else
{
printf("\nPreorder Traversal Of Tree Is \n");
preorder(root);
}
break;
case 4:
if(root==NULL)
printf("\nTree Is Empty");
else
{
printf("\nPostorder Traversal Of Tree Is \n");
postorder(root);
}
break;
case 5:
if(root==NULL)
printf("\nTree Is Empty");
else
{
t=total(root);
printf("\nTotal Nodes in Tree Is %d",t);
}
break;
case 6:
if(root==NULL)
printf("\nTree Is Empty");
else
{
t=enode(root);
printf("\nTotal External Nodes are %d",t);
}
break;
case 7:
if(root==NULL)
printf("\nTree Is Empty");
else
{
t=total(root)-enode(root);
printf("\nTotal Internal Nodes are %d",t);
}
break;
case 8:
if(root==NULL)
printf("\nTree Is Empty");
else
printf("\nHeight of Tree Is %d",height(root));
break;
case 10:
if(root==NULL)
printf("\nTree Is Empty");
else
{
temp=max(root);
printf("\nMaximum Value of tree Is : %d",temp->no);
}
break;
case 9:
if(root==NULL)
printf("\nTree Is Empty");
else
{
temp=min(root);
printf("\nMinimum Value of tree Is : %d",temp->no);
}
break;
case 11:
if(root==NULL)
printf("\nTree Is Empty");
else
{
mirror(root);
printf("\nTree has Mirror");
}
break;
case 12:
exit(0);
}
getch();
}
}
void inorder(stree *root)
{
if(root!=NULL)
{
inorder(root->left);
printf("\n%d",root->no);
inorder(root->right);
}
}
void preorder(stree *root)
{
if(root!=NULL)
{
printf("\n%d",root->no);
preorder(root->left);
preorder(root->right);
}
}
void postorder(stree *root)
{
if(root!=NULL)
{
postorder(root->left);
postorder(root->right);
printf("\n%d",root->no);
}
}
void mirror(stree *root)
{
stree *temp;
if(root!=NULL)
{
mirror(root->left);
mirror(root->right);
temp=root->left;
root->left=root->right;
root->right=temp;
}
}
int height(stree *root)
{
int lh,rh;
if(root==NULL)
return 0;
else
{
lh=height(root->left);
rh=height(root->right);
if(lh>rh)
return ++lh;
else
return ++rh;
}
}
int total(stree *root)
{
if(root==NULL)
return 0;
else
return total(root->left)+total(root->right)+1;
}
int enode(stree *root)
{
if(root==NULL)
return 0;
else if(root->left==NULL && root->right==NULL)
return 1;
else
return enode(root->left)+enode(root->right);
}
int inode(stree *root)
{
return 0;
}
stree* max(stree *root)
{
if(root==NULL || root->right==NULL)
return root;
else
max(root->right);
}
stree* min(stree *root)
{
if(root==NULL || root->left==NULL)
return root;
else
max(root->left);
}
Stree* insert (stree *root,int n)
{
if( (root)==NULL)
{
(root)=(stree*)malloc(sizeof(stree));
(root)->no=n;
(root)->left=(root)->right=NULL;
}
else if( (root)->no > n)
insert( root->left,n);
else
insert( root->right,n); }
AVL TREE
GENERAL TREE
B-TREE
B-TREE
Tries
B+- TREE
GRAPH
graph is a non-linear data structure.
A random structure.
No any fixed structure.
Non hierarchical data structure.
Basically used to represent relationship between or among pair of elements.
Definition
Graph G is a set (V, E) where V represent set of elements called “Vertices” and E represent edges
between these vertices.
Graph is a collection of connected nodes in any order called Vertices and there vertices connected by
Edges.
So G= (V, E)
Example of graph:-
1. 2.
e1 V1
V1 V2
e1 e2
e5 e6
e4 e2 e4 e5
V5
e7 e8
V2 V3
V3 e3 V4
e3
Details of Graph 1.
G = (V, E)
V = {V1, V2, V3, V4, V5,}
E = {e1, e2, e3, e4, e5, e6, e7, e8}
Graph Terminology
Vertex: - Node of Graph (G), represented by V.
Adjacent node
Isolated vertex
A vertex which is not belongs to any edge is known as Isolated Vertex.
Isolated vertex is not connected in a graph.
deg (isolated vertex) = 0 (always)
Source
A source is a special type of vertex of a graph, which has only outgoing edges, no any
incoming edges.
Means
v is a source if 2
indeg (v) = 0
outdeg (v) > 0
Sink
It is also a special type of vertex of a graph, which has only indegree or incoming edges;
it has no any outgoing edges.
Means
v is a sink.
if outdeg (v) = 0
indeg (v) >0
Parallel Edges
Any two distinct edges e1 and e2 are called parallel edges if they connect equal
neighbours or Adjacent Nodes.
Means
e1 and e2 are parallel edges.
if e1 = (A, B)
e2 = (A, B)
e1 and e2 both have same vertices A & B as an Adjacent Vertex.
Path
Path refers to way or route between any two vertex if it exists.
“Path may be directed or undirected”
Directed Path
If any one edge exist between any two vertex.
Undirected path
If more than one edge exists between any two vertex.
Reachability
A vertex v is said to be reachable from u if there exists a path from vertex u to vertex v.
Cycle
A cycle is a closed simple path between any two vertex.
Number of vertex within any path is known as length of a path.
So a cycle is a closed simple path with length 2 or more. A cycle of length k is known as
k-cycle.
Weight
When any non negative value assigned to the edge, it is called Weight of Edge.
Weight also represent the cost of moving between two vertex or distance between two
vertex.
Types of graph
Several types of graph are here, they are divided in categories because of their structure or organization of vertex in
a graph.
Directed Graph
e6 e3
e8
e1 e7 V5
e4
V3 V4
e5
Weighted Graph
8 E 9
Mixed Graph
e2
A B
A graph which have some edges are directed and some are e3
e1
undirected is called mixed graph, means when a graph is
directed also and undirected also is referred as mixed graph.
e1, e2, e3, e4, e5 are directed edges. C e6 e7 D
e6, e7 are undirected edges.
= “Mixed Graph”
e5 e4
E
Loop Graph
e5
Multiple edges can be there for creating loop for same vertex.
Also called Circular Graph. e1
A loop graph is a graph which has an edge whose adjacent vertex A B
are identical or same. A loop graph is a graph which has at least
one edge whose source and destination vertex are equal.Means e1 e4 e2
= (v, u) e2 = (u, u)
A graph which contains such type of edges is called loop graph.
Example: C D
e1 =(A, B), e2 = (B, D), e3 = (D, C), e4 = (A,C) e3 e6
e5 = (A, A) e6 = (D,D) }
These edges are called “slink”
“loop graph edges”
Vidhya Institute of Information Technology
138
Ideal ‘Data Structure’
NULL graph
e1
When a graph contains parallel edges, is called Multigraph. A E
Means, when in a graph, two or more than two edges are used to e5
join two vertices is called Parallel Edges and graph is called e4 e2 B e3 e6 e7
Multigraph.
C e8 F
e9 e1
D 1
GRAPH REPRESENTATION e1
Graph can be represented in memory in two forms, according to requirement as convenience
0 it can be used.
1 SEQUENTIAL REPRESENTATION
2 LINKED LIST REPRESENTATION
SEQUENTIAL REPRESENTATION
Sequentially graph can be represented in two ways:
Adjacency matrix
Incidency matrix
This representation use concept of array means array is used to represent the graph.
This type of matrix contains only either 0 or 1. So these are known as BIT matrix or BOOLEAN matrix.
Adjacency matrix does not consider the order or organization of vertex in a graph.
So any type of order of vertex can be used in matrix but every order result different - different types of matrix.
If (G) graph is undirected then the adjacency matrix of G will Symmetric [Aij = Aji]
e1
A B
e5 e6
is a symmetric matrix.
e1
A B
e6
e5
E e8 e2
e7
e4
C D
e3
10 20
30
40 50
60
10 20 40 50 x
20 10 40 50 30 x
30 20 50 x
40 10 60 20 x
50 10 20 30 60 x
60 40 50 x
60
10 20 50 x
30 50 x
20
50 x
30
60 10 20 x
40
60 x
50
X
60
30
40 50
Representation: 60
10 20 40 50 x
20 10 40 50 30 x
30 20 50 x
40 10 60 20 x
50 10 20 30 60 x
X 60 40 50 x
0
Above representation is better than as before because above one is dynamic, if number of nodes increases
then array cannot expand but in linked list representation a new node can easily be inserted for a vertex.
2
40 50
Value of Weight Link to
7 5 Vertex [Data Part] next vertex
60 [Data Part] [Address Part]
Representation
1 20 4 40 9 50 7
0 x
2 10 4 40 6 50 2 30 3
0 x
3 20 3 50 2
0 x
4 10 9 60 7 20 6
0 x
5 10 7 20 2 30 2 60 5
0 x
X 6 40 7 50 5
0 x
Practically implemented structure of above list:
Two structures are required for:
Doubly Singly
struct dlist struct slist
{ {
int no; int no;
struct dlist * next list; int weight;
struct dlist * next vertex; struct list * next;
}; };
5 A
4 3 5
B 1 6 C
7 2 4
9
D 4 4
E F G
3
3
7
6
A C 3 E 1 F 6
x
B D 7 A 4 B 5
X
C G 4 C 5
x
D H 6 E 4
X
E F 3
X
F E 3 C 9
X
G H 7 F 4
x
X H E 3 F 3
x
In form of general list:-
A C, E, F
B D, A, B
C G, C
E F
F E, C
G H, F
H E, F
(Weight may be considered in brackets with outdegree)
5 A
4 3 5
A C 3 E 2 F 6 x B 6 C
1
7 2 4
9
B D 7 A 4 B 5
D 4 F 4
X E G
3
C G 4 C 5 x 3
7
6
D H 6 E 4
X H
E F 3
X General List with Weight
F E 3 C 9
X A C(3), E(2), F(6)
B D(7), A(4), B(5)
G H 7 F 4 x C G(4), C(5)
E F(3)
H E 3 F 3 x F E(3), C(9)
G H(7), F(4)
H E(2), F(3)
e9
A
e1 e2
B C
e3 e4 e5
e6
D E
e7 e8 F
e10
Representation
A X
B X
C X
D X
E X
X F X
Graph Traversals
There are two types of traversals.
BFS [Breadth First Search]
DFS [Depth First Search]
Basically these are searching technique not traversal.
In graph there is no any main node.
We have to consider any node as a source node.
So with the help of this source node remaining nodes are traversed.
And it is not always possible that all nodes are approachable by source vertex.
For any type of traversals either stack or queue structures are required.
For performing traversals on graph, three different status of vertex used which define various condition of a
vertex during traversals.
To find out the MST of a graph, two type of algorithm can be used.
Kruskal’s Algorithm
Prims Algorithm
Both type of algorithm can be used
Output is always same, means both will create same tree.
Technique of these algo is different.
KRUSKAL’S ALGORITHM
This algo is used to find out the MST.
Algo:-
Step1: Write the pair of all adjacent vertexes with their weight.
Steps 2: Arrange these all pairs in ascending order according to their weight.
Steps 3: Connect these vertex pair one by one in order but cycle does not create.
Step 4: If any vertex pair creates a cycle ignore it move to next pair.
Step 5: Repeat steps 3 until all pair has processed.
Step 6: Finally it will be MST.
2
Step 7: Exit A B
4
For example: 3 6
7 G 2 F
1 4
2
C D
5
6 1
CG->1
DB->2
DG->4
DF->2
DE->1
BG->6
BF->4
STEP 2: arrange them in ascending order by weight.
CG->1
DE->1
DF->2
DB->2
AB->2
AG->3
DG->4
BF->4
CD->5
CE->6
BG->6
AC->7
STEP 3: connect these pair one by one but cycle not occur
CG->1 DE->1
G G
1 1
C C
D
1
DF-> 2 DB-> 2
G B
1
F
C 2 G
1 2 F
2
D C
1
D
1
E
E
AB->2 AG->3
2 2
A B A B
G
3 2
2 F G F
G
1 2 1 2
C C
D D
1 1
E E
Dg-> 4, BF-> 4, CD-> 5, CE-> 6, BG-> 6, AC-> 7, not connected because they create cycle and MST can not
have cycle in any case.
C
D
1
PRIM’S ALGORITHM
This algo is used to find out the MST by given weighted graph G.
Algo
Step 1: Take any vertex as a source vertex A of group G.
Step 2: Write its all adjacent vertex with their weight.
Step 3: Write ∞ for remaining vertex which are not adjacent of A.
Step 4: Finds the adjacent vertex N whose weight is minimum or lowest.
Step 5: Connect this vertex N with A but cycle does not occur in any case and ignore remaining vertex
Step 6: Repeat step 2 by making N as A [source vertex] until all vertex connect in MST and once connected vertex
must not occur again.
Step 7: Exit
For eg:-
2
A B
2
1 3 1
1
5
F G E C
2 2 1 1
2
H I D
1
Path matrix
When we create the adjacency matrix for a graph (G), then it shows only direct path
between vertices
But it may be possible that any undirected path may be these between any two vertices.
Such type of matrix which displays the direct & undirect path between any two vertices
is called path matrix.
Number of different - different algos is these to find out the path matrix.
1. General Algo
2. Warshall Algo
General Algo
Step 1: Create a adjacency matrix (A) of given graph (G)
Step 2: Create or find out matrix
pm = A1 +A2 +A3------------+An
[Here m = no of vertices]
Step 3: Replace the non-zero entry of pm with 1 and other is already zero.
Step 4: Create new P matrix with logic of step 3.
[Now this P is path matrix]
e3
Step 5: Exit. A D
e4 e5
For eg:- graph(G) e2 e6
e1
Now here B
e7
C
Adjacency matrix (A)=
pm = A+A2+A3+A4 A=
A2 = A X A =
A3 = A 2 X A =
A4 = A 3 X A =
Now pm = A+A2+A3+A4
Warshall algorithm
Previous algo is a very complex algo.
Because if number of node increases, then m time matrix has to multiplied so it become complex.
Warshall provide an easy way to find out path matrix.
In this algo, first of all direct path matrix (P) has to create with help of adjacency matrix (A).
Pij contain all elements with zero where Aij = 0 otherwise Pij = 1
Algo:
Algo Contain
1 A weighted graph G
2 M nodes
3 W weight matrix
4 Q matrix: -
Q[I,j] is the length of shortest path from node vi to vj
5 Infinity: is a very large number.
used initially in Q where no any path between vi & vj
6 MIN: It is a function which returns minimum value which is used to find short path.
Basically our goal is to replace this all infinity with shorted path weight value
DIJKASTRA ALGO
Step 1: Repeat for i = 1, 2---------m
if w [i, j] = 0, then
set q [i, j] = infinity
else
set q [i, j] = w [i, j]
end if
end of loop
SEARCHING
Our computer system can store large amount of data of different – different types as in
form of files
And if there is any need to retrieve them again, then there is a requirement to search the
required data. So at that time the concept of searching comes into existence.
Searching is a process of finding the element, that either it is available is structure or not
Searching is one of the basic technique to also find the location of an element in any
structure if it is available in it.
Searching is one of the most basic operation and important operation of “data structure”
or any “data organization “
Generally every data structure requires searching.
Always fast searching is preferred.
Searching may be a very “time consuming process” and time complexity increases if
number of elements in structure exceed.
While using searching technique, three different types of cases considered.
(A) BEST CASE: - It is a case, where element found at first location or in first
comparison or almost at starting locations in data structure:
“It is preferred case”
(B) AVERAGE CASE: - It is a case, where element found at mid location or almost at
mid location, that is average case.
(C) WORST CASE: - It is a case, where element found at last location, or almost last
locations of data structure that is worst case.
Last level of worst case is that element not found in data structure.
“It is not preferred case”
Selection of case is not in our hand. It depends on the structure’s type or element in the
structure.
“Linear Search”
Linear search is also known as:
Sequential Search
One by one Search
Step by step Search
Concept: -
In the linear search technique given element is compared with the every element
of the structure one by one as name implies.
When element is given, then this element is composed with every location of available
structure in linear form, and when element is found then according to requirement searching
stop here.
The element is search is linear form or search sequentially that’s why it is called as Linear or
Sequential Search.
“Suppose there are n elements”.
The process of linear search is similar to that if you want to find the locations of your
known person in any line or queue.
Technical Concept
Suppose there is structure a with n element.
You want to search k element & its location in a then,
Compare every element of a with k
if found then
stop searching
otherwise
Check or compare all n elements.
So a[i] compare with K
where I =1, 2-----------upto n
void main()
{
int a[max],n,i,k flag =0;
clrscr();
printf(“\nenter how many element :-”);
scanf(“%d”&n);
if (n> max)
{
printf(“\n input size is greater than the declared size”);
getch();
exit(0);
}
printf(“\n enter %d element in array ”,n);
BINARY SEARCH
It is a most advance form of linear search.
It is based on “divide & conquer” technique.
It is discovered to reduce the time in searching.
This technique is similar to search any word in English dictionary.
One condition is that all elements must be stored in any order either Ascending or
Descending.
If elements are not arranged in order, this technique becomes fail.
As we say that it is based on Divide & Conquer technique, means:
o In this technique entire structure is divide in two halves (part)
o Then required operation (searching) is performed by selecting appropriate value.
500
For eg
Suppose we have 10 elements stored in structure a in ascending order and we want to
locate 25 in this structure.
10 elements are:
Location 1 2 3 4 5 6 7 8 9 10
10 18 25 34 57 62 69 72 85 90
Here l=1, u=10, mid 5 (integer part because decimal locations is not possible in any structure)
k=25; element location, which we want to search.
Step1: Check k not available at a [mid]
a[mid] =57
k=25 (not)
divide structure in two parts.
18 25 (false)
Again make two part
Because if they cross each other, then they move in this direction then directions (value)
are already searched and it will also become infinite.
So when ever l<=u, comparison will done or continue.
------------------u ----- l------------
l-------------- ---------------u
Practical Implementation of Binary Search
#include<conio.h>
#include<stdio.h>
#include<process.h>
#define max 10
void main ()
{
int a[max] k,i,l,mid,u,n;
clrscr();
printf(“\n enter how many element:-”);
scanf(“%d”&n);
if (n>max)
{
printf (“\n size out of array-:”);
getch();
exit(0);
}
printf(“/n enter %d sorted elements in array:n”);
for(i=0;i<n;i++)
{
printf(“\n enter element:-”);
scanf(“%d”&a[i]);
}
clrscr();
printf(“\n enter element which you want to search:-”);
scanf(“%d”&k);
/* logic of binary search*/
l=0;
u=n-1;
mid=(l+u)/2;
while (a[mid]!=k && l<=u)
{
if (a[mid]>k)
u= mid -1; // move to left array
if (a[mid]<k)
l=mid+1;// move to right array.
mid =(l+u)/2; // again two part with new bound
}
if (a[mid]= = k)
printf(“\n %d element found at [%d] location,” k,mid);
else
printf(“/n %d element not found ” k);
getch();
}
SORTING
Sorting is one of the most important types of operation of data structure of any type.
Sorting is a process of arranging the element of structure in any logical order. This order
either can be Ascending or Descending.
Sorting make searching so fast.
For example:-
We can easily search any word of English in dictionary because all words are arranged in
ascending order.
Similar to that, to improve the searching or efficiency of our structure, we use the
concept of sorting.
Binary search is much better than linear search, because linear search is time consuming
process but if we prefer binary search, condition of binary search is that all elements
must be either in ascending to descending order otherwise binary search is not possible.
So to arrange the elements of a structure in any order, the concept of sorting is used.
1. External Sorting
This is process of arranging the elements or data which are stored in data files
(permanent storage).
This sorting is done when there is a large amount of data is available.
This sorting is used with the data which are available in auxiliary memory such as hard
disk, floppy disk or permanent storage.
Example are :>
Merge sort
Radix sort
2 . Internel Sorting: -
This is a process of arranging the elements or data which are stored in computer’s main
memory (temporary files)
This sorting is done when low amount of data is available.
When one pass complete, and then in second pass, last element will not be compared.
Because it is already sorted.
If there are n elements in the structure then n-1 pass will occur, because in the last n
pass, already smallest element will be at top(0) so no need to compare with it to all again.
Means every jth element of an array will be compared with j+1th element, if greater, than
both will be swapped.
a j compare with a j+1 with greater condition.
if (a[j]>a [j+1])
Then aj swapped with aj+1
t=a[j]
a[j] =a[j+1]
a[j+1] = t
Internal steps where n(total element) = 5
BUBBLE SORT
One of the most general types of sorting is bubble sort.
Concept of bubble sort
Every element of the structure compared with its next element.
If it is greater, then swap this with its next one.
This process will continue until every element is compared with its next one.
When all elements are compared with its next then this is known as “Pass”.
When one pass complete, the largest element is arranged at last position (ascending).
With another pass that is second pass, the second largest element will be stored at
second last position.
And so on.
Example: -
Suppose following numbers are stored in array a.
23, 99, 87, 58, 66, 32, 11
Sorting of array a in ascending order by bubble sort technique:
Here n=7 (total elements of a)
pass 1 :
23 23 23 23 23 23 23
99 99 87 87 87 87 87
87 87 99 58 58 58 58
58 58 58 99 66 66 66
66 66 66 66 99 32 32
32 32 32 32 32 99 11
11 11 11 11 11 11 99
After one pass largest 99 will be at last position, no need to check it again.
So on the next pass checking or comparison loop will run but less one
Pass 2:
23 23 23 23 23 23
87 87 58 58 58 58
58 58 87 66 66 66
66 66 66 87 32 32
32 32 32 32 87 11
11 11 11 11 11 [87]
[99] [99] [99] [99] [99 ] [99]
After second pass second largest (87) will be at second largest position.
So in the next pass comparison, loop will run but less two, because two elements have
sorted.
Pass 3: -
23 23 23 23 23
58 58 58 58 58
66 66 66 32 32
32 32 32 66 11
11 11 11 11 [66]
[87] [87] [87] [87] [87]
[99] [99] [99] [99] [99]
After pass 3, third largest (66) arrange at third last position.
So in the next pass total comparison will less three
Pass 4:
23 23 23 23
58 58 32 32
32 32 58 11
11 11 11 [58]
[66] [66] [66] [66]
[87] [87] [87] [87]
[99] [99] [99] [99]
Pass 5:
23 23 23
32 32 11
11 11 [32]
[58] [58] [58]
[66] [66] [66]
[87] [87] [87]
[99] [99] [99]
Pass 6:
(n-1) pass Final array is:
[23] 11
[11] [23] [11]
[58] [32] [23]
[58] [58] [32]
[66] [66] [58]
[87] [87] [66]
[99] [99] [87]
[99]
After every pass the largest element will be placed in nth position.
The next largest element will be placed at (n-1), (n-2)…………2 respectively.
SELECTION SORT
Another and again simplest of sorting is a selection sort.
If ith position element is greater than smallest then they are swapped with each other
otherwise, no swapping will occur.
(Saving of time)
Example -:
Suppose we have following element with in array a:
78 34 45 12 89 23
Pass1:
78 34 45 12 89 23
i=0
a[i] = 78 compare with smallest between a+1 to n
min=> 12
location of 12 =3, that is loc = 3
if (a[i] >min )
{
t=a[i];
a[i] = a[loc];
a[loc] =t;
}
[12 ] 34 45 78 89 23
Pass 2:
(12) 34 45 78 89 (23)
Pass 3:
Pass 4:
Pass 5:
Now by seeing the above passes we can establish the following relations:
Total pass = n-1
Where n = total elements of an array
Total passes = i=0 to n-1>
Smallest element selection range
start = i+1
end = 1
loc hold the location of smallest element among remaining element
Initially loc contain pass value
If loc not equal to I then swap the values of a loc and a [i] because if both are equal then
no mean of swapping.
void main()
{
int a[10] , I,j,loc, small, t,n;
clrscr();
printf(“/n enter the how many element -: ”);
scanf(“%d”,&n);
if (n>10)
{
printf(“/n size out of array”);
getch();
exit(0);
}
printf(“/n enter total element in array ”a);
for (i=0; i<n; i++)
{
printf(“/n enter %d element-:”);
scanf(“%d”, &a[i]);
}
clrscr();
printf(“/n element before sorting are -”);
for (i=0; i<n; i++)
{
printf(“/n%d”, a[i]);
}
/* selection another sort logic */
for (i=0; i<n-1;i++)
{
loc =I;
min = a[i];
for (j=i+1; j<=n-1;j++)
{
if (a[j]< min)
{
min = a[j];
loc =j;
}
}
if (loc !=i)
{
t=a[i];
a[i] = a[loc];
a[loc] = t;
}
}
printf(“/n elements after sorting are ”);
for (i=0; i<n; i++)
printf(“/n %d”, a[i]);
getch();
}
Insertion Sort
It is a special type of sorting.
“In this technique, we pick a particular value y and then insert or place it at the
appropriate place in the structure”.
Here every element of the structure is compared with all its previous elements.
If previous element is greater than y then this element is moved to its next location.
(Here we use concept of array, so copy will move to next location, actual location will
not become (empty)
This process is continued for last element, means when last element is compared with all
its previous elements then sorting will complete.
Here every pass will be checked with all previous elements.
If there are n elements then (n-1) pass will be performed.
After (n-1) passes, the array or structure will become sorted.
Every ith location element is compared with all previous i-1 location until I become 0.
If previous one is small then no element is moved, otherwise ith element will move to
i+1 location, so we can make a room or place for this ith element with in a structure.
“We insert the element at particular location which we have select, so this technique is
called Insertion Sort”.
a[0] compare with no comparison
because this location has no previous elements.
a[1] compare with a[0]
a[2] compare with a[1], a[0]
a[3] compare with a[0], a[1], a[2]
a [4] compare with a[0], a[1], a[2], a[3]
For example [Square brackets [ ] represent element which is being compared round
brackets represent Y]
77 33 11 44 88 99 55 22
Pass 1 :
Selected element is y =33, because 77 has no previous element
y=33
[77] (33) 11 44 88 99 55 22
“77 will move to next location” (33 location)
77 77 11 44 88 99 55 22
All element has been tested then 33 is placed at first location
33 77 11 44 88 99 55 22
In this way all pass will occur.
Pass 2:
33 77 (11) 44 88 99 55 22
y=11
33 [77] (11) 44 88 99 55 22
[33] 77 11 44 88 99 55 22
33 77 11 44 88 99 55 22
Now finally
11 34 77 44 88 99 55 22
Pass 3:
11 33 77 (44) 88 99 55 22
11 33 77 44 88 99 55 22
y=44 11 33 77 44 88 99 55 22
y =44 11 33 77 44 88 99 55 22
y=44 11 33 33 77 88 99 55 22
No shifting
Finally
11 33 44 77 88 99 55 22
Pass 4:
11 33 44 77 88 99 55 22
11 33 44 77 (88) 99 55 22
y=88 11 33 44 77 88 99 55 22
11 33 44 77 88 99 55 22
Here 88 is already greater than with its previous element(77) then it will not be
moved and no further comparison will occur.
Because we are at (88) by sorting its entire previous element. So no need to
compare, even if we compare then no any element will moved.
Pass 5:
11 33 44 77 88 (99) 55 22
y=99 11 33 44 77 88 99 55 22
Same as pass 4 no need to move
Pass 6:
11 33 44 77 88 99 55 22
y=55 11 33 44 77 88 99 55 22
y=55 11 33 44 77 88 (99) 99 22
y=55 11 33 44 77 88 88 99 22
y=55 11 33 44 77 77 88 99 22
No movement
So
11 33 44 77 88 99 55 22
That is final array of pass 5, which use for pass 6.
Pass 7:
11 33 55 77 88 99 (22)
y=22 11 33 55 77 88 99 22
y=22 11 33 55 77 88 99 99
y=22 11 33 55 77 88 88 99
y=22 11 33 55 77 77 88 99
y=22 11 33 55 55 77 88 99
y=22 11 33 33 55 77 88 99
No movement (place y at compared +1 location)
y=22 11 22 33 55 77 88 99
Now array= 11 22 33 55 77 88 99
for (i=0;i<n;i++)
printf(“/n%d”,a[i]);
getch();
/* logic for insertion sort */
for (k=1; k<n;k++)
{
y=a[k];
for (i=k-1; i>=0 &&y<a[i]; i++)
{
a[i+1] =a[i];
}
a[i+1] =y;
}
printf(“/n elements after sorting are ”);
for (i=0; i<n;i++)
printf(“/n %d”, a[i]);
getch();
}
Note: -
The following logic can also be used for following condition for insertion sort.
Output & working of both logic is same.
/* Another logic of insertion sort */
for(k=1;k<n;k++)
{
y=a[k];
i=k-1;
while ((i>=0) && (y<a[i]))
{
a[i+1] = a[i]
i--;
}
a[i+1]=y;
}
SHELL SORT
This type of sorting is one of the most advance forms of bubble sort.
Logic: - This type of sorting makes multiple passes of array and each time sort the number
which are at equal distance (d).
This technique is similar to bubble sort that it also check every element but not with its next
element.
In this sort every element is compared with the element which is sorted at fixed location d,
and after that again next element is compared with the element which is stored at same dth
location.
This location d also varies with every element which you are comparing with.
Suppose there are n elements in the data structure.
Every element of this structure will compare with d distance element where
d=mid location of structure [d=n/2]
In next pass, again every element compare with its d distance element but now d will be round
half of previous d that is [d=d/2.0+0.5].
This entire process continues until d become 1.
During comparison, if d location element is smaller than ith location element, then swapping
will be performed.
Means every ith location element is compared with (i+d)th location element and if (i+d)th
element is smaller, then both will interchange to each other.
After that d become d/2.
Again same process will be continued until d become 1
if (a[i]>a[i+d])
{
t=a[i]
a[i]=a[i+d];
a[i+d]=t;
}
Suppose n=6 then d=n/2 =3
In pass 1
a[0] compare with a[3]
a[3] compare with a[6]
For eg:- An array contains 7 elements in following order:
12 9 -10 22 2 35 40
Pass 1:
12 12 12 12 12
9 9 2 2 2
-10 -10 -10 -10 -10
22 22 22 22 22
2 2 9 9 9
35 35 35 35 35
40 40 40 40 40
Pass 2:
d=d/2 > 3/2 = 1.5 +5>2
12 -10 -10 -10 -10 -10
2 2 2 2 2 2
-10 12 12 9 9 9
22 22 22 22 22 22
9 9 9 12 12 12
35 35 35 35 35 35
40 40 40 40 40 40
Now, finally we can say it is most short of bubble sort and it require very less
pass to sort elements where as it element increases then passes will also increase means n
elements require n-1 pass, where as shell sort require very less pass.
That’s why shell sort is better than bubble sort.
Pratical implementation of shell sort
#include<stdio.h>
#include<conio.h>
#include<process.h>
void main()
{
int a[10],n,I,d;
clrscr();
printf(“enter how many element ”);
scanf(“%d”,&n);
if(n>10)
{
printf(“/n size out of array ”);
getch();
exit(0);
}
printf(“/n enter %d element in array”n);
for(i=0;i<n; i++)
{
printf(“/n enter [%d] location element ” i);
scanf(“%d”, &a[i]);
}
clrscr();
printf(“/n array element before sorting ”);
for(i=0: i<n; i++)
{
printf(“/n %d,”,a[i]);
}
getch();
/* logic of shell short */
d=n/2;
while (d>=1)
{
for (i=0; i<n-d:i++)
{
if (a[i] > a[i+d])
{
t=a[i];
a[i] =a[i+d];
a[i+d] =t;
}
}
if (d==1)
Break;
d=d/2.0 +0.5;
}
printf(“/n elements after sorting :-”);
2 Again divide
[Beg] left array [end] [beg] right array [end]
25 57 48 37 12 92 86 33
3 Now finally
25 57 37 48 12 92 33 86
[25] [57] [48] [37] [12] [92] [86] [33]
4 Merge these array with sorting
Left array Right Array
25 57 37 48 12 92 33 86
5 merge them:
25 37 48 57 12 33 86 92
6 Merge them:
12 25 33 37 48 57 86 92
“Now it is finally sorted array”
Now basically two function require in merge sort :=>
1. For divide list in two parts again & again.
2. For merging these array which are divided by (1) among with sorting concept
then merge them into single one
Because of these reason we will create two functions:
merge sort () :>
It will divide array in two half (parts)
merge array () ->
It will merge array.
Here
la = lower index of array list
ua = upper index of first array
lb = lower index of second array
lb = upper index of second array
Here first array & second array both are same only we divide into two parts for
sorting purpose and represent both with different index.
Practical implementation of Merge Sort:
#include<conio.h>
#include<stdio.h>
#include<process.h>
void mergesort (int [ ], int , int);
void mergearray (int[ ], int, int, int, int, ) ;
void main()
{
int a[10],n,I;
clrscr();
printf(“/n how many element -:”);
scanf(“%d,”&n);
if (n>10)
{
printf(“/n size out of array ”);
getch();
exit();
}
printf(“/n enter %d elements in array “,n) ;
for(i=0; i<n; i++)
{
printf(“/n enter [%d] location element -:”);
scanf(“%d”, &a[i]);
}
void merge array (int a[10],int la, int ua, int lb,int ub)
{
int a[10], i,j,k=0;
i = la;
j = lb;
while ((i<=ua) &&(j<=ub))
{
if (a[i]>a[j])
a[k++] = a[j++];
else if (a[i] <a[j])
a[k++] = a[i++];
}
if (i==ua && j!= ub)
{
while (j<=ub)
a[k++] = a[j++];
}
if (j==ub && i!= ua )
{
while (i<=ua )
a[k++] = a[i++];
}
/* sorted array is sorted in c but we want in a, so we again copy c into a, so we
can get
Sorted array in a */
for (i=0; i<k; i++)
a[i] = c[i];
}
printf(“/n elements before sorting ”);
for (i=0; i<n; i++)
{
printf(“/n %d”, a[i]);
}
/* calling of function which will sort array */
Merge sort (a, 0, n-1);
printf(“/n elements after sorting”);
for (i+0; i<n; i++)
printf(“/n %d”a[i]);
getch();
}
/* function definition */
void merge sort (int a[10], int beg, int end)
{
int mid ;
if (beg<end)
{
mid =(beg +end)/2 ;
merge sort (a,beg, mid); // merge left
merge sort (a, mid+1, end); // merge right
merge array (a,beg, mid, mid+1, end);
/ / it merge left & right with sorting
}
}
QUICK SORT
Quick sort is also a sorting technique like merge sort.
It is also based on “divide and conquer” technique.
This technique finds the element called “pivot” that partitions the array into two values in such a
way that the left sub array are less than elements in the right sub array and greater than the
partitioning element. Then these two sub arrays are sorted respectively.
It is a “recursive procedure”
The main task in quick sort is to find the element that partitions the array into two
halves and to place it at its proper location in the array.
Generally the procedure places the first element in the array at its final location.
Use the following steps to perform quick sort:
Set the index of the first element of the array to loc and left variable and index of the last
element of the array to right variable.
Begin with the element pointed to by right the array is scanned from right to left
comparison each element with the element pointed by loc.
If element smaller than the element pointed to by loc is found then element are swapped
(interchanged) and procedure continue with step2.
If the value of right variable becomes equal to the value of loc the procedure is
terminated .This condition indicates that element is placed in its final position that is loc.
Begin with the element pointed to by left the array is scanned from left to right
comparing each element on the way with the element pointed to by loc.
If element greater than the element pointed to by loc is found in this condition, the
elements are interchanged and procedure continue with step 1.
If the value of the left variable becomes equal to the value of loc. The procedure
terminate here this condition indicates that the element is placed in its final position loc.
As this procedure terminates, the first element pivot of original the array will be placed
at loc. Its final location in the stored array.
The element to left of it will be less than this element and element to its right will be
greater than this element.
For e.g.
28,12, 32,17, 22, 30
Initially loc = 0, left = 0, right = 5
Scanning from right to left
28 12 32 17 22 30
| |
Loc/left right
22 12 32 17 28 30
| |
left loc/ right
Scan from left to right
a[loc] >a[left], true then left ++
22 12 32 17 28 30
| │
left loc/right
22 12 32 17 28 30
| |
left loc/ right
Now left become equal to loc, so procedure will become terminate here because 28 is
placed at it final position and it divide the array into two sub arrays like this :
22 12 17 28 32 30
{
int loc;
if (lb<ub)
{
partition (a, lb, ub, &loc);
quick sort (a, lb, loc-1);
quick sort (a , loc+1, ub);
}
}
void partition (int a[], int beg, int end,int *loc)
{
int left , right, temp;
int d = 1;
loc = left = beg;
right = end;
while (d= = 1)
{
while ((a[*loc]<=a [right])&&(*loc!= right))
right--;
if (* loc = = right)
d = 0;
else if (a[* loc]> a[right])
{
temp = a[* loc];
a[* loc] = a[right];
a[right] = temp;
*loc = right;
}
if (d==1)
{
while ((a[*loc] > = a[left]) && (*loc! = left))
left ++;
if (*loc = = left)
d = 0;
else if (a[*loc]<a [left])
{
temp = a[*loc];
a[*loc] = a[left];
a[left] = temp;
* loc = left;
}
}
}
Complexity of quick sort: -
o Here array is divided into two values again and again so here complexity is:
(log 2 n)
o Here each value examined in linear form that’ why here complexity is:
o(n)
o So total complexity is:
(n log2 n)
o The efficiency of quick sort is affected by the initial order of elements.
HEAP
A heap is a special type of tree which maintains following these two properties:
1 Shape property
2 Order property
1. Shape property: -
It refers that tree must be a complete binary tree (CBT). CBT is a
binary tree that contains the maximum numbers of nodes possible at least level for its
height that is 2h11 where h = height of a tree.
2. Order property: -
It is also based on two concept means tree must be either:
1 Min heap
2 Max heap
1 Max heap: -
2 Min heap: -
Special point: -
A heap is represented in memory using Linear Array, means Sequential
Representation, because heap is a complete binary tree. Therefore a heap of size n is represented
in memory using a linear array of size n.
Operations on Heap: -
“Element is always inserted at last child of the Heap, means always element will be
inserted at last location of heap.
This insertion violate (break) heap order property (min heap or max heap) so to maintain
it, we have to readjust the structure of heap so again it becomes tree.
To maintain its order property the new element has to move up from the last
position until it does not reach at its required location.
This operation is called “Reheapify Ppward” operation
Heapify because heap is created.
Reheapfy because is created again.
Upward because element is moving up.
Step:
If the value of last new inserted node is greater than its parent then exchange it with
value of its parent.
Then repeat this same process from the parent node and so on until the order property
is satisfied.
Basically it is a “recursive procedure”
40 30
20 10 4 5
Suppose we want insert 45 with in this tree then heap will become like this:
5
0
4 3
0 0
2 1 4 5
0 0
4
5
Here shape property is maintained but order property is not satisfied. So we will use reheapify
upward operation :
(a) compare 5
0 5
0
4 3
0 0 4 3
Exchange 0 0
2 1 4 5
0 0 4 1 4 5
5 0
4
5 2
(b) compare 0
5
0 5
0
4 3
0 0 4 3
Exchange 5 0
4 1 4 5
5 0 4 1 4 5
0 0
2
0 2
0
5 5
0 0
No Exchange
4 3 4 3
5 0 5 0
4 1 4 5 4 1 4 5
0 0 0 0
2 2
0 0
Now finally after reheapify operation, properties are maintained, order also and shape also. In
this way insertion is performed shape also.
Pratical Procedures:
void insert element (int a [], int *n , int value)
{
(*n) ++;
a[*n -1] = value ;
reheapity upward (a, *n-1);
]
Heap a. maintain heap
n , maintain location
Value is mew inserted value * is used with n because of call by values.
5
0
4 3
0 0
2 1 4 5
0 0
5
0
4 3
0 0
2 1 4
0 0
[Remove last node] but order property is not maintained.
40 is interchange with 5, because it is max heap and at root always highest value is placed.
4 4
0 0
5 3 2 3
0 0 0
2 1 4 5 1 4
0 0 0
Now it is final heap after deleting 50 nodes and here order and shape both properties are
maintained
Heap sort: -
As we known heap has order property, the min heap or non heap.
Min heap Minimum value of root node.
Max heap Maximum value at root node.
We can take the advantage of this condition by using a heap an array of n element can by
easily sorted.
Min heap is used for
“Descending order”
Max heap is used for
“Ascending order”
Following steps are used:
1. Create initial max heap by given elements.
2. Interchange the root value with last element.
3. Use reheapifydown operation from the root to last -1 and recreate heap again.
4. Repeat a step 1 and 2 until there are no more elements to perform reheapify downward
operation.
Insert : 45
5 45
RU
3 45 3 5
Insert: 10
4 4
5 RU 5
3 5 1 5
0
1
0 3
45
insert : 9
10 5
3 9
insert : 30 45 45
RU
10 5 10 30
3 9 30 3 9 5
insert : 50
45 45
RU
10 30 10 50
3 9 5 50 3 9 5 30
50
10 45
3 9 5 30
Now after reheapify operation elements in array are = (level order traversal)
50 10 45 3 9 5 30
10 30 10 30
10 45
Now array is 3 9 5
45 10 30 3 9 5 50
Interchange
5 10 30 3 9 45 50
5,10,30,3,9
5 10 30
RU RU
10 5 30 5 10
3 9
30
9 10
3 5
Swap
5 9 10 3 30 45 50
5 9 9 1
0
RU
9 5 5 1 5 9
0
Now array is:
3
10 5 9 3 30 45 50
Swap
3 5 9 10 30 45 50
3 5 5 9
RU RU
5 3 3 9 3 5
Now array is :
9 3 5 10 30 45 50
swap
5 3 9 10 30 45 50
Now array is
5 3 9 10 30 45 50
3
swap
{
printf(“\n size out of array”);
getch();
exit(0);
}
printf(“\n enter element in array”);
for (i=1; i<=n; I++)
{
printf(“\n enter elements ”);
scanf(“%d”, &a[i]);
}
printf(“\n elements before sorting”);
for (i=1; i<=n; i++)
printf(“\n %d”, a[i]);
Heap sort (a, n);
{
temp = a [start]
a[start ] = a[index];
a[index ] = temp;
reheapify down (a,index, end);
}
}
}
viod heapify (int a[], int n)
{
int I, index;
index = n/2 ;
HASHING
In all the search algorithms considered so far, the location of the item is determined by a sequence of comparisons. In
each case, a data item sought is repeatedly compared with items in certain locations of the data structure. However, the number
of actual comparison depends on the data structure and the search algorithm used. For example :
In an array and linked list, the linear search requires O(n) comparisons.
In a sorted array, the binary search requires 0 (log2n) comparisons.
In a binary search tree, search requires 0 (log2n) comparisons.
However, there are some applications that require search to be performed in constant time, i.e. O (1) Ideally, it may
not be possible, but still we can achieve a performance very close to it And this is possible using a data structure known as hash
table
A hash table, in basic sense, is a generalization of the simpler notion of an ordinary array. Directly addressing into
array makes it possible to access any data element of the array in O(1) time For example if a[1..200] is an. ordinary array, then
the nth data element, 1<=n<= 100, can be directly accessed as a[n]. However direct addressing is applicable only when we can
allocate an array that has one position for every possible key In addition direct addressing suffers from following problems
1. If the total number of possible keys is very large, it may not be possible to allocate an array of that size because of the
memory available in the system or the applications soft ware does not permit it.
2. If the actually number of keys is very small as compared to total number of possible keys, lot of space in the array will be
wasted.
Therefore, in practice, when the number of keys actually stored is small relative to total number of possible keys, a hash table
becomes more effective since a hash table typically uses an array of size proportional to the number of keys actually stored.
Further, instead of using the key as array index directly, the array index is computed from the key.
HASH TABLE
A hash table is a data structure in which the location of a data item is determined directly as a function of the data
item itself rather than by a sequence of comparisons. Under ideal conditions, the time required to locate a data item in a hash
table is O(1), i.e., it is constant and does not depend on the number of data items stored.
When the set of K of keys stored is much smaller than the universe U of all possible keys, a hash table requires much less
storage space than a direct-address table. In fact, the storage requirements can be reduced to O(k), while maintaining the search
operation an O(1) operation. The difference here is that this bound is for average-case time, whereas for direct addressing it
holds for the worst-case lime.
While in a direct-address table, an element with key k is element is stored in slot h(k); that is, a hash function h is the key
it Here, the hash function h is used to compute the slot from the key k. Here the hash function h maps the universe U of keys
into the slots of a hash table T[0..m-1]. This process of mapping keys to appropriate slots in a hash table is known as hashing.
Above diagram shows the implementing a dynamic set by a hash table T[0..m-1], where the elements are stored in
the table itself. Here each key in the dynamic set K of actual keys is mapped to hash table slots using hash function h. Note that
the keys k2 , k4 and k7 map to the same slot. The mapping of more than one key maps to the same slot is known as collision. We
can also say that the keys k2, k4 and k7 collide. Similarly, key k3, and k5 also collide.
We usually say that an element with key k hashes to slot h(k). We can also say that h (k) is the hash value of key k.
The purpose of the hash function is to reduce the range of array indices that need to be handled. Therefore, instead
of U values, we need to handle only m values which led to the reduction in the storage requirements.
The main flaw of this beautiful idea is that two or more keys (unequal keys) may hash to the same slot, which lead
to the condition called collision. Ideally, it would have been nice if the collision could be avoided by carefully choosing a hash
function. But in practice, it is not possible to avoid collision irrespective of the nature of the hash function Therefore, in these
circumstances, the best solution is to minimize the number of collisions and device a scheme to resolve then collisions if they
occur
The following schemes fat resolving collisions: -
1 Collision resolution by separating chaining
2 Collision resolutions by open addressing
HASH FUNCTION
A hash function h is simply a mathematical formula that manipulates the key in some form to compute the index
for this key in the hash table. For example, a hash function can divide the key by some number, usually the size of the hash table,
and return remainder as the index for the key.
In general, we say that a hash function h maps the universe U of keys into the slots of a hash table T [0...m-1]. This
process of mapping keys to appropriate slots in a hash table is known as hashing.
Different Hash Functions
There is variety of hash functions. The main considerations while choosing a particular hash function h are
1. It should be possible to compute it efficiently.
2. It should distribute the keys uniformly across the hash-table i.e. it should keep the number of collisions as minimum as
possible.
DIVISION METHOD
In division method, key k to be mapped into one of m slots in the hash-table is divided by m and the remainder of this
division is taken as index into the hash-table.
That is, the hash function
h(k) =k mod m
where mod is the modulus operator and is supported by Pascal language as such. In C/C++ and Java, its equivalent operator
is% character.
The above has function will map the keys in the range 0 to m-1 and is acceptable in C/C++ and Java. But if some
language supports the index from 1 onwards, then the hash function becomes
h(k)= k mod m+1
Example
Consider a hash table with 9 slots i.e. m =9, then the hash function
h(k)= k mod m
will map the key 132 to slot 7 since
h(132)= l32 mod 9 =7
Since it requires only a single division operation, hashing is quite fast. When using the division method, certain values
of m should be avoided. It has been proved in literature that good values form are prime values not too close to exact powers of
2.
MULTIPLICATION METHOD
The multiplication method operates in two steps. In the first step, the key value k is multiplied by a constant A in the
range 0 <A < 1 and extract the fractional part of value kA. In the second step, the fractional value obtained above is multiplied
by m and the floor of the result is taken as the hash value. That is, the hash function is
where “kA mod 1” means the fractional part of kA i e kA — . Note that read as floor of x and represent the largest
integer less than or equal x
Although this method works with any value of A, it works better with some values than others The best choice
depends on the characteristics of the key values Knuth has suggested in his study that the following value of A is likely to work
reasonably well.
Example :
Consider a hash table with 10000 slots i.e. m = 10000, then the hash function
= 41
MIDSQUARE METHOD
The mid square method also operates in two steps. In the first step, the square of the key value k is taken. In the
second step, the bash value is obtained by deleting digits from ends of the squared value i.e. k 2. It is important to note that same
position of k2 must be used for all keys. Thus, the hash function is
h(k)=s
where s is obtained by deleting digits from both sides of k 2.
Example
Consider a hash table with 100 slots i.e. m=100, and key values k=3205, 7148, 2345
Solution:
The calculations are shown below:
The hash values are obtained by taking fourth and fifth digits counting from right.
FOLDING METHOD
The folding method also operates in two steps in the first step, the key value k is divided into number of parts, k 1, k2,
k3,...,kr where each part has the same number of digits except the last part, which can have 1esser digits. In the second step, these
parts are added together and the hash value is obtained by ignoring the last carry, if any For example if the hash table has 1000
slots, each part will have three digits, and the sum of these parts after ignoring the last carry will also be three-digit number in the
range 0 to 999
Example:
Consider a hash table with 100 slots i.e. m = 100 and key values k= 9235, 714, 71458
Solution:
In above examples, we have assumed that keys are numeric. However, if the keys are alphanumeric, then the ASCII
codes of fixed number of characters can be added together to transfer the character key to its equivalent numeric key, and then
any of the above hash function can be applied.
Multidimensional Array
Address Formula