Data Structure Full Syllabus
Data Structure Full Syllabus
DS Notes
DATA
STRUCTURE
PRIMITIVE NON
PRIMITIVE
Data types
A particular kind of data item, as defined by the values it can take, the programming language used, or
the operations that can be performed on it.
Pointer: A variable that holds memory address of another variable are called pointer.
Graph: Graph is a collection of nodes (Information) and connecting edges (Logical relation) between nodes.
o A tree can be viewed as restricted graph.
o Graphs have many types:
Un-directed Graph
Directed Graph
Mixed Graph
Multi Graph
Simple Graph
Null Graph
Weighted Graph
1. Create
The create operation results in reserving memory for program elements. This can be done by declaration
statement. Creation of data structure may take place either during compile-time or run-time. malloc()
function of C language is used for creation.
2. Destroy
Destroy operation destroys memory space allocated for specified data structure. free() function of C
language is used to destroy data structure.
3. Selection
Selection operation deals with accessing a particular data within a data structure.
4. Updation
It updates or modifies the data in the data structure.
5. Searching
It finds the presence of desired data item in the list of data items, it may also find the locations of all
elements that satisfy certain conditions.
6. Sorting
Sorting is a process of arranging all data items in a data structure in a particular order, say for example,
either in ascending order or in descending order.
7. Merging
Merging is a process of combining the data items of two different sorted list into a single sorted list.
8. Splitting
Splitting is a process of partitioning single list to multiple list.
9. Traversal
Traversal is a process of visiting each and every node of a list in systematic manner.
An algorithm is a procedure that you can write as a C function or program, or any other language.
Algorithm Efficiency
Some algorithms are more efficient than others. We would prefer to choose an efficient algorithm, so it
would be nice to have metrics for comparing algorithm efficiency.
The complexity of an algorithm is a function describing the efficiency of the algorithm in terms of the
amount of data the algorithm must process.
Usually there are natural units for the domain and range of this function. There are two main complexity
measures of the efficiency of an algorithm
Time complexity
Time Complexity is a function describing the amount of time an algorithm takes in terms of the
amount of input to the algorithm.
"Time" can mean the number of memory accesses performed, the number of comparisons between
integers, the number of times some inner loop is executed, or some other natural unit related to the
amount of real time the algorithm will take.
Space complexity
Space complexity is a function describing the amount of memory (space) an algorithm takes in terms
of the amount of input to the algorithm.
We often speak of "extra" memory needed, not counting the memory needed to store the input itself.
Again, we use natural (but fixed-length) units to measure this.
We can use bytes, but it's easier to use, say, number of integers used, number of fixed-sized structures,
etc. In the end, the function we come up with will be independent of the actual number of bytes
needed to represent the unit.
Space complexity is sometimes ignored because the space used is minimal and/or obvious, but
sometimes it becomes as important an issue as time.
b1, b2 b1, u2
[1,1][1,2] [1,3] [ 1 ,m ] col 1 col 2 col 3 col 4
Applications of Array
1. Symbol Manipulation (matrix representation of polynomial equation)
2. Sparse Matrix
Once we have algorithm for converting the polynomial equation to an array representation and another
algorithm for converting array to polynomial equation, then different operations in array (matrix) will be
corresponding operations of polynomial equation
Example:-
o The non-zero entries of a sparse matrix may be mapped into a linear list in row-major order.
o For example the non-zero entries of 4X8 matrix of below fig.(a) in row major order are 2, 1, 6, 7,
3, 9, 8, 4, 5
0 0 0 2 0 0 1 0
0 6 0 0 7 0 0 3
0 0 0 9 0 8 0 0
0 4 5 0 0 0 0 0
Fig (a) 4 x 8 matrix
Terms 0 1 2 3 4 5 6 7 8
Row 1 1 2 2 2 3 3 4 4
Column 4 7 2 5 8 4 6 2 3
Value 2 1 6 7 3 9 8 4 5
Fig (b) Linear Representation of above matrix
0 0 6 0 9 0 0
A= 2 0 0 7 8 0 4
10 0 0 0 0 0 0
0 0 12 0 0 0 0
0 0 0 0 0 0 0
0 0 0 3 0 0 5
Here from 6X7=42 elements, only 10 are non zero. A[1,3]=6, A[1,5]=9, A[2,1]=2, A[2,4]=7, A[2,5]=8,
A[2,7]=4, A[3,1]=10, A[4,3]=12, A[6,4]=3, A[6,7]=5.
One basic method for storing such a sparse matrix is to store non-zero elements in one dimensional
array and to identify each array elements with row and column indices fig (c).
ROW COLUMN A
1 1 3 6
2 1 5 9
3 2 1 2
4 2 4 7
5 2 5 8
6 2 7 4
7 3 1 10
8 4 3 12
9 6 4 3
10 6 7 5
Fig (c )
COLUMN A
1 3 6
ROW 2 5 9
1 1 3 1 2
2 3 4 4 7
3 7 5 5 8
4 8 6 7 4
5 0 7 1 10
6 9 8 3 12
9 4 3
10 7 5
ROW NO First Column
for row no COLUMN NO
Fig(d)
A more efficient representation in terms of storage requirement and access time to the row of the
matrix is shown in fid (d). The row vector changed so that its ith element is the index to the first of the
column indices for the element in row I of the matrix.
1 3 6 1 5 9 2 1 2 2 4 7
2 5 8 2 7 4 3 1 10 4 3 12
6 4 3 6 7 5 NULL
A pointer TOP keeps track of the top element in the stack. Initially, when the stack is empty, TOP has a
value of “one” and so on.
Each time a new element is inserted in the stack, the pointer is incremented by “one” before, the
element is placed on the stack. The pointer is decremented by “one” each time a deletion is made from
the stack.
Applications of Stack
Recursion
Keeping track of function calls
Evaluation of expressions
Reversing characters
Servicing hardware interrupts
Solving combinatorial problems using backtracking.
Write an algorithm which will check that the given string belongs to following
grammar or not. L={wcwR | w Є {a,b}*}(Where wR is the reverse of w)
Algorithm : RECOGNIZE
Given an input string named STRING on the alphabet {a, b, c} which contains a blank in its rightmost
character position and function NEXTCHAR which returns the next symbol in STRING, this algorithm
determines whether the contents of STRING belong to the above language. The vector S represents the
stack, and TOP is a pointer to the top element of the stack.
Write an algorithm for push, pop and empty operations on stack. Using above
functions write an algorithm to determine if an input character string is of the
form aibi where i>=1 i.e. no of a should be equal to no of b
Algorithm RECOGNIZE
Given an input string named STRING on alphabet ‘a’ and ‘b’ which contain blank (‘ ‘) on right most character
function NEXTCHAR which returns the next symbol from STRING. This algorithm determines if an input string
is of form aibi where i>1 i.e no of ‘a’ should be equal to no of ‘b’. the vector S represent the stack and TOP is
the pointer to the top element of stack. Counter is a counter B for ‘b’ occurrence.
#include<stdio.h>
int Find_GCD(int, int);
void main()
{
int n1, n2, gcd;
scanf(“%d %d”,&n1, &n2);
gcd = Find_GCD(n1, &n2);
printf(“GCD of %d and %d is %d”, n1, n2, gcd);
}
Given integer N, this algorithm computes factorial of N. Stack A is used to store an activation record associated
with each recursive call. Each activation record contains the current value of N and the current return address
RET_ADDE. TEMP_REC is also a record which contains two variables PARAM & ADDRESS.TOP is a pointer to the
top element of stack A. Initially return address is set to the main calling address. PARAM is set to initial value N.
Algorithm : REVPOL
Given an input string INFIX containing an infix expression which has been padded on the right with ‘)’ and
whose symbol have precedence value given by above table, a vector S used as a stack and a NEXTCHAR
which when invoked returns the next character of its argument. This algorithm converts INFIX into reverse
polish and places the result in the string POLISH. The integer variable TOP denotes the top of the stack.
Algorithm PUSH and POP are used for stack manipulation. The integer variable RANK accumulates the rank
of expression. Finally the string variable TEMP is used for temporary storage purpose.
1. [Initialize stack]
TOP 1
S[TOP] ‘(‘
2. [Initialize output string and rank count ]
POLISH ‘ ‘
RANK 0
3. [Get first input symbol]
NEXTNEXTCHAR (INFIX)
4. [Translate the infix expression ]
Repeat thru step 7 while NEXT != ‘ ‘
5. [Remove symbols with greater precedence from stack]
IF TOP < 1
Then write (‘INVALID’)
EXIT
Repeat while G (S[TOP]) > F(NEXT)
TEMP POP (S, TOP)
POLISH POLISH O TEMP
RANK RANK + R(TEMP)
IF RANK <1
Then write ‘INVALID’)
EXIT
6. [Are there matching parentheses]
IF G(S[TOP]) != F(NEXT)
Then call PUSH (S,TOP, NEXT)
Else POP (S,TOP)
7. [Get next symbol]
NEXT NEXTCHAR(INFIX)
8. [Is the expression valid]
IF TOP != 0 OR RANK != 1
Then write (‘INVALID ‘)
Else write (‘VALID ’)
(ii) ( A + B ) * C + D / ( B + A * C ) + D
Translate the following string into Polish notation and trace the content of
stack: (a + b ^ c ^ d) * ( e + f / d )
Evaluate (i): 5 4 6 + * 4 9 3 / + *
Empty Stack Read Operator +, Read Operator *,
pop two values pop two values
from stack opn2 = from stack opn2 =
Read and push 6, opn1 = 4, and 10, opn1 = 5, and
operands 5, 4, 6 push the answer 10 push the answer 50
6
4 10
5 5 50 Read and
push
operands
4, 9, 3
Evaluate (ii) : * 7 5 2 + * 4 1 1 + / -
Empty Stack Read Operator +, Read Operator *,
pop two values pop two values
from stack opn2 = from stack opn2 =
Read and push 2, opn1 = 5, and 7, opn1 = 7, and
operands 7, 5, 2 push the answer 7 push the answer 49
2
5 7
7 5 49 Read and
push
operands
4, 1, 1
Explain following:
(i) Queue (ii) Circular Queue (iii) DQUEUE (iv) Priority Queue
(i) Queue
o A linear list which permits deletion to be performed at one end of the list and insertion at the other
end is called queue.
o The information in such a list is processed FIFO (first in first out) of FCFS (first come
first served) pattern.
o Front is the end of queue from that deletion is to be performed.
o Rear is the end of queue at which new element is to be inserted.
o The process to add an element into queue is called Enqueue
o The process of removal of an element from queue is called Dequeue.
o The familiar and traditional example of a queue is Checkout line at Supermarket Cash Register
where the first person in line is usually the first to be checkedout.
Front
Deletion Insertion
Rear
(iii) Dequeue
o A dequeue (double ended queue ) is a linear list in which insertion and deletion are performed from
the either end of the structure.
o There are two variations of Dqueue
Input restricted dqueue- allows insertion at only one end
Output restricted dqueue- allows deletion from only one end
o Such a structure can be represented by following fig.
Front
Deletion Insertion
Insertion Deletion
Rear
Task Identification
R1 R2 … Ri-1 O1 O2 … Oj-1 B1 B2 … Bk-1 …
1 1 … 1 2 2 … 2 3 3 … 3 …
Priority
Ri Oj Bk
Fig (a) : Priority Queue viewed as a single queue with insertion allowed at any position.
Priority 1
R1 R2 … Ri-1 … Ri
Priority 2
O1 O2 … Oj-1 … Oj
Priority 3
B1 B2 … Bk-1 … Bk
1. [Overflow]
IF R >= N
Then write (‘OVERFLOW’)
Return
2. [Increment REAR pointer]
RR+1
3. [Insert element ]
Q[R] Y
4. [Is front pointer properly set]
IF F=0
Then F 1
Return
1. [Underflow]
IF F= 0
Then write (‘UNDERFLOW’)
Return(0) (0 denotes an empty Queue)
2. [Decrement element]
Y Q[F]
3. [Queue empty?]
IF F=R
Then F R 0
Else F F+1 (increment front pointer)
4. [Return element]
Return (Y)
1. [Underflow?]
If F = 0
Then Write (‘UNDERFLOW’)
Return (0)
2. [Delete Element]
Y ← Q[F]
3. [Queue Empty?]
If F=R
Then F ← R ← 0
Return (Y)
4. [Increment front pointer]
If F=N
Then F ← 1
Else F←F+1
Return (Y)
1. [Overflow]
IF F=0
Then write (‘EMPTY’)
Return
IF F=1
Then write (‘OVERFLOW’)
Return
2. [Decrement front pointer]
F F-1
3. [Insert element ]
Q[F] Y
Return
1. [Underflow]
IF R= 0
Then write (‘UNDERFLOW’)
Return(0)
2. [Delete element]
Y Q[R]
3. [Queue empty?]
IF R=F
Then R F 0
Else R R-1 (decrement front pointer)
4. [Return element]
Return (Y)
Positions 1 2 3 4 5 6
Initial Position of Queue, Front=2, Rear=4 A C D
F is added to queue, Front=2, Rear=5 A C D F
Two letters are deleted, Front=4, Rear=5 D F
R is added to the queue, Front=4, Rear=6 D F R
S is added to the queue, Front=4, Rear=1 S D F R
One letter is deleted, Front=5, Rear=1 S F R
Linked List
There are many applications where sequential allocation method is unacceptable because of following
characteristics
The linked allocation method of storage can result in both efficient use of computer storage and computer time.
A Linked List
Linked List
Node
// C Structure to represent a node
struct node
info link
{
int info
struct node *link
Data Pointer to
};
next node
Linked List
• Main advantage of doubly linked list is we can traverse in any direction, forward or reverse.
• Other advantage of doubly linked list is we can delete a node with little trouble, since we have
pointers to the previous and next nodes. A node on a singly linked list cannot be removed unless we
have the pointer to its predecessor.
• Drawback of doubly linked list is it requires more memory compared to singly linked list because we
need an extra pointer to point previous node.
• L and R in image denote left most and right most nodes in the list.
• Left link of L node and right link of R node is NULL, indicating the end of list for each direction.
Advantages of an array
1. We can access any element of an array directly means random access is easy
2. It can be used to create other useful data structures (queues, stacks)
Linked List
Disadvantages of an array
1. Its size is fixed
2. It cannot be dynamically resized in most languages
3. It is hard to add/remove elements
4. Size of all elements must be same.
5. Rigid structure (Rigid = Inflexible or not changeable)
Advantages and disadvantages of stack & queue implemented using linked list over array is described below,
Linked List
Searching a node
If a particular node in a linked list is required, it is necessary to follow links from the first node
onwards until the desired node is found.
Where as in the case of an array, directly we can access any node
Memory
The pointers in linked list consume additional memory compared to an array
Size
Array is fixed sized so number of elements will be limited in stack and queue.
Size of linked list is dynamic and can be changed easily so it is flexible in number of elements
X1 Y X2 X3 X4 X5 X6
X1 X2 X3 X4
Linked List
Few assumptions,
We assume that a typical element or node consists of two fields namely; an information field called
INFO and pointer field denoted by LINK. The name of a typical element is denoted by NODE.
Node
// C Structure to represent a node
struct node
info link
{
int info
struct node *link
Data Pointer to
};
next node
Linked List
1 [Underflow?]
IF AVAIL = NULL
Then Write (“Availability Stack Underflow”)
Return(FIRST)
Linked List
1 [Underflow?]
IF AVAIL = NULL
Then Write (“Availability Stack Underflow”)
Return(FIRST)
Linked List
Linked List
1 [Underflow?]
IF AVAIL = NULL
Then Write (“Availability Stack Underflow”)
Return(FIRST)
5. [Does the new node precede all other node in the list?]
If INFO(NEW) ≤ INFO (FIRST)
then LINK (NEW) FIRST
Return (NEW)
Linked List
By repeatedly involving function INSORD; we can easily obtains an ordered liner list for example the sequence of
statements.
FRONT NULL
FRONT INSORD (29, FRONT)
FRONT INSORD (10, FRONT)
FRONT INSORD (25, FRONT)
FRONT INSORD (40, FRONT)
FRONT INSORD (37, FRONT)
FRONT 29
FRONT 10 29
FRONT 10 25 29
FRONT 10 25 29 40
FRONT 10 25 29 37 40
Linked List
3. [Find X]
Repeat thru step-5 while SAVE ≠ X and LINK (SAVE) ≠ NULL
7. [Delete X]
If X = FIRST (if X is first node?)
then FIRST LINK (FIRST)
else LINK (PRED) LINK (X)
Linked List
2. If the availability stack is empty then write availability stack underflow and return else copy the first
node.
3. Report thru step 5 while the old list has not been reached.
4. Obtain next node in old list and record its predecessor node.
5. If availability stack is empty then write availability stack underflow and return else copy the node and
add it to the rear of new list.
6. Set link of the last node in the new list to null and return.
3. [Initialize traversal]
SAVE FIRST
6. [Copy node]
If AVAIL = NULL
then write (‘Availability stack underflow’)
Return (0)
else NEW AVAIL
AVAIL LINK (AVAIL)
FIELD (NEW) INFO (SAVE)
PTR (PRED) NEW
Linked List
Linked List
Linked List
Linked List
Linked List
Linked List
Linked List
3. [Find X]
Repeat thru step 5 while INFO(SAVE) ≠ X and SAVE ≠ LAST
4. [Update Predecessor]
PRED SAVE
7. [Delete node X]
If INFO (FIRST) = X
then LINK (HEAD) LINK(FIRST)
else LINK (PRED) LINK(SAVE)
If SAVE = LAST
then LAST PRED
Linked List
5. [Insert in middle]
LPTR (NEW) LPTR (M)
RPTR (NEW) M
LPTR (M) NEW
RPTR (LPTR (NEW)) NEW
Return
Linked List
If SAVE = R
then RPTR(SAVE) NEW
Linked List
1. [ Is underflow ?]
If R=NULL
then write (‘ UNDERFLOW’)
return
2. [Delete node]
If L = R (single node in list)
then L R NULL
else If OLD = L (left most node)
then L RPTR(L)
LPTR (L) NULL
else if OLD = R (right most)
then R LPTR (R)
RPTR (R) NULL
else RPTR (LPTR (OLD)) RPTR (OLD)
LPTR (RPTR (OLD)) LPTR (OLD)
Linked List
int pop()
{
int a;
if(top>=0)
{
a=stack[top];
top–-;
return a;
}
else
{
printf("Stack is Underflow, Stack is empty, nothing to POP!");
return -1;
}
}
Linked List
struct node
{
int info;
struct node *link;
} *top;
int pop()
{
int val;
if(top!=NULL)
{
val = top info;
top=top link;
return val;
}
else
{
printf("Stack Underflow");
return -1;
}
}
Linked List
# include <stdio.h>
# define MAXSIZE 100
int queue[MAXSIZE], front = -1, rear = -1;
void enqueue(int val)
{
if(rear >= MAXSIZE)
{
printf("Queue is overflow") ;
return ;
}
rear++;
queue [rear] = val;
if(front == -1)
{
front++;
}
}
int dequeue()
{
int data;
if(front == -1)
{
printf("Queue is underflow") ;
return -1;
}
data = queue [front];
if(front == rear)
{
front = rear = -1;
}
else
{
front++;
}
return data;
}
Linked List
struct node
{
int info;
struct node *link;
} *front, *rear;
int dequeue()
{
struct node *p;
int val;
if (front == NULL || rear == NULL)
{
printf("Under Flow");
exit(0);
}
else
{
p = front;
val = p info;
front = front link;
free(p);
}
return (val);
}
Linked List
struct node
{
int priority;
int info;
struct node *link;
}*front = NULL;
remove()
{
struct node *tmp;
if(front == NULL)
printf("Queue Underflow\n");
else
{
tmp = front;
printf("Deleted item is %d\n",tmp->info);
front = front->link;
free(tmp);
}
}/*End of remove()*/
Linked List
insert()
{
struct node *tmp,*q;
int added_item,item_priority;
tmp = (struct node *)malloc(sizeof(struct node));
printf("Input the item value to be added in the queue : ");
scanf("%d",&added_item);
printf("Enter its priority : ");
scanf("%d",&item_priority);
tmp->info = added_item;
tmp->priority = item_priority;
/*Queue is empty or item to be added has priority more than
first item*/
if( front == NULL || item_priority < front->priority )
{
tmp->link = front;
front = tmp;
}
else
{
q = front;
while( q->link != NULL &&
q->link->priority <= item_priority )
{
q=q->link;
}
tmp->link = q->link;
q->link = tmp;
}/*End of else*/
}/*End of insert()*/
Linked List
display()
{
struct node *ptr;
ptr = front;
if(front == NULL)
printf("Queue is empty\n");
else
{
printf("Queue is :\n");
printf("Priority Item\n");
while(ptr != NULL)
{
printf("%5d %5d\n",ptr->priority,ptr->info);
ptr = ptr->link;
}
}/*End of else */
}/*End of display() */
1. Discuss following
1. Graph
A graph G consist of a non-empty set V called the set of nodes (points, vertices) of the
graph, a set E which is the set of edges and a mapping from the set of edges E to a set of
pairs of elements of V.
It is also convenient to write a graph as G=(V,E).
Notice that definition of graph implies that to every edge of a graph G, we can associate a
pair of nodes of the graph. If an edge X Є E is thus associated with a pair of nodes (u,v)
where u, v Є V then we says that edge x connect u and v.
2. Adjacent Nodes
Any two nodes which are connected by an edge in a graph are called adjacent node.
5. Undirected graph
A graph in which every edge is undirected is called undirected graph.
6. Mixed Graph
If some of the edges are directed and some are undirected in graph then the graph is called
mixed graph.
7. Loop (Sling)
An edge of a graph which joins a node to itself is called a loop (sling).
8. Parallel Edges
In some directed as well as undirected graphs, we may have certain pairs of nodes joined by
more than one edges, such edges are called Parallel edges.
9. Multigraph
Any graph which contains some parallel edges is called multigraph.
23. Forest
If we delete the root and its edges connecting the nodes at level 1, we obtain a set of
disjoint tree. A set of disjoint tree is a forest.
31. Sibling
Siblings are nodes that share the same parent node.
1. All key (if any) in the left sub tree of the root precedes the key in the root.
2. The key in the root precedes all key (if any) in the right sub tree.
3. The left and right sub tree sub trees of the root are again search trees.
The most common operations performed on tree structure is that of traversal. This is a procedure by
which each node in the tree is processed exactly once in a systematic manner.
There are three ways of traversing a binary tree.
1. Preorder Traversal
2. Inorder Traversal
3. Postorder Traversal
A Preorder traversal : A B C D E F G
Inorder traversal : C B A E F D G
B D Postorder traversal : C B F E G D A
Preorder
Preorder traversal of a binary tree is defined as follow
o Process the root node
o Traverse the left subtree in preorder
o Traverse the right subtree in preorder
If particular subtree is empty (i.e., node has no left or right descendant) the traversal is performed by
doing nothing, In other words, a null subtree is considered to be fully traversed when it is encountered.
The preorder traversal of a tree (Fig. 1.1) is given by A B C D E F G
Inorder
The Inorder traversal of a binary tree is given by following steps,
o Traverse the left subtree in Inorder
o Process the root node
o Traverse the right subtree in Inorder
The Inorder traversal of a tree (Fig. 1.1) is given by C B A E F D G
Postorder
The postorder traversal is given by
o Traverse the left subtree in postorder
o Traverse the right subtree in postorder
o Process the root node
The Postorder traversal of a tree (Fig. 1.1) is given by C B F E G D A
Converse …
If we interchange left and right words in the preceding definitions, we obtain three new traversal orders
which are called
o Converse Preorder (A D G E F B C)
o Converse Inorder (G D F E A B C)
o Converse Postorder (G F E D C B A)
Procedure : RPREORDER(T)
Given a binary tree whose root node address is given by pointer variable T and whose node structure is
same as described below. This procedure traverses the tree in preorder, in a recursive manner.
4. [Finished]
return
Procedure : RINORDER(T)
Given a binary tree whose root node address is given by pointer variable T and whose node structure is
same as described below. This procedure traverses the tree in inorder, in a recursive manner.
1. [Check for empty Tree]
If T = NULL
then write (‘Empty Tree’)
return
5. [Finished]
return
Procedure : RPOSTORDER(T)
Given a binary tree whose root node address is given by pointer variable T and whose node structure is
same as described below. This procedure traverses the tree in postorder, in a recursive manner.
5. [Finished]
return
4. Give traversal order of following tree into Inorder, Preorder and Postorder.
1 Inorder: 2 1 4 5 3
Preorder: 1 2 3 4 5
Post order: 2 5 4 3 1
2 3
Inorder :DGBAHEICF
Postorder : G D B H I E F C A
D G B H E I C F
B C
D G H E I F
B C
D E F
G H I
Postorder : C B E H G I F D A
Inorder :BCAEDGHFI
B C E D G H F I
B D
C E G H F I
B D
C E F
G H I
B D
C E F
G I
Preorder : G B Q A C K F P D E R H
Inorder : Q B K C F A G P E D H R
Q B K C F A P E D H R
B P
Q K C F A D E R H
B P
Q A D
E R H
K C F
B P
Q A D
C E R
K F H
50
25 75
22 40 80
60
15 30 90
8. Construct binary search tree for the following data and find its Inorder,
Preorder and Postorder traversal
10,3,15,22,6,45,65,23,78,34,5
10
3 15
6 22
5
45
23 65
34 78
The wasted NULL links in the binary tree storage representation can be replaced by threads.
A binary tree is threaded according to particular traversal order. e.g.: Threads for the inorder traversals
of tree are pointers to its higher nodes, for this traversal order.
o If left link of node P is null, then this link is replaced by the address of its predecessor.
o If right link of node P is null, then it is replaced by the address of its successor
Because the left or right link of a node can denote either structural link or a thread, we must somehow
be able to distinguish them.
Method 1:- Represent thread a –ve address.
Method 2:- To have a separate Boolean flag for each of left and right pointers, node structure for this is
given below,
Head node is simply another node which serves as the predecessor and successor of first and last tree
nodes. Tree is attached to the left branch of the head node
Head
Advantages
Inorder traversal is faster than unthreaded version as stack is not required.
Effectively determines the predecessor and successor for inorder traversal, for unthreaded tree this task is
more difficult.
A stack is required to provide upward pointing information in tree which threading provides.
It is possible to generate successor or predecessor of any node without having over head of stack with the
help of threading.
Disadvantages
Threaded trees are unable to share common subtrees
Prof. Pradyumansinh Jadeja (9879461848) | 2130702 – Data Structure 12
If –ve addressing is not permitted in programming language, two additional fields are required.
Insertion into and deletion from threaded binary tree are more time consuming because both thread and
structural link must be maintained.
B D
E G
C
F
Binary Tree
Inorder Traversal C B A E F D G
HEAD
B D
C E G
F
Prof. Pradyumansinh Jadeja (9879461848) | 2130702 – Data Structure 13
10. Draw a right in threaded binary tree for the given tree
B E
C D F H
11. What is the meaning of height balanced tree? How rebalancing is done in
height balanced tree.
A tree is called AVL (height balance binary tree), if each node possesses one of the following properties
1. A node is called left heavy if the longest path in its left sub tree is one longer then the longest path of its
right sub tree.
2. A node is called right heavy if the longest path in the right sub tree is one longer than path in its left sub
tree.
3. A node is called balanced, if the longest path in both the right and left sub tree are equal.
If tree becomes unbalanced by inserting any node, then based on position of insertion, we need to rotate the
unbalanced node. Rotation is the process to make tree balanced
1) Insertion into Left sub-tree of nodes Left child – Single Right Rotation
2) Insertion into Right sub-tree of node’s Left child – Left Right Rotation
3) Insertion into Left sub-tree of node’s Right child – Right Left Rotation
4) Insertion into Right sub-tree of node’s Right child – Single Left Rotation
1) Insertion into Left sub-tree of nodes Left child – Single Right Rotation
If node becomes unbalanced after insertion of new node at Left sub-tree of nodes Left child, then we need
to perform Single Right Rotation for unbalanced node.
Right Rotation
a. Detach leaf child’s right sub-tree
b. Consider leaf child to be the new parent
c. Attach old parent onto right of new parent
d. Attach old leaf child’s old right sub-tree as leaf sub-tree of new right child
Critical Node J K
Right J
K Z X
Rotation
X Y N Y Z
Critical Node 13 7
Steps of 13
7 15 Right 5
Rotation
5 10 3 10 15
7
7
5 13
5 13
3 10 15
3 10 15
2) Insertion into Right sub-tree of node’s Left child – Left Right Rotation
If node becomes unbalanced after insertion of new node at Right sub-tree of node’s Left child, then we need
to perform Left Right Rotation for unbalanced node.
J J Y
Y Z K J
K Z
Left Right
Rotation of K Rotation of J
X Y K n Z
n X
n X
3) Insertion into Left sub-tree of node’s Right child – Right Left Rotation
If node becomes unbalanced after insertion of new node at Left sub-tree of node’s Right child, then we
need to perform Right Left Rotation for unbalanced node.
Unbalanced node
X X Y
T1 Right T1 Y Left
Z
Rotation of Z Rotation of X X Z
T2
Y T4 Z
T1 T2 T3 T4
T3 T4
T2 T3
4) Insertion into Right sub-tree of node’s Right child – Single Left Rotation
If node becomes unbalanced after insertion of new node at Right sub-tree of nodes Right child, then we
need to perform Single Left Rotation for unbalanced node.
Left Rotation
a. Detach right child’s leaf sub-tree
b. Consider right child to be new parent
c. Attach old parent onto left of new parent
d. Attach old right child’s old left sub-tree as right sub-tree of new left child
Unbalanced node
X
Y
T1
Y Leaf
T3
Rotation of X X
T2 T3
T1 T2
n
Example
50 Unbalanced node 70 70
40 70 50 80 50 80
90
60 80 40 90 40 60
90 60
1 2 3 4
Insert 6 Insert : 5 Insert : 4 Insert : 3
Right
6 6 6 5 5
Rotate 6
5 5 4 6 4 6
4
3
6 5
Insert : 2
Insert : 1
5 5
5
Righ
3 6 3 6
Rotate 4 6
2 4 2 4 3
1 Right
2
Rotate 5
2 5
1 4 6
Assignment:
Define height of the binary tree. Define height balanced tree with its advantages. Construct a height
balanced binary tree (AVL tree) for the following data 42,06,54,62,88,50,22,32,12,33
Construct the AVL search tree by inserting the following elements in the order of their occurrence. 64, 1,
44, 26, 13, 110, 98, 85
13. What are the advantages of Multiway search tree in disc access?
Construct B tree of order 5 for the following data
1,6,7,2,11,5,10,13,12,20,16,24,3,4,18,19,14,25
1 2 3 4 5
Insert: 1 Insert: 6 Insert: 7 Insert: 2 Insert: 11
6
1 1, 6 1, 6, 7 1, 2, 6, 7 1, 2, 6, 7, 11
Overflow 1, 2 7, 11
6 7 8
Insert: 5 Insert: 10 Insert: 13
6 6 6
9 10
Insert: 12 Insert: 20
6 6, 11 6, 11
11 12
Insert: 16 Insert: 24
6, 11 6, 11
6, 11, 16
1, 2, 5 7, 10 12, 13, 16, 20 1, 2, 5 7, 10 12, 13, 16, 20, 24
Overflow
1, 2, 5 7, 10 12, 13 20, 24
13
Insert: 3, 4
6, 11, 16 3 6 11 16
14
Insert: 18, 19, 14
3 6 11 16
15
Insert: 25
3 6 11 16
3, 6 16 , 20
Assignment:
Construct mutiway search tree for the following data of order for 100, 150, 50, 55, 250, 200, 170, 65, 75,
20, 30, 52, 10, 25, 180, 190, 300, 5
15. What is graph? How it can be represented using adjacency matrix, what
is path matrix? How path matrix can be found out using adjacency matrix .
Graph
A graph G consist of a non empty set V called the set of nodes (points, vertices) of the graph, a set E
which is the set of edges and a mapping from the set of edges E to a set of pairs of elements of V.
It is also convenient to write a graph as G=(V,E).
Notice that definition of graph implies that to every edge of a graph G, we can associate a pair of nodes
of the graph. If an edge X Є E is thus associated with a pair of nodes (u,v) where u, v Є V then we says
that edge x connect U and V.
Adjacency matrix
Let G = (V, E) be a simple diagraph in which V = {v1, v2,…., vn} and the nodes are assumed to be ordered from
v1 to vn. An n x n matrix A whose elements are aij are given by
( )
aij = {
V1 V4
V1 V2 V3 V4
V1 0 1 0 1
V2 1 0 0 0
V3 1 1 0 1
V4 0 1 0 0
V2 V3
We can extend the idea of matrix representation to multigraph and weighted graphs. In the case of
multigraph or weighted graph we write aji = w, where aij denotes either the multiplicity or the
weight of the edge.
Path matrix
An entry of 1 in the ith row and jth column of A shows the existence of an edge (v i, vj), that is a path
of length 1 from vi to vj.
( )
Let denote the elements of A2 by aij(2). Then {∑
(2)
Therefore aij is equal to the number of different paths of exactly length 2 from vi to vj.
Similarly element in ith row and jth column of A3 gives number of paths of exactly length 3 from vi to
v j.
1 1 0 0 1 1 0 1 1 2 0 1
2
A = 0 1 0 1 3
A = 1 1 0 0 4
A = 1 1 0 1
1 2 0 1 2 2 0 1 2 3 0 2
1 1 0 0 0 1 0 1 1 1 0 0
16. Which are the basic traversing techniques of the Graph? Write the
algorithm of them.
Most graph problems involve traversal of a graph. Traversal of a graph means visit each node exactly
once.
Two commonly used graphs traversal techniques are
1. Depth First Search (DFS)
2. Breadth First Search (BFS)
1
DFS (G, 1) is given by
a) Visit (1)
2 5
3 4 b) DFS (G, 2)
DFS (G, 3)
DFS (G, 4)
6 7 DFS (G, 5)
Since graph can have cycles, we must avoid re-visiting a node. To do this when we visit a vertex V,
we marks it visited as visited should not be selected for traversal.
This procedure traverse the graph G in DFS manner. V is a starting vertex to be explored. S is a
Stack, visited[] is an array which tells you whether particular vertex is visited or not. W is a
adjacent node of vertex V. PUSH and POP are functions to insert and remove from stack
respectively.
2 5
3 4
BFS traversal of given graph is:
1 | 2, 3, 4, 5 | 6, 7 | 8
6 7
This procedure traverse the graph G in BFS manner. V is a starting vertex to be explored. Q is a
queue, visited[] is an array which tells you whether particular vertex is visited or not. W is a
adjacent node of vertex V.
1. Initialize Q
2. [Marks visited of V as 1]
visited [v] 1
3. [Add vertex v to Q]
InsertQueue(V)
4. [Repeat while Q is not empty]
Repeat while Q is not empty
v RemoveFromQueue()
For all vertices W adjacent to v
if visited[w] is 0
then visited[w] 1
InsertQueue(w)
A Spanning tree of a graph is an undirected tree consisting of only those edges necessary to connect all
the nodes in the original graph
A spanning tree has the properties that
o For any pair of nodes there exists only one path between them
o Insertion of any edge to a spanning tree forms a unique cycle
The particular Spanning for a graph depends on the criteria used to generate it.
If DFS search is use, those edges traversed by the algorithm forms the edges of tree, referred to as
Depth First Spanning Tree.
If BFS Search is used, the spanning tree is formed from those edges traversed during the search,
producing Breadth First Search Spanning tree.
V0
V1 V2
V3 V4 V5 V6
V7
V0
V0
V1 V2
V1 V2
V3 V4 V5 V6
V3 V4 V5 V6
V7
V7
18. Consider the graph shown in Fig Find depth-first and breadth first
traversals of this graph starting at A
B C
E
D
F
A A
B C B C
E E
D D
F F
DFS : A B D C F E BFS : A B C D F E
19. Define spanning tree and minimum spanning tree. Find the minimum
spanning tree of the graph shown in Fig.
A 5
4
C D
1
Step 1: Taking minimum weight edge of all Adjacent Step 2: Taking minimum weight edge of all Adjacent A–B|4
edges of X = { A } edges of X = { A , B }
A–E|5
A–C|6
A A
4 4 A–D|6
B–E|3
B X={A,B}
B B–C|2
X={A,B,C} C–E|6
2
C–D|1
C D–E|7
Step 3: Taking minimum weight edge of all Adjacent Step 4: Taking minimum weight edge of all Adjacent
edges of X = { A , B , C } edges of X = { A , B , C , D }
4
A 4
A
3
B B E
X = { A , B , C, D }
2 2
C 1 D C 1
D
X = { A , B , C, D, E }
All nodes of graph are there with set X, so we obtained minimum spanning tree of cost: 4 + 2 + 1 + 3 = 10
A 5
4
B
3 E
Using Kruskal’s Algorithm
6
2 5 6 7
C D
1
Step 1: Taking min edge (C,D) Step 2: Taking next min edge (B,C) Step 3: Taking next min edge (B,E)
3
B B E
2 2
C 1
D
C 1 D C 1 D
Step 4: Taking next min edge (A,B) Step 5: Taking next min edge (A,E) it forms cycle so do not consider
Step 6: Taking next min edge (C,E) it forms cycle so do not consider
4
A Step 7: Taking next min edge (A,D) it forms cycle so do not consider
Step 8: Taking next min edge (A,C) it forms cycle so do not consider
3 Step 9: Taking next min edge (E,D) it forms cycle so do not consider
B E
All edges of graph has been visited,
2
so we obtained minimum spanning tree of cost:
C D 4 + 2 + 1 + 3 = 10
1
20. Give example and applications of directed and undirected graphs. Find
the adjacency matrix for the graph shown in Fig.
Applications of graph:
Electronic Circuits
o Printed Circuit Board
o Integrated Circuit
Transportation networks
o Highway networks
Modeling a road network with vertexes as towns and edge costs as distances.
o Water Supply networks
Modeling a water supply network. A cost might relate to current or a function of capacity and
length. As water flows in only 1 direction, from higher to lower pressure connections or
downhill, such a network is inherently an acyclic directed graph.
o Flight network
Minimizing the cost and time taken for air travel when direct flights don't exist between starting
and ending airports.
Computer networks
o Local Area Network
o Internet
Dynamically modeling the status of a set of routes by which traffic might be directed over the
Internet.
o Web
Using a directed graph to map the links between pages within a website and to analyze ease of
navigation between different parts of the site.
Databases
o Entity Relationship Diagram
21. Apply Dijkstra’s algorithm to find shortest path between vertex A and
vertex F5 for the graph shown in Fig.
2
1 B D 6
4
A 1 7
F
3 2
C E
5
Step 1: Traverse all adjacent node of A Step 2: Traverse all adjacent node of B
1 ∞ 1 3
2 2
1 B D 6 1 B D 6
0 4 0 4
A 1 7 ∞ A 1 7 ∞
F F
3 2 3 2
3
C E 3
C E
5 5
∞ 5
Step 3: Traverse all adjacent node of C Step 4: Traverse all adjacent node of D
3 1 3
1
2 2
1 B D 1 B D 6
6
4 0 4
0 A 7 A 1 7 9
1
F ∞ F
3 2 3 2
C E 3
C E
3 5 5
5 5
Hashing
What is Hashing?
Sequential search requires, on the average O(n) comparisons to locate an element. So many
comparisons are not desirable for a large database of elements.
Binary search requires much fewer comparisons on the average O (log n) but there is an additional
requirement that the data should be sorted. Even with best sorting algorithm, sorting of elements
require 0(n log n) comparisons.
There is another widely used technique for storing of data called hashing. It does away with the
requirement of keeping data sorted (as in binary search) and its best case timing complexity is of
constant order (0(1)). In its worst case, hashing algorithm starts behaving like linear search.
Best case timing behavior of searching using hashing = O( 1)
Worst case timing Behavior of searching using hashing = O(n)
In hashing, the record for a key value "key", is directly referred by calculating the address from the key
value. Address or location of an element or record, x, is obtained by computing some arithmetic
function f. f(key) gives the address of x in the table.
Record
0
1
f()Address
2
3
4
5
6
Hash Table
Mapping of Record in hash table
Hashing
B-1
The basic idea is that the records [elements] are partitioned into B classes, numbered 0,1,2 … B-l
A Hashing function f(x) maps a record with key n to an integer value between 0 and B-l.
Each bucket in the bucket table is the head of the linked list of records mapped to that bucket.
Hashing
Hashing Functions
Characteristics of a Good Hash Function
1. Division-Method
2. Midsquare Methods
3. Folding Method
4. Digit Analysis
5. Length Dependent Method
6. Algebraic Coding
7. Multiplicative Hashing
1. Division-Method
In this method we use modular arithmetic system to divide the key value by some integer divisor m
(may be table size).
It gives us the location value, where the element can be placed.
We can write,
L = (K mod m) + 1
where L => location in table/file
K => key value
m => table size/number of slots in file
Suppose, k = 23, m = 10 then
L = (23 mod 10) + 1= 3 + 1=4, The key whose value is 23 is placed in 4th location.
2. Midsquare Methods
In this case, we square the value of a key and take the number of digits required to form an address,
from the middle position of squared value.
Suppose a key value is 16, then its square is 256. Now if we want address of two digits, then you
select the address as 56 (i.e. two digits starting from middle of 256).
3. Folding Method
Most machines have a small number of primitive data types for which there are arithmetic
instructions.
Frequently key to be used will not fit easily in to one of these data types
It is not possible to discard the portion of the key that does not fit into such an arithmetic data type
Prof. Pradyumansinh Jadeja (9879461848) | 2130702 – Data Structure 3
Hashing
The solution is to combine the various parts of the key in such a way that all parts of the key affect
for final result such an operation is termed folding of the key.
That is the key is actually partitioned into number of parts, each part having the same length as that
of the required address.
Add the value of each parts, ignoring the final carry to get the required address.
This is done in two ways :
o Fold-shifting: Here actual values of each parts of key are added.
Suppose, the key is : 12345678, and the required address is of two digits,
Then break the key into: 12, 34, 56, 78.
Add these, we get 12 + 34 + 56 + 78 : 180, ignore first 1 we get 80 as location
o Fold-boundary: Here the reversed values of outer parts of key are added.
Suppose, the key is : 12345678, and the required address is of two digits,
Then break the key into: 21, 34, 56, 87.
Add these, we get 21 + 34 + 56 + 87 : 198, ignore first 1 we get 98 as location
4. Digit Analysis
This hashing function is a distribution-dependent.
Here we make a statistical analysis of digits of the key, and select those digits (of fixed position)
which occur quite frequently.
Then reverse or shifts the digits to get the address.
For example, if the key is : 9861234. If the statistical analysis has revealed the fact that the third and
fifth position digits occur quite frequently, then we choose the digits in these positions from the key.
So we get, 62. Reversing it we get 26 as the address.
6. Algebraic Coding
Here a n bit key value is represented as a polynomial.
The divisor polynomial is then constructed based on the address range required.
The modular division of key-polynomial by divisor polynomial, to get the address-polynomial.
Let f(x) = polynomial of n bit key = a1 + a2x + ……. + anxn-1
d(x) = divisor polynomial = x1 + d1 + d2x + …. + d1x1-1
then the required address polynomial will be f(x) mod d(x)
7. Multiplicative Hashing
This method is based on obtaining an address of a key, based on the multiplication value.
Hashing
If k is the non-negative key, and a constant c, (0 < c < 1), compute kc mod 1, which is a fractional part of
kc.
Multiply this fractional part by m and take a floor value to get the address
( )
0 < h (k) < m
1. Separate chaining
In this strategy, a separate list of all elements mapped to the same value is maintained.
Separate chaining is based on collision avoidance.
If memory space is tight, separate chaining should be avoided.
Additional memory space for links is wasted in storing address of linked elements.
Hashing function should ensure even distribution of elements among buckets; otherwise the timing
behavior of most operations on hash table will deteriorate.
Hashing
List of Elements
0 10 50
2 12 32 62
4 4 24
7 7
9 9 69
Example : The integers given below are to be inserted in a hash table with 5 locations using
chaining to resolve collisions. Construct hash table and use simplest hash function. 1, 2, 3, 4, 5,
10, 21, 22, 33, 34, 15, 32, 31, 48, 49, 50
An element can be mapped to a location in the hash table using the mapping function key % 10.
Hashing
Hash Table
0 5 10 15 50
1 1 21 31
2 2 22 32
3 3 33 48
4 4 34 49
2. Open Addressing
Separate chaining requires additional memory space for pointers. Open addressing hashing is an
alternate method of handling collision.
In open addressing, if a collision occurs, alternate cells are tried until an empty cell is found.
a. Linear probing
b. Quadratic probing
c. Double hashing.
a) Linear Probing
In linear probing, whenever there is a collision, cells are searched sequentially (with
wraparound) for an empty cell.
Fig. shows the result of inserting keys {5,18,55,78,35,15} using the hash function (f(key)=
key%10) and linear probing strategy.
Hashing
When many keys are mapped to the same location (clustering), linear probing will not
distribute these keys evenly in the hash table. These keys will be stored in neighborhood of
the location where they are mapped. This will lead to clustering of keys around the point of
collision
b) Quadratic probing
One way of reducing "primary clustering" is to use quadratic probing to resolve collision.
Suppose the "key" is mapped to the location j and the cell j is already occupied. In quadratic
probing, the location j, (j+1), (j+4), (j+9), ... are examined to find the first empty cell where the
key is to be inserted.
This table reduces primary clustering.
It does not ensure that all cells in the table will be examined to find an empty cell. Thus, it may
be possible that key will not be inserted even if there is an empty cell in the table.
c) Double Hashing
This method requires two hashing functions f1 (key) and f2 (key).
Problem of clustering can easily be handled through double hashing.
Function f1 (key) is known as primary hash function.
In case the address obtained by f1 (key) is already occupied by a key, the function f2 (key) is
evaluated.
The second function f2 (key) is used to compute the increment to be added to the address
obtained by the first hash function f1 (key) in case of collision.
The search for an empty location is made successively at the addresses f1 (key) + f2(key),
f1 (key) + 2f2 (key), f1 (key) + 3f2(key),...
File
What is File?
A file is a collection of records where a record consists of one or more fields. Each contains the same
sequence of fields.
Each field is normally of fixed length.
A sample file with four records is shown below:
Sequential Files
It is the most common type of file. In this type of file:
File
Block 1
Name Roll No. Year Marks
AMIT 1000 1 82
KALPESH 1005 2 54
JITENDRA 1009 1 75
RAVI 1010 1 79
Block 2
NILESH 1011 2 89
Some blocks of an ordered (sequential) file of students records with Roll no. as the ordering field
File
The blocks making up each bucket could either be contiguous blocks or they can be chained together in
a linked list.
Translation of bucket number to disk block address is done with the help of bucket directory. It gives the
address of the first block of the chained blocks in a linked list.
Hashing is quite efficient in retrieving a record on hashed key. The average number of block accesses for
retrieving a record.
Thus the operation is b times faster (b = number of buckets) than unordered file.
To insert a record with key value x, the new record can added to the last block in the chain for bucket
f(x). If the record does not fit into the existing block, record is stored in a new block and this new block is
added at the end of the chain for bucket f(x).
A well designed hashed structure requires two block accesses for most operations
Bucket 0
230
0 460 480
580 790
1
850
2
Bucket 1
321
531
651
Bucket 2
232
582 510
b-1
Bucket
Directory
Hashing with buckets of chained blocks
Indexing
Indexing is used to speed up retrieval of records.
File
It is done with the help of a separate sequential file. Each record of in the index file consists of two
fields, a key field and a pointer into the main file.
To find a specific record for the given key value, index is searched for the given key value.
Binary search can used to search in index file. After getting the address of record from index file, the
record in main file can easily be retrieved.
Search
Main File
Key Pointer
Name Roll No Year Marks
1000
1010 AMIT 1010 1 70
Index file is ordered on the ordering key Roll No. each record of index file points to the corresponding
record. Main file is not sorted.
File
With indexing, new records can be added at the end of the main file. It will not require movement of
records as in the case of sequential file. Updation of index file requires fewer block accesses compare to
sequential file
Types of Indexes:
1. Primary indexes
2. Clustering indexes
3. Secondary indexes
File
101
201 200
351 201
350
351
805 400
905
805
Index File
904
Data File
Primary Index on ordering key field roll number
Clustering Indexes
If records of a file are ordered on a non-key field, we can create a different type of index known as
clustering index.
A non-key field does not have distinct value for each record.
A Clustering index is also an ordered file with two fields.
File
Field
Value Block Pointer 100 Math
106
105
108
105
109
106
Index File
106
108
108
109
109
File
11 15
12 18
13
12
14
1
15
19
16
8
17
18 9
19 11
20 16
Index File
20
Data File
Bubble sort
Bubble sort, sometimes referred as sinking sort.
It is a simple sorting algorithm that works by repeatedly stepping through the list to be sorted,
comparing each pair of adjacent items and swapping them if they are in the wrong order.
The pass through the list is repeated until no swaps are needed, which indicates that the list is
sorted.
The algorithm gets its name from the way smaller elements "bubble" to the top of the list.
As it only uses comparisons to operate on elements, it is a comparison sort.
Although the algorithm is simple, it is too slow for practical use, even compared to insertion sort.
Algorithm
for i ← 1 to n do
for j ← 1 to n-i do
If Array[j] > Array[j+1] then /* For decreasing order use < */
temp ← Array[j]
Array[j] ← A [j+1]
Array[j+1] ← temp
Program
#include <stdio.h>
void main()
{
int array[100], n, i, j, temp;
printf("Enter number of elements\n");
scanf("%d", &n);
printf("Enter %d integers\n", n);
for (i = 0; I < n; i++)
{
scanf("%d", &array[i]);
}
for (i = 0 ;i< ( n - 1 );i++)
{
for (j = 0 ; j< n - c - 1; j++)
{
if (array[j] > array[j+1]) /* For decreasing order use < */
{
Prof. Pradyumansinh Jadeja (9879461848) | 2130702 – Data Structure 1
temp = array[j];
array[j] = array[j+1];
array[j+1] = temp;
}
}
}
printf("Sorted list in ascending order:\n");
for (i = 0 ;i< n ;i++ )
{
printf("%d\n", array[i]);
}
getch();
}
Example
Consider an array A of 5 element
A[0] 45
A[1] 34
A[2] 56
A[3] 23
A[4] 12
At the end of first pass the largest element of the array, 56, is bubbled up to the last position in the
array as shown.
45 34 34 34 34
34 45 45 45 45
56 56 56 23 23
23 23 23 56 12
12 12 12 12 56 Largest element
34 34 34 34
45 45 23 23
23 23 45 12
34 23 23
23 34 12
56 56 56
23 12
12 23
34 34
Sorted Array
45 45
56 56
Selection Sort
The idea of algorithm is quite simple.
Array is imaginary divided into two parts - sorted one and unsorted one.
At the beginning, sorted part is empty, while unsorted one contains whole array.
At every step, algorithm finds minimal element in the unsorted part and adds it to the end of the sorted one.
When unsorted part becomes empty, algorithm stops.
Algorithm
SELECTION_SORT (A)
for i ← 1 to n-1 do
min ← i;
for j ← i + 1 to n do
If A[j] < A[i] then
min ← j
If min!=i then
temp ← A[i]
A[i] ← A [min]
A[min] ← temp
Program
#include <stdio.h>
void main()
{
int array[100], n, i, j, min, temp;
printf("Enter number of elements\n");
scanf("%d", &n);
printf("Enter %d integers\n", n);
for ( i = 0 ; i < n ; i++ )
{
scanf("%d", &array[i]);
}
for ( i = 0 ; i < ( n - 1 ) ; i++ )
{
min = i;
for ( j = i + 1 ; j < n ; j++ )
{
if ( array[min] > array[j] )
min = j;
}
Prof. Pradyumansinh Jadeja (9879461848) | 2130702 – Data Structure 5
if ( min != i )
{
temp = array[i];
array[i] = array[min];
array[min] = temp;
}
}
printf("Sorted list in ascending order:\n");
for ( i = 0 ; i < n ; i++ )
{
printf("%d\n", array[i]);
}
getch();
}
Example
Unsorted Array
Step – 1: 5 1 12 -5 16 2 12 14
Step – 5: -5 1 2 5 16 12 12 14 No Exchange
Quick Sort
Quicksort is the currently fastest known sorting algorithm and is often the best practical choice for sorting,
as its average expected running time is O(n log(n)).
Pick an element, called a pivot, from the array.
Reorder the array so that all elements with values less than the pivot come before the pivot, while all
elements with values greater than the pivot come after it (equal values can go either way). After this
partitioning, the pivot is in its final position. This is called the partition operation.
Recursively apply the above steps to the sub-array of elements with smaller values and separately to the
sub-array of elements with greater values.
Quicksort, like merge sort, is a divide-and-conquer recursive algorithm.
The basic divide-and-conquer process for sorting a sub array A[i..j] is summarized in the following three easy
steps:
o Divide: Partition T[i..j] Into two sub arrays T[i..l-1] and T[l+1… j] such that each element of T[i..l-1] is
less than or equal to T[l], which is, in turn, less than or equal to each element of T[l+1… j]. Compute the
index l as part of this partitioning procedure
o Conquer: Sort the two sub arrays T[i..l-1] and T[l+1… j] by recursive calls to quicksort.
o Combine: Since the sub arrays are sorted in place, no work is needed to combing them: the entire array
T[i..j] is now sorted.
Algorithm
Procedure pivot (T [i… j]; var l)
{Permutes the elements in array T [i… j] and returns a value l such that, at the end, i<=l<=j,
T[k] <=P for all i ≤ k < l, T[l] =P, and T[k] > P for all l < k ≤ j, where P is the initial value T[i]}
P ← T[i]
K ← i; l ← j+1
Repeat k ← k+1 until T[k] > P
Repeat l ← l-1 until T[l] ≤ P
While k < l do
Swap T[k] and T[l]
Repeat k ← k+1 until T[k] > P
Repeat l ← l-1 until T[l] ≤ P
Swap T[i] and T[l]
Program
#include<stdio.h>
void quicksort(int [10],int,int);
int partition(int [10],int, int);
void main()
{
int x[20],size,i;
quicksort(x,0,size-1);
value=x[r];
i=p-1;
for(j=p;j<=r-1;j++)
{
If(x[j] ≤value)
{
i=i+1;
temp=x[i];
x[i]=x[j];
x[j]=temp;
}
}
temp=x[i+1];
x[i]=x[r];
x[r]=temp;
Return (i+1);
}
Example
i P,j r
(a) 2 8 7 1 3 5 6 4
P,i j r
(b) 2 8 7 1 3 5 6 4
P,i j r
(c) 2 8 7 1 3 5 6 4
P,i j r
(d) 2 8 7 1 3 5 6 4
Exchange 8 and 1
P i j r
(e) 2 1 7 8 3 5 6 4
P i j r Exchange 7 and 3
(f) 2 1 3 8 7 5 6 4
P i j r
(g) 2 1 3 8 7 5 6 4
P i r
(h) 2 1 3 8 7 5 6 4
Exchange 8 and 4
P i r
(i) 2 1 3 4 7 5 6 8
2 1 3 4 7 5 6 8
Left Sub Array Right Sub Array
Apply same method for left and right sub array finally we will get sorted
Merge Sort
The merge sort algorithm is based on the classical divide-and-conquer paradigm. It operates as follows:
o DIVIDE: Partition the n-element sequence to be sorted into two subsequences of n/2 elements each.
o CONQUER: Sort the two subsequences recursively using the merge sort.
o COMBINE: Merge the two sorted subsequences of size n/2 each to produce the sorted sequence
consisting of n elements.
Note that recursion "bottoms out" when the sequence to be sorted is of unit length.
Since every sequence of length 1 is in sorted order, no further recursive call is necessary.
The key operation of the merge sort algorithm is the merging of the two sorted sub sequences in the
"combine step".
To perform the merging, we use an auxiliary procedure Merge (A,p,q,r), where A is an array and p,q and r
are indices numbering elements of the array such that procedure assumes that the sub arrays A[p..q] and
A[q+1...r] are in sorted order.
It merges them to form a single sorted sub array that replaces the current sub array A[p..r]. Thus finally, we
obtain the sorted array A[1..n], which is the solution.
Algorithm
MERGE (A,p,q,r)
n1 = q -p + 1
n2 = r – q
let L[1…n1+1] and R[1…n2+1] be new arrays
for i = 1 to n1
L[i] = A[p+i-1]
for j = 1 to n2
R[j] = A[q+j]
L[n1+1] = infinite
R[n2+1]= infinite
i=1
j=1
for k = p to r
if L[i] ≤ R[j]
A[k]=L[i]
i = i +1
else A[k] = R[j]
j=j+1
Program
#include<stdio.h>
void mergesort(int [20],int,int);
int merge(int [20],int, int, int);
void main()
{
int x[20],size,i;
mergesort(x,0,size-1);
{
q=(p+r)/2;
mergesort(x,p,q);
mergesort(x,q+1,r);
merge(x,p,q,r)
}
}
int merge(int x[20],int p,int q,int r)
{
Int n1,n2,L[20],R[20],i,j,k;
n1 = q -p + 1;
n2 = r – q;
for(i=1; i<=n1;i++)
{
L[i]=x[p+i-1];
}
for(j=1; i<=n2;j++)
{
R[j]=x[q+j];
}
L[n1+1]=NULL;
L[n2+1]=NULL;
I=1;
J=1;
For(k=p;k<=r;k++)
{
If(L[i]<=R[j])
{
X[k]=L[i];
I++;
}
Else
{
x[k] = R[j];
j++;
}
}
}
Example
38 27 43 3 9 82 10
38 27 43 3 9 82 10
38 27 43 3 9 82 10
38 27 43 3 9 82 10
27 38 3 43 9 82 10
3 27 38 43 9 10 82
3 9 10 27 38 43 82
Linear/Sequential Search
In computer science, linear search or sequential search is a method for finding a particular value in a list that
consists of checking every one of its elements, one at a time and in sequence, until the desired one is found.
Linear search is the simplest search algorithm.
It is a special case of brute-force search. Its worst case cost is proportional to the number of elements in the
list.
Algorithm
Algorith: Linear_Search
for i = 0 to last index of A:
if A[i] equals key:
return i
return -1
Program
#include <stdio.h>
void main()
{
int array[100], key, i, n;
Example
(a) 2 9 3 1 8
(b) 2 9 3 1 8
(c) 2 9 3 1 8
Binary Search
If we have an array that is sorted, we can use a much more efficient algorithm called a Binary Search.
In binary search each time we divide array into two equal half and compare middle element with search
element.
If middle element is equal to search element then we got that element and return that index otherwise if
middle element is less than search element we look right part of array and if middle element is greater than
search element we look left part of array.
Algorithm
Program
#include <stdio.h>
void main()
{
int i, first, last, middle, n, key, array[100];
first = 0;
last = n - 1;
middle = (first+last)/2;
Example