Professional Documents
Culture Documents
KKP-BDS Lecture Notes
KKP-BDS Lecture Notes
Syllabus:
Introduction: Data Types, Data structures, Types of data structures, Operations, ADTs,
Algorithms, Comparison of Algorithms, Complexity, Time and space trade off.
Recursion: Introduction, format of recursive functions, recursion Vs. iteration, examples
1. INTRODUCTION
1.1 DATA TYPES
The following are the different data types in C Programming.
Variables:
Variables in a c programming language are the named memory locations where the user can
store different values of the same data type during the program execution.In other words, a
variable can be defined as a storage container to hold values of the same data type.
Every variable must be declared in the declaration section before it is used.Every variable
must have a data type that determinesthe range and type of values be stored andthe size of
the memory to be allocated.A variable name may contain letters, digits and underscore
symbol.
The following are the rules to specify a variable name...
Variable name should not start with a digit.
Keywords should not be used as variable names.
A variable name should not contain any special symbols except underscore(_).
A variable name can be of any length but compiler considers only the first 31
characters of the variable name.
Declaration of a variable:
Declaration of a variable tells the compiler to allocate the required amount of memory with
the specified variable name and allows only specified data type values into that memory
location.
In C programming language, the declaration can be performed either before the function as
global variables or inside any block or function.But it must be at the beginning of block or
function.
Declaration Syntax:
Datatype variableName;
Example:
int number;
the compiler that allocates 2 bytes of memory with the name number and allows only
integer values into that memory location
15-1
to2 ).
If it takes 4 bytes (32 bits), then the possible values are between-2,147,483,648 and
31 31-1
+2,147,483,647 (- 2 to2 ).
Depending on the organization of the elements, data structures are classified into two types:
1.3.1 Linear data structures
If the elements of a data structure are stored in a linear or sequential order, then it is a linear
data structure.
Examples: arrays, linked lists, stacks, and queues.
Linear data structures can be represented in memory in two different ways. One way is to
have to a linear relationship between elements by means of sequential memory locations.
The other way is to have a linear relationship between elements by means of links.
Elements are accessed in a sequential order but it is not compulsory to store allelements
sequentially.
Arrays:
An array is a collection of similar data elements. These data elements have the same data
type.
The elements of the array are stored in consecutive memory locations and are referenced by
an index (also known as the subscript).
In C, arrays are declared using the following syntax:
type name[size];
Example: int marks[10];
The above statement declares an array marks that contains 10 elements. In C, the array in-
dex starts from zero. This means that the array marks will contain 10 elements in all. The
first element will be stored in marks[0], second element in marks[1], so on and so forth.
Therefore, the last element, that is the 10th element, will be stored in marks[9]. In the mem -
ory, the array will be stored as shown in Fig. 1.4.
Stacks:
A stack is a linear data structure in which insertion and deletion of elements are done at
only one end, which is known as the top of the stack. Stack is called a last-in, first-out
(LIFO) structure because the last element which is added to the stack is the first element
which is deleted from the stack.
In the computer’s memory, stacks can be implemented using arrays or linked lists. Fig.1.6
shows the array implementation of a stack. Every stack has a variable top associated with
it, top is used to store the address of the topmost element of the stack. It is this position
from where the element will be added or deleted. There is another variable MAX, which is
used to store the maximum number of elements that the stack can store.
Graphs:
A graph is a non-linear data structure which is a collection of vertices (alsocalled nodes)
and edges that connect these vertices.
A graph is often viewed
1. As a generalization of the tree structure, where instead of a purely parent-to-child re-
lationshipbetween tree nodes, any kind of complex relationships between the nodes
can exist.
2. In a tree structure, nodes can have any number of children but only one parent, a
graph on theother hand relaxes all such kinds of restrictions.
Fig.1.9 shows a graph with five nodes.
Figure 1.9Graph
A node in the graph may represent a city and the edges connecting the nodes can represent
roads. A graph can also be used to represent a computer network where the nodes are work-
stations andthe edges are the network connections.
Advantage: Best models real-world situations
Disadvantage: Some algorithms are slow and very complex
1.6 ALGORITHMS
Let us consider the problem of preparing an omelette.
To prepare an omelette, we follow thesteps given below:
1. Get the frying pan.
2. Get the oil.
3. Do we have oil?
4. If yes, put it in the pan.
5. If no, do we want to buy oil?
6. If yes, then go out and buy.
7. If no, we can terminate.
8. Turn on the stove, etc...
For a given problem (preparing an omelette), we are providing a step-by step procedure for
solving it.
The formal definition of an algorithm can be stated as:
An algorithm is the step-by-step unambiguous instructions to solve a given problem
Definition: An algorithm is a finite set of instructions which, if followed, accomplish a par-
ticular task.
In addition every algorithm must satisfy the following criteria:
(i) input: there are zero or more quantities which are externally supplied;
(ii) output: at least one quantity is produced;
(iii) definiteness: each instruction must be clear and unambiguous;
(iv) finiteness: if we trace out the instructions of an algorithm, then for all cases the algo-
rithm will
terminate after a finite number of steps;
(v) effectiveness: every instruction must be sufficiently basic that it can in principle be car-
ried out by a person using only pencil and paper. It is not enough that each operation be
definite as in (iii), but it must also be feasible.
An algorithm can be described in many ways. A natural language such as English can be
used but we must be very careful that the resulting instructions are definite (condition iii)
As an example,n 4,2 n2, 100 and 500 are the individual costs of some function and
approximate to n 4since is the highest rate of growth.
Commonly Used Rates of Growth:
Decision:
Decision statements are used when the execution of a process depends on the outcome of
some condition. For example, if x = y, then print EQUAL
So the general form of IF construct can be given as:
IF condition Then process
A condition may evaluate to either a true value or a false value.
In the above example, a variable x can be either equal to y or not equal to y. However, it
cannot be both true and false.If the condition is true, and then the process is executed.
A decision statement can also be stated in the following manner:
IF condition Then process1 ELSE process2
This form is popularly known as the IF–ELSE construct.Here, if the condition is true, then
process1 is executed, else process2 is executed.
Repetition:
It involves executing one or more steps for a number of times, it can be implemented using
constructs such as while, do–while, and for loops. These loops execute one or more times
until some condition is true.
Algorithm to test for equality of Algorithm to print the first 10 natural numbers
two numbers
Programming
Comparison of Algorithms examples :gramming Examples
1. Write an algorithm for swapping two values.
Step 1: Input first number as A
Step 2: Input second number as B
Step 3: SET TEMP = A
Step 4: SET A = B
Step 5: SET B = TEMP
Step 6: PRINT A, B
Step 7: END
For a given algorithm, we can represent the best, worst and average cases in the form of
expressions.
As an example, let f(n) be the function which represents the given algorithm.
when n = 1000 , the number of iterations can be given by log 1000 which is approximately
equal to 10.
The efficiency of loops in which iterations divide or multiply the loop-controlling variables
can be given as
f(n) = log n
Dependent quadratic loop:
In a dependent quadratic loop, the number of iterations in the inner loop is dependent on the
outer loop.
Consider the code given below:
for(i=0;i<10;i++)
for(j=0; j<=i;j++)
statement block;
In this code, the inner loop will execute just once in the first iteration, twice in the second
iteration, thrice in the third iteration, so on and so forth.
In this way, the number of iterations can be calculated as 1 + 2 + 3 + ... + 9 + 10 = 55 ,If we
calculate the average of this loop (55/10 = 5.5), the inner loop iterates (n+ 1)/2 times.
Therefore, the efficiency of such a code can be given as
f(n) = n (n + 1)/2
Nested Loops:
Loops that contain loops are known as nested loops.
In order to analyse nested loops, we need to determine the number of iterations each loop
completes.
The total is then obtained as the product of the number of iterations in the inner loop and the
number of iterations in the outer loop.
In this case, we analyse the efficiency of the algorithm based on whether it is a linear
logarithmic, quadratic, or dependent quadratic nested loop.
Logarithmic Loops:
This inner loop is controlled by an outer loop which iterates 10 times. Therefore, according
to the formula, the number of iterations for this code can be given as 10 log 10.
Fro Example,
for(i=0;i<10;i++)
for(j=1; j<10;j*=2)
statement block;
In more general terms, the efficiency of such loops can be given as
f(n) = n log n .
Quadratic loops:
In a quadratic loop, the number of iterations in the inner loop is equal to the number of
iterations in the outer loop.
Consider the following code in which the outer loop executes 10 times and for each
iteration of the outer loop, the inner loop also executes 10 times.Therefore, the efficiency
here is 100.
for(i=0;i<10;i++)
for(j=0; j<10;j++)
statement block;
The generalized formula for quadratic loop can be given as
2
f (n)=n
Dependent quadratic loop:
In a dependent quadratic loop, the number of iterations in the inner loop is dependent on the
outer loop.Consider the code given below:
for(i=0;i<10;i++)
for(j=0; j<=i;j++)
statement block;
In this code, the inner loop will execute just once in the first iteration, twice in the second
iteration, thrice in the third iteration, so on and so forth.In this way, the number of iterations
can be calculated as 1 + 2 + 3 + ... + 9 + 10 = 55 ,If we calculate the average of this loop
(55/10 = 5.5),it is equal to the number of iterations in the outer loop (10) plus 1 divided by
2.the inner loop iterates (n+ 1)/2 times.
Therefore, the efficiency of such a code can be given as
f(n) = n (n + 1)/2
It means that for large amounts of data, f(n) will grow no more than a constant factor than
g(n) .Hence, g provides an upper bound. Note that here c is a constant which depends on the
following factors:
o the programming language used,
o the quality of the compiler or interpreter,
o the CPU speed,
o the size of the main memory and the access time to it,
o the knowledge of the programmer
Hence, we can say that Ω(g(n)) comprises a set of all the functions f(n) that are greater than
or equal to cg(n) for all values of n ≥ n0.
Our objective is to give the largest rate of growth g(n) which is less than or equal to the
given algorithm’s rate of growth f(n).
Ω Examples
Example-1 Find lower bound for f(n) = 5n2.
Solution: ∃c, n 0Such that: 0 ≤ cn2≤ 5n2⇒cn2 ≤ 5n2⇒c = 5 and n 0 = 1
∴5n2 = Ω(n2) with c = 5 and n 0 = 1
Example-2
f (n)=2 n+3
Solution:2 n+3 ≥ 1n , ∀ n ≥1
∴ f (n)=Ω(n)
Or
It can also be
f (n)=O(log n)
But f (n)≠ O(n2)
n
f (n)≠ O(2 )
Since Big-Ω represents lower bound, the time complexities before n, only allowed.
This notation decides whether the upper and lower bounds of a given function (algorithm)
are the same. The average running time of an algorithm is always between the lower bound
and the upper bound. If the upper bound (O) and lower bound (Ω) give the same result, then
the Θ notation will also have the same rate of growth.
Θ Examples
Example-2
f (n)=2 n+3
Solution:
1 n ≤2 n+3 ≤ 5 n , ∀ n ≥ 1
∴ f (n)=Ω(n)
and
f (n)≠ O(log n)
or f (n)≠ O(n2)
n
f (n)≠ O(2 )
Nested loops: Analyze from the inside out. Total running time is the product of the
sizes of all the loops.
2. RECURSION
2.1 INTRODUCTION
Any function which calls itself is called recursive function.
Recursion in the data structure can be defined as a method through which problems are
broken down into smaller sub-problems to find a solution. This is done by replicating the
function on a smaller scale, making it call itself and then combining them together to solve
problems.
In recursion, a function α either calls itself directly or calls a function β that in turn calls
the original function α. The function α is called recursive function.
Example − a function calling itself.
int function(int value) {
if(value < 1)
return;
function(value - 1);
printf("%d ",value);
}
Example − a function that calls another function which in turn calls it again.
int function1(int value1) {
if(value1 < 1)
return;
function2(value1 - 1);
printf("%d ",value1);
}
int function2(int value2) {
function1(value2);
}
The recursion step can result in many more such recursive calls. It is important to ensure
that the recursion terminates.
As an example consider the factorial function: n! is the product of all integers between n
and 1.The definition of recursive factorial looks like:
n !=1if n=0
n !=n∗( n−1 ) ! ifn>0
This definition can easily be converted to recursive implementation. Here the problem is de-
termining the value of n!, and the sub problem is determining the value of (n – l)!.
In the recursive case, when n is greater than 1, the function calls itself to determine the
value of (n – l)! and multiplies that with n.
In the base case, when n is 0 or 1, the function simply returns 1. This looks like the
following:
//calculates factorial of a positive integer
int Fact(int n){
if ( n= =1) //base case: fact of 0 or 1 is 1
return 1;
else if ( n= =0)
return 1;
else //recursive case: multiply n by (n-1) factorial
return n*Fact(n-1);
}
For this example, if we call the print function with n=4, visually our memory assignments
may look like:
2.3 RECURSION VERSUS ITERATION
A recursive approach makes it simpler to solve a problem that may not have the most obvi-
ous of answers. But, recursion adds overhead for each recursive call (needs space on the
stack frame).
Recursion
•Terminates when a base case is reached.
• Each recursive call requires extra space on the stack frame (memory).
• If we get infinite recursion, the program may run out of memory and result in stack
overflow.
• Solutions to some problems are easier to formulate recursively.
Iteration
• Terminates when a condition is proven to be false.
• Each iteration does not require extra space.
• An infinite loop could loop forever since there is no extra memory being created.
• Iterative solutions to a problem may not always be as obvious as a recursive solution.
Some problems are best suited for recursive solutions while others are not.
Difference between recursion and iteration
Iteration Recursion
In iteration, a problem is converted into aRecursion is like piling all of those steps on top
train of steps that are finished one at a time, of each other and then quashing the mall into
one after another the solution.
In recursion, each step replicates itself at a
With iteration, each step clearly leads on to
smaller scale, so that all of them combined
the next, like stepping stones across a river
together eventually solve the problem.
Not all recursive problem can solved by
Any iterative problem is solved recursively
iteration
It does not use Stack It uses Stack
Problem-2 Given an array, check whether the array is in sorted order with recursion.
Solution:
Time Complexity: O(n). Space Complexity: O(n) for recursive stack space.
Unit-II
Topics to be covered
Linked Lists: Introduction, Linked lists and types ,Representation of
linked list, operations on linked list , Comparison of Linked Lists with
Arrays , Dynamic Arrays
2.1 : Introduction
Array: In array(or lists) are simple data structures used to hold sequence of data. Array elements
are stored in consecutive memory locations. To occupy the adjacent space, block of memory that is
required for the array should be allocated beforehand.
Example : int a[ ]= {50,42,85,71,99};
Once memory allocated it cannot be extended any more. So that array is called the static
data structure. Wastage of memory is more in arrays.
– insertion and deletion operations are slow. Because, we have to shift subsequent ele-
ments
– Fixed size
– Wastage of memory
Example: Linked list to store the sequence : 50, 42,85, 71, 99.
Assume each integer and pointer requires 4 bytes
Starting location of list (head) is 124
The head or header always points to the first node in the list. A NULL pointer used to mark the end
of the linked list.
1. Insertion operation
• There are various positions where node can be inserted.
Node Structure
struct node
{ int data;
struct node *link;
}*new, *ptr, *header, *ptr1;
Creating a node
new = malloc (sizeof(struct node));
new -> data = 10;
new -> link = NULL;
• Step2- ptr=header
• Step3- while(ptr->link!=null)
• 3.1. ptr=ptr->link
• Step4- ptr->link=new
• Step5- new->data=item
• Step6- new->link=null
• Step7-stop
ptr = header;
while(ptr -> link != NULL)
{
ptr1=ptr;
ptr = ptr -> link;
}
ptr1 -> link = NULL;
free(ptr);
ptr = header ;
for(i=1;i<pos-1;i++)
ptr = ptr -> link;
ptr1 = ptr -> link;
ptr -> link = ptr1-> link;
free(ptr1);
Traversing an elements of a list
if(header = = NULL)
print “List is empty”;
else
for (ptr = header ; ptr != NULL ; ptr = ptr -> link)
print “ptr->data”;
A doubly linked list is a two-way list because one can move in either direction. That is,
either from left to right or from right to left.
Where, DATA field - stores the element or data, PREV- contains the address of its previous
node, NEXT- contains the address of its next node.
• Insertion
• Deletion
• Traverse
Search.
Insertion on doubly linked list
• Insertion of a node at the front
• Deletion at end
3. new->data=item
4. ptr= header
5. while(ptr->next!=NULL)
5.1 ptr=ptr->next;
6. new->next=NULL;
7. ptr->next=new;
8. new->prev=ptr;
Deletion at End
Algorithm:
1. ptr=header
2. while(ptr->next!=NULL)
2.1 ptr=ptr->next;
3. end while
4. ptr1=ptr->prev;
5. ptr1->next=NULL;
2. if(header = = NULL)
3. else
2. while(ptr!=NULL)
1. print “ptr->data”;
2. if(ptr->next = = NULL)
1. break;
3. ptr=ptr->next;
4. while(ptr!=header)
Arrays:
- 1. to access an array element, the address of an element computed by using base address and
multiply position with element size then added to base address. Hence, it takes constant
time to access an array element.
• No wastage of memory
Dynamic arrays
• Dynamic array is also called as resizable array, growable array , mutable array or arraylist.
• Dynamic array is a random access and variable size list data structure and enables to add or
remove elements.
• The size of the array grows up automatically when we try to insert new element when there
is no space. Array size will be doubled.
• Dynamic array starts with predefined size and as soon as array become full, array size
would get doubled of the original size.
• Similarly array size reduced to half when elements in the array are less then the half.
• A music player which has next and previous button uses doubly linked list.
• Circular dll and doubly linked list are used to implement rewind and forward functions in
the playlist.
Applications of circular ll
• Used in operating system. When multiple applications are running in PC operating system
to put the running applications on a list and then to cycle through them, giving each of them
a slice of time to execute, and then making them wait while the CPU is given to another ap-
plication.
• Escalator which will run circularly uses the circular linked list.
Question Bank
1. What is Linked list? CO2,BL1,2M
2. Why linked list is linear and dynamic data structure? CO2,BL2,2M
3. List out types of linked list? CO2,BL1,2M
4. What is dynamic array?CO2, BL1, 2M
5. Differentiate between array and dynamic array? CO2,BL2,2M
6. What are dis advantages of linked list over an array? CO2,B2,2M
7. What are the advantages of linked list over an array? CO2,BL3,3M
8. What are the application of SLL,DLL and CLL? CO2,BL1,3M
9. What is circular linked list? What are the advantages of circular linked list over linked list?
CO2, BL2,3M
10. Demonstrate an algorithm or function to insert a node at beginning in singly linked list?
CO2,BL2,5M
11. Demonstrate an algorithm or function to insert a node at end in singly linked list?
CO2,BL25M
12. Demonstrate an algorithm of function to insert a node at any position in singly linked list ?
CO2,BL2,5M
13. Demonstrate delete of a node (start, end, middle ) in singly linked list? CO2,BL2,5M
14. Explain about insertion and deletion operations on singly linked list with neat diagrams?
CO2,BL2,5M
15. What are the application of SLL,DLL and CLL? CO2,BL1,3M
16. What is circular linked list? What are the advantages of circular linked list over linked list?
CO2, BL2,3M.
UNIT-III
Stack is a linear data structure that follows a particular order in which the operations are
performed. The order may be LIFO(Last In First Out) or FILO(First In Last Out).
Mainly the following three basic operations are performed in the stack:
Push: Adds an item in the stack. If the stack is full, then it is said to be an Overflow
condition.
Pop: Removes an item from the stack. The items are popped in the reversed order in
which they are pushed. If the stack is empty, then it is said to be an Underflow condi-
tion.
Peek or Top: Returns the top element of the stack.
isEmpty: Returns true if the stack is empty, else false.
Example: A + (B - C)
To evaluate the expressions, one needs to be aware of the standard precedence rules for arithmetic
expression. The precedence rules for the five basic arithmetic operators are:
Evaluation of Arithmetic Expression requires two steps:
o First, convert the given expression into special notation.
o Evaluate the expression in this new notation.
o Infix Notation
o Prefix Notation
o Postfix Notation
Infix Notation
The infix notation is a convenient way of writing an expression in which each operator is placed
between the operands. Infix expressions can be parenthesized or unparenthesized depending upon
the problem requirement.
Example: A + B, (C - D) etc.
Prefix Notation
• The prefix notation places the operator before the operands. This notation was introduced
by the Polish mathematician and hence often referred to as polish notation.
• Example: + A B, -CD etc.
Postfix Notation
• The postfix notation places the operator after the operands. This notation is just the reverse
of Polish notation and also known as Reverse Polish notation.
• Example: AB +, CD+, etc.
Infix Prefix Postfix Notation
Notation Notation
Example
In the above example, the last inserted node is 99 and the first inserted node is 25. The order of
elements inserted is 25, 32,50 and 99.
To implement a stack using a linked list, we need to set the following things before implementing
actual operations.
Step 1 - Include all the header files which are used in the program. And declare all the user
defined functions.
Step 2 - Define a 'Node' structure with two members data and next.
Step 3 - Define a Node pointer 'top' and set it to NULL.
Step 4 - Implement the main method by displaying Menu with list of operations and make
suitable function calls in the main method.
We can use the following steps to insert a new node into the stack...
We can use the following steps to display the elements (nodes) of a stack...
Queue is also an abstract data type or a linear data structure, just like stack data structure, in which
the first element is inserted from one end called the REAR(also called tail), and the removal of
existing element takes place from the other end called as FRONT(also called head).
This makes queue as FIFO(First in First Out) data structure, which means that element inserted
first will be removed first.
Which is exactly how queue system works in real world . If you go to a ticket counter to buy movie
tickets, and are first in the queue, then you will be the first one to get the tickets. Right? Same is the
case with Queue data structure. Data inserted first, will leave the queue first.
• The process to add an element into queue is called Enqueue and the process of removal of
an element from queue is called Dequeue.
Basic features of Queue
1. Like stack, queue is also an ordered list of elements of similar data types.
3. Once a new element is inserted into the Queue, all the elements inserted before the new ele-
ment in the queue must be removed, to remove the new element.
4. peek( ) function is oftenly used to return the value of first element without dequeuing it.
Applications of Queue
1. Serving requests on a single shared resource, like a printer, CPU task scheduling etc.
2. In real life scenario, Call Center phone systems uses Queues to hold people calling them in
an order, until a service representative is free.
3. Handling of interrupts in real-time systems. The interrupts are handled in the same order as
they arrive i.e First come first served.
Queue can be implemented using an Array, Stack or Linked List. The easiest way of implementing
a queue is by using an Array.
Initially the head(FRONT) and the tail(REAR) of the queue points at the first index of the array
(starting the index of array from 0). As we add elements to the queue, the tail keeps on moving
ahead, always pointing to the position where the next element will be inserted, while the head re-
mains at the first index.
When we remove an element from Queue, we can follow two possible approaches (mentioned [A]
and [B] in above diagram). In [A] approach, we remove the element at head position, and then one
by one shift all the other elements in forward position.
In approach [B] we remove the element from head position and then move head to the next
position.
In approach [A] there is an overhead of shifting the elements one position forward every time
we remove the first element.
In approach [B] there is no such overhead, but whenever we move head one position ahead, after
removal of first element, the size on Queue is reduced by one space each time.
When we remove an element from Queue, we can follow two possible approaches (mentioned [A]
and [B] in above diagram). In [A] approach, we remove the element at head position, and then one
by one shift all the other elements in forward position.
In approach [B] we remove the element from head position and then move head to the next
position.
In approach [A] there is an overhead of shifting the elements one position forward every time
we remove the first element.
In approach [B] there is no such overhead, but whenever we move head one position ahead, after
removal of first element, the size on Queue is reduced by one space each time.
1. If the queue is not empty, then print the element at the head and increment the head.
peek()
This function helps to see the data at the front of the queue. The algorithm of peek() function is as
follows −
Algorithm
return queue[front]
end procedure
isfull()
As we are using single dimension array to implement queue, we just check for the rear pointer to
reach at MAXSIZE to determine that the queue is full. In case we maintain the queue in a circular
linked-list, the algorithm will differ. Algorithm of isfull() function −
Algorithm
return true
else
return false
Endif
isempty()
Algorithm of isempty() function −
Algorithm
return true
else
return false
endif
end procedure
end procedure
Enqueue Operation
Queues maintain two data pointers, front and rear. Therefore, its operations are comparatively
difficult to implement than that of stacks.
The following steps should be taken to enqueue (insert) data into a queue −
Step 1 − Check if the queue is full.
Step 2 − If the queue is full, produce overflow error and exit.
Step 3 − If the queue is not full, increment rear pointer to point the next empty space.
Step 4 − Add data element to the queue location, where the rear is pointing.
Step 5 − return success.
procedure enqueue(data)
if queue is full
return overflow
endif
rear ← rear + 1
queue[rear] ← data
return true
end procedure
Dequeue Operation
Accessing data from the queue is a process of two tasks − access the data where front is pointing
and remove the data after access. The following steps are taken to perform dequeue operation −
Step 1 − Check if the queue is empty.
Step 2 − If the queue is empty, produce underflow error and exit.
Step 3 − If the queue is not empty, access the data where front is pointing.
Step 4 − Increment front pointer to point to the next available data element.
Step 5 − Return success.
Priority Queues
A priority queue is a special type of queue in which each element is associated with a priority
value. And, elements are served on the basis of their priority. That is, higher priority elements are
served first.
However, if elements with the same priority occur, they are served according to their order in the
queue.
In the below priority queue, element with maximum ASCII value will have the highest priority.
Generally, the value of the element itself is considered for assigning the priority. For example,
The element with the highest value is considered the highest priority element. However, in other
cases, we can assume the element with the lowest value as the highest priority element.
In a queue, the first-in-first-out rule is implemented whereas, in a priority queue, the values are
removed on the basis of priority. The element with the highest priority is removed first.
Implementation of Priority Queue
Priority queue can be implemented using an array, a linked list, a heap data structure, or a binary
search tree. Among these data structures, heap data structure provides an efficient implementation
of priority queues.
Question Bank
1. Write an algorithm to convert infix to postfix expression and explain with an example CO3-
L2
2. Write a function to evaluate postfix CO3-L2
3. Define a stack? How do you implement stack using arrays CO2-L3
4. Write a postfix form of each of the following infix expression CO3-L3
a. a)A-B+(M^N)*(O+P)-Q/R^S*T+Z
b. b)K+L-M*N+(O^P)*W/U/V*T+Q
a b
c
d e
Here, ‘a’ and ‘b’ are the points. The link between these two points is called a line.
Vertex
A vertex is a point where multiple lines meet. It is also called a node. Similar to points, a vertex is also
denoted by an alphabet.
In the above example, ab, ac, cd, and bd are the edges of the graph. Similarly, a, b, c, and d are the ver-
tices of the graph.
Loop
In a graph, if an edge is drawn from vertex to itself, it is called a loop.
In the above graph, V is a vertex for which it has an edge (V, V) forming a loop.
Degree of Vertex
It is the number of vertices adjacent to a vertex V.
Notation − deg(V).
In a simple graph with n number of vertices, the degree of any vertices is −
deg(v) ≤ n – 1 ∀ v ∈ G
A vertex can form an edge with all other vertices except by itself. So the degree of a vertex will be up
to the number of vertices in the graph minus 1. This 1 is for the self-vertex as it cannot form a loop
by itself. If there is a loop at any of the vertices, then it is not a Simple Graph.
Degree of vertex can be considered under two cases of graphs −
Undirected Graph
Directed Graph
Degree of Vertex in an Undirected Graph
An undirected graph has no directed edges. Consider the following examples.
Indegree of a Graph
Indegree of vertex V is the number of edges which are coming into the vertex V.
Notation − deg−(V).
Outdegree of a Graph
Outdegree of vertex V is the number of edges which are going out from the vertex V.
Notation − deg+(V).
Adjacentvertices
If two nodes are connected by an edge, they are neighbors (and the nodes are adjacent to each
other).
The size of a graph is the number of nodes in it
The empty graph has size zero (no nodes).
Loop- An edge that connects the vertex with itself
Degree of a Vertex- the number of edges connected to that vertex
• For directed graph,
– the in-degree of a vertex v is the number of edges incident on to the vertex.
– the out-degree of a vertex v is the number of edges emanating from that vertex.
Examples
simple path: no vertex is repeated
Cycle - some path with distinct vertices except that the last vertex is the same as the first vertex
a b a
Parallel edges- if there are one or More than one edges between the same pair of vertices.
ba b a b
c d
c
e c bec c
acda
d e abedc d e d e
• Representation of a Graph
There are two ways of representing a graph in memory:
Sequential Representation by means of Adjacency Matrix.
Linked Representation by means of Linked List.
A
A B C D E
BA 0 1 C1 1 0
B D
1 0 1 E1 0
C 1 1 0 1 1
D 1 1 1 0 1
E 0 0 1 1 0
Linked List Representation
It saves the memory.
The number of lists depends on the number of vertices in the graph.
The header node in each list maintains a list of all adjacent vertices of a node .
A
B A
C B C
D D E
NE
Undirected Matrix
Adjacency List
Graph
A stack can be used to maintain the track of all paths from any vertex so as to help backtracking.
Initially starting vertex will be pushed onto the stack.
To visit a vertex, we are to pop a vertex from the stack, and then push all the adjacent vertices onto it.
A list is maintained to store the vertices already visited.
When a vertex is popped, whether it is already visited or not that can be known by searching the list.
If the vertex is already visited, we will simply ignore it and we will pop the stack for the next vertex to
be visited.
This procedure will continue till the stack not empty.
Breadth First Traversal:
The breadth first traversal is similar to the pre-order traversal of a binary tree.
The breadth first traversal of a graph is similar to traversing a binary tree
level by level (the nodes at each level are visited from left to right).
All the nodes at any level, i, are visited before visiting the nodes at level i + 1.
To implement the breadth first search algorithm, we use a queue.
BFS follows the following rules:
1. Select an unvisited node x, visit it, have it be the root in a BFS tree being formed. Its level is called the
current level.
2. From each node x in the current level, visit all the unvisited neighbors of x. The newly visited nodes
from this level form a new level that becomes the next current level.
3. Repeat step 2 until no more nodes can be visited.
4. If there are still unvisited nodes, repeat from Step 1.
Applications of Graphs:
Computer networks
Local area network
Internet
Web
Databases
Entity-relationship diagram
Spanning Trees
A spanning tree of a graph is just a sub graph that contains all the vertices and
is a tree( without any cycles in a graph)
A graph may have many spanning trees.
or or or
Hyderabad
580km 270km
Banglore vijayawada
980km Mumbai1000km
Find a short distance to cover all four
cities
The minimum spanning tree for a given graph is the spanning tree of
minimum cost for that graph.
Weighted Graph Minimum Spanning Tree
7
2 2
5 3 3
4
1 1
Algorithms to find Minimum Spanning Trees are:
Kruskal‘s Algorithm
Prim‘s Algorithm
Kruskal’s algorithm:
Kruskal’s algorithm finds the minimum cost spanning tree by selecting the edges one by one as
follows.
1. Draw all the vertices of the graph.
2. Select the smallest edge from the graph and add it into the spanning tree (initially it is empty).
3. Select the next smallest edge and add it into the spanning tree.
4. Repeat the 2 and 3 steps until that does not form any cycles.
Prim’s algorithm:
Prim’s algorithm finds the minimum cost spanning tree by selecting the edges one by one as follows.
1. All vertices are marked as not visited
2. Any vertex v you like is chosen as starting vertex and is marked as visited (define a cluster C).
3. The smallest- weighted edge e = (v,u), which connects one vertex v inside the cluster C with another
vertex u outside of C, is chosen and is added to the MST.
4. The process is repeated until a spanning tree is formed.
Binary Search :Binary Search is used with sorted array or list. In binary search, we follow the
following steps:
1. We start by comparing the element to be searched with the element in the middle of the list/array.
2. If we get a match, we return the index of the middle element.
3. If we do not get a match, we check whether the element to be searched is less or greater than in value
than the middle element.
4. If the element/number to be searched is greater in value than the middle number, then we pick the ele-
ments on the right side of the middle element(as the list/array is sorted, hence on the right, we will
have all the numbers greater than the middle number), and start again from the step 1.
5. If the element/number to be searched is lesser in value than the middle number, then we pick the ele-
ments on the left side of the middle element, and start again from the step 1.
Binary Search is useful when there are large number of elements in an array and they are sorted.
So a necessary condition for Binary search to work is that the list/array should be sorted.
Features of Binary Search
1. It is great to search through large sorted arrays.
2. It has a time complexity of O(log n) which is a very good time complexity.
3. It has a simple implementation.
Binary Search Algorithm
Bubble Sort:
A well known algorithm called Bubble sort, is easy to understand. Probably this is the least efficient.
The basic idea underlying the bubble sort is to pass through the array left to right several times. Each
pass consists of comparing each element in the array with its successor and interchanging the two ele-
ments if they are not in proper order. At the end of each pass we can observe that the largest element of
the list is moved to its final position.
Explanation:
Time Complexity :
Best Case : O(n²) #Means array is already sorted.
Average Case : O(n²) #Means array with random numbers.
Worst Case : O(n²) #Means array with descending order.
Next →← Prev
Heap Sort Algorithm
In this article, we will discuss the Heapsort Algorithm. Heap sort processes the elements by creating
the min-heap or max-heap using the elements of the given array. Min-heap or max-heap represents the
ordering of array in which the root element represents the minimum or maximum element of the array.
Heap sort basically recursively performs two main operations -
o Build a heap H, using the elements of array.
o Repeatedly delete the root element of the heap formed in 1st phase.
Before knowing more about the heap sort, let's first see a brief description of Heap.
What is a heap?
A heap is a complete binary tree, and the binary tree is a tree in which the node can have the utmost
two children. A complete binary tree is a binary tree in which all the levels except the last level, i.e.,
leaf node, should be completely filled, and all the nodes should be left-justified.
What is heap sort?
Heapsort is a popular and efficient sorting algorithm. The concept of heap sort is to eliminate the ele-
ments one by one from the heap part of the list, and then insert them into the sorted part of the list.
Heapsort is the in-place sorting algorithm.
Now, let's see the algorithm of heap sort.
Algorithm
1. HeapSort(arr)
2. BuildMaxHeap(arr)
3. for i = length(arr) to 2
4. swap arr[1] with arr[i]
5. heap_size[arr] = heap_size[arr] ? 1
6. MaxHeapify(arr,1)
7. End
BuildMaxHeap(arr)
1. BuildMaxHeap(arr)
2. heap_size(arr) = length(arr)
3. for i = length(arr)/2 to 1
4. MaxHeapify(arr,i)
5. End
MaxHeapify(arr,i)
1. MaxHeapify(arr,i)
2. L = left(i)
3. R = right(i)
4. if L ? heap_size[arr] and arr[L] > arr[i]
5. largest = L
6. else
7. largest = i
8. if R ? heap_size[arr] and arr[R] > arr[largest]
9. largest = R
10. if largest != i
11. swap arr[i] with arr[largest]
12. MaxHeapify(arr,largest)
13. End