0% found this document useful (0 votes)
9 views

Theory of Data Structure With Notes

1. Data structures organize data in a way that allows for efficient access and storage. They represent logical relationships between different data elements. 2. There are two main categories of data structures - primitive and non-primitive. Primitive structures like integers and characters can be directly manipulated by machines, while non-primitive structures like arrays and linked lists are derived from primitive structures. 3. Algorithms are step-by-step procedures to solve problems and achieve desired outputs. Common algorithms involve searching, sorting, inserting, updating and deleting data within a structure. Algorithms should be unambiguous, have defined inputs/outputs, and be language-independent.
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
9 views

Theory of Data Structure With Notes

1. Data structures organize data in a way that allows for efficient access and storage. They represent logical relationships between different data elements. 2. There are two main categories of data structures - primitive and non-primitive. Primitive structures like integers and characters can be directly manipulated by machines, while non-primitive structures like arrays and linked lists are derived from primitive structures. 3. Algorithms are step-by-step procedures to solve problems and achieve desired outputs. Common algorithms involve searching, sorting, inserting, updating and deleting data within a structure. Algorithms should be unambiguous, have defined inputs/outputs, and be language-independent.
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 61

UNIT -1

BASIC CONCEPT OF DATA STRUCTURE

The study of data structure helps you to understand how data is


organized and how data flow is managed to increase efficiency of any
process or program.

Data structure is the structural representation of logical relationship


between data elements. This means that a data structure organizes
data items based on the relationship between the data elements.

Basic Terminology

Following terminology is used as far as data structures are concerned

Data: Data can be defined as an elementary value or the collection of


values, for example, student's name and its id are the data about the
student.

Group Items: Data items which have subordinate data items are called
Group item, for example, name of a student can have first name and
the last name.

Record: Record can be defined as the collection of various data items,


for example, if we talk about the student entity, then its name, address,
course and marks can be grouped together to form the record for the
student.

File: A File is a collection of various records of one type of entity, for


example, if there are 60 employees in the class, then there will be 20
records in the related file where each record contains the data about
each employee.

Attribute and Entity: An entity represents the class of certain objects. it


contains various attributes. Each attribute represents the particular
property of that entity. Field: Field is a single elementary unit of
information representing the attribute of an entity

Need for Data Structure

>> It gives different level of organization data.


>> It tells how data can be stored and accessed in its elementary level.
>> Provide operation on group of data, such as adding an item, looking
up highest priority item.

>> Provide a means to manage huge amount of data efficiently.


>>Provide fast searching and sorting of data.

Goals of Data Structure

Data structure basically implements two complementary goals.

Correctness: correctness forms the primary goal of data structure,


which always depends on the specific problems that the data structure
is intended to solve.

Efficiency: the efficiency of a data structure is an important factor that


determines the success and failure of the process.

Features of Data Structure


Some of the important features of data structures are:

Robustness: Generally, all computer programmers wish to produce


software that generates correct output for every possible input
provided to it, as well as execute efficiently on all hardware platforms.
This kind of robust software must be able to manage both valid and
invalid inputs.

Adaptability: Developing software projects such as word processors,


Web browsers and Internet search engine involves large software
systems that work or execute correctly and efficiently for many years.
Moreover, software evolves due to ever changing market conditions or
due to emerging technologies.

Reusability: Reusability and adaptability go hand-in-hand. It is a known


fact that the programme requires many resources for developing any
software, which makes it an expensive enterprise. However, if the
software is developed in a reusable and adaptable way, then it can be
implemented in most of the future applications. Thus, by implementing
quality data structures, it is possible to develop reusable software,
which tends to be cost effective and time saving.

CLASSIFICATION OF DATA STRUCTURES

Data structure can be classified into two categories:

1 Primitive data structure

2 Non-primitive data structure


Primitive Data Structure: Primitive data structures consist of the
numbers and the characters which are built in programs. These can be
manipulated or operated directly by the machine level instructions.
Basic data types such as integer, real, character, and Boolean come
under primitive data structures. These data types are also known as
simple data types because they consist of characters that cannot be
divided.

Non-primitive Data Structure: Non-primitive data structures are those


that are derived from primitive data structures. These data structures
cannot be operated or manipulated directly by the machine level
instructions. They focus on formation of a set of data elements that is
either homogeneous (same data type) or heterogeneous (different data
type). These are further divided into linear and non-linear data
structure based on the structure and arrangement of data.

Linear Data Structure: A data structure that maintains a linear


relationship among its elements is called a linear data structure. Here,
the data is arranged in a linear fashion. But in the memory, the
arrangement may not be sequential. Ex: Arrays, linked lists, stacks,
queues.
Non-linear Data Structure: Non-linear data structure is a kind of data
structure in which data elements are not arranged in a sequential
order. There is a hierarchical relationship between individual data
items. Here, the insertion and deletion of data is not possible in a linear
fashion. Trees and graphs are examples of non-linear data structures.

In short, Non-Primitive Data Structures:


ALGORITHM

Algorithm is a step-by-step procedure, which defines a set of


instructions to be executed in a certain order to get the desired output.

Algorithms are generally created independent of underlying languages,


i.e. an algorithm can be implemented in more than one programming
language.

From the data structure point of view, following are some important
categories of algorithms −

1. Search − Algorithm to search an item in a data structure.

2. Sort − Algorithm to sort items in a certain order.

3. Insert − Algorithm to insert item in a data structure.

4. Update − Algorithm to update an existing item in a data structure.

5. Delete − Algorithm to delete an existing item from a data structure.

Characteristics of an Algorithm

Not all procedures can be called an algorithm.

An algorithm should have the following characteristics − An algorithm


should have the following characteristics −

1. Clear and Unambiguous: Algorithm should be clear and


unambiguous. Each of its steps should be clear in all aspects and must
lead to only one meaning.
2. Well-Defined Inputs: If an algorithm says to take inputs, it should be
well defined inputs.

3. Well-Defined Outputs: The algorithm must clearly define what


output will be yielded and it should be well-defined as well.

4. Finiteness: The algorithm must be finite, i.e. it should not end up in


an infinite loops or similar.

5. Feasible: The algorithm must be simple, generic and practical; such


that it can be executed upon will the available resources. It must not
contain some future technology, or anything.

6. Language Independent: The Algorithm designed must be language


independent, i.e. it must be just plain instructions that can be
implemented in any language, and yet the output will be same, as
expected

Advantages and Disadvantages of Algorithm


Advantages of Algorithms:

1. It is easy to understand.

2. Algorithm is a step-wise representation of a solution to a given


problem.

3. In Algorithm the problem is broken down into smaller pieces or steps


hence, it is easier for the programmer to convert it into an actual
program.

Disadvantages of Algorithms:

1 Writing an algorithm takes a long time so it is time-consuming.

2 Branching and Looping statements are difficult to show in Algorithms.

Different approach to design an algorithm:


1. Top-Down Approach: A top-down approach starts with identifying
major components of system or program decomposing them into their
lower level components & iterating until desired level of module
complexity is achieved . In this we start with topmost module &
incrementally add modules that is calls.

2. Bottom-Up Approach: A bottom-up approach starts with designing


most basic or primitive component & proceeds to higher level
components.

Starting from very bottom, operations that provide layer of abstraction


are implemented

Categories of Algorithm:

Based on the different types of steps in an Algorithm, it can be divided


into three categories, namely
Sequence
Selection and
Iteration

Sequence: The steps described in an algorithm are performed


successively one by one without skipping any step. The sequence of
steps defined in an algorithm should be simple and easy to understand.
Each instruction of such an algorithm is executed, because no selection
procedure or conditional branching exists in a sequence algorithm.
Example:
// adding two numbers
Step 1: start
Step 2: read a,b
Step 3: Sum=a+b
Step 4: write Sum
Step 5: stop
Selection: The sequence type of algorithms is not sufficient to solve the
problems, which involves decision and conditions. In order to solve the
problem which involve decision making or option selection, we go for
Selection type of algorithm.
The general format of Selection type of statement is as shown below:

if(condition)
Statement-1;
else
Statement-2;

The above syntax specifies that if the condition is true, statement-1 will
be executed otherwise statement-2 will be executed. In case the
operation is unsuccessful. Then sequence of algorithm should be
changed/ corrected in such a way that the system will re-execute until
the operation is successful.

Iteration: Iteration type algorithms are used in solving the problems


which involves repetition of statement. In this type of algorithms, a
particular number of statements are repeated ‘n’ no. of times.
Example1:
Step 1 : start
Step 2 : read n
Step 3 : repeat step 4 until n>0
Step 4 : (a) r=n mod 10
(b) s=s+r
(c) n=n/10
Step 5 : write s
Step 6 : stop

Performance Analysis an Algorithm:


The Efficiency of an Algorithm can be measured by the following
metrics.
i. Time Complexity and
ii. Space Complexity.

i.Time Complexity:
The amount of time required for an algorithm to complete its execution
is its time complexity. An algorithm is said to be efficient if it takes the
minimum (reasonable) amount of time to complete its execution.
ii. Space Complexity:
The amount of space occupied by an algorithm is known as Space
Complexity. An algorithm is said to be efficient if it occupies less space
and required the minimum amount of time to complete its execution.

1.Write an algorithm for roots of a Quadratic Equation?


// Roots of a quadratic Equation
Step 1 : start
Step 2 : read a,b,c
Step 3 : if (a= 0) then step 4 else step 5
Step 4 : Write “ Given equation is a linear equation “
Step 5 : d=(b * b) _ (4 *a *c)
Step 6 : if ( d>0) then step 7 else step8
Step 7 : Write “ Roots are real and Distinct”
Step 8: if(d=0) then step 9 else step 10
Step 9: Write “Roots are real and equal”
Step 10: Write “Roots are Imaginary”
Step 11: stop

2. Write an algorithm to find the largest among three different numbers


entered by user
Step 1: Start
Step 2: Declare variables a,b and c.
Step 3: Read variables a,b and c.
Step 4: If a>b
If a>c
Display a is the largest number.
Else
Display c is the largest number.
Else
If b>c
Display b is the largest number.
Else
Display c is the greatest number.
Step 5: Stop

3.Write an algorithm to find the factorial of a number entered by user.


Step 1: Start
Step 2: Declare variables n,factorial and i.
Step 3: Initialize variables
factorial←1
i←1
Step 4: Read value of n
Step 5: Repeat the steps until i=n
5.1: factorial←factorial*i
5.2: i←i+1
Step 6: Display factorial
Step 7: Stop

4.Write an algorithm to find the Simple Interest for given Time and Rate
of Interest .
Step 1: Start
Step 2: Read P,R,S,T.
Step 3: Calculate S=(PTR)/100
Step 4: Print S
Step 5: Stop

ASYMPTOTIC NOTATIONS

Asymptotic analysis of an algorithm refers to defining the mathematical


boundation/framing of its run-time performance. Using asymptotic
analysis, we can very well conclude the best case, average case, and
worst case scenario of an algorithm.
Asymptotic analysis is input bound i.e., if there's no input to the
algorithm, it is concluded to work in a constant time. Other than the
"input" all other factors are considered constant.
Asymptotic analysis refers to computing the running time of any
operation in mathematical units of computation. For example, the
running time of one operation is computed as f(n) and may be for
another operation it is computed as g(n2). This means the first
operation running time will increase linearly with the increase in n and
the running time of the second operation will increase exponentially
when n increases. Similarly, the running time of both operations will be
nearly the same if n is significantly small.

The time required by an algorithm falls under three types −


Best Case − Minimum time required for program execution.
Average Case − Average time required for program execution.
Worst Case − Maximum time required for program execution.

Asymptotic Notations
Following are the commonly used asymptotic notations to calculate the
running time complexity of an algorithm.
Ο Notation
Ω Notation
θ Notation

Big Oh Notation, Ο
The notation Ο(n) is the formal way to express the upper bound of an
algorithm's running time. It measures the worst case time complexity or
the longest amount of time an algorithm can possibly take to complete
For example, for a function f(n)
Ο(f(n)) = { g(n) : there exists c > 0 and n0 such that f(n) ≤ c.g(n) for all n
> n0. }
Omega Notation, Ω
The notation Ω(n) is the formal way to express the lower bound of an
algorithm's running time. It measures the best case time complexity or
the best amount of time an algorithm can possibly take to complete.

For example, for a function f(n)


Ω(f(n)) ≥ { g(n) : there exists c > 0 and n0 such that g(n) ≤ c.f(n) for all n
> n0. }
Theta Notation, θ
The notation θ(n) is the formal way to express both the lower bound
and the upper bound of an algorithm's running time. It is represented
as follows –
θ(f(n)) = { g(n) if and only if g(n) = Ο(f(n)) and g(n) = Ω(f(n)) for all n > n0.
}

UNIT-2

Stacks:

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). LIFO implies that the element that is inserted last,
comes out first and FILO implies that the element that is inserted first, comes
out last. Stack creation in two different ways : by an Array and by Linked List.

Array and Linked implementation of STACK

Stack Using Array


We are going to use the element at the index 1 of the array as the bottom of
the stack and the last element of the stack as the top of the stack as
described in the picture given below.
Since we need to add and remove elements from the top of the stack, we are
going to use a pointer which is always going to point the topmost element of
the stack. It will point to the element at index 0 when the stack is empty.

So, let’s first write a function to check whether a stack is empty or not.

IS_EMPTY(S)

if S.top == 0

return TRUE

return FALSE

We are going to consider only the elements from 1 to S.top as part of the
stack. It might be possible that there are other elements also in the array but
we are not going to consider them as stack.

Push and Pop operations


To add an item to a stack (push), we just need to increment the top pointer by
1 and add the element there.
PUSH(S, x) → Here, S is the stack and x is the item we are going to push to
the stack.
Let’s suppose that S.size is the maximum size of the stack. So,
if S.top+1 exceed S.size, then the stack is overflowed. So, we will first check
for the overflowing of the stack and then accordingly add the element to it.

PUSH(S, x)

S.top = S.top+1

if S.top > S.size

Error "Stack Overflow"

else

S[top] = x

Similarly to remove an item from a stack (pop), we will first check if the stack
is empty or not. If it is empty, then we will throw an error of "Stack Underflow",
otherwise remove the element from the stack and return it.

POP()

if S.top<0

Error “Stack Underflow”

else

S.top = S.top-1

return S.top

Application of STACK:
There are many applications of a stack. Some of them are:

 Stacks are used in backtracking algorithms.


 They are also used to implement undo/redo functionality in a software.
 Stacks are also used in syntax parsing for many compilers.
 Stacks are also used to check proper opening and closing of
parenthesis.
We have already discussed a lot about stacks. So, let’s code a stack using an
array as well as a linked list.

Stack Using Linked List


A stack using a linked list is just a simple linked list with just restrictions that
any element will be added and removed using push and pop respectively. In
addition to that, we also keep top pointer to represent the top of the stack.
This is described in the picture given below.

A stack will be empty if the linked list won’t have any node i.e., when
the top pointer of the linked list will be null. So, let’s start by making a function
to check whether a stack is empty or not.

IS_EMPTY(S)

if S.top == null

return TRUE

return FALSE

Now, to push any node to the stack (S) - PUSH(S, n), we will first check if the
stack is empty or not. If the stack is empty, we will make the new node head
of the linked list and also point the top pointer to it.

Digram:
PUSH(S, n)
if IS_EMPTY(S) //stack is empty
...
else
S.top.next = n
S.top = n

PUSH(S, n)

if IS_EMPTY(S) //stack is empty

S.head = n //new node is the head of the linked list

S.top = n //new node is the also the top

else

S.top.next = n

S.top = n

Similarly, to remove a node (pop), we will first check if the stack is empty or
not as we did in the implementation with array.
POP(S)
if IS_EMPTY(S)
Error “Stack Underflow”
In the case when the stack is not empty, we will first store the value
in top node in a temporary variable because we need to return it after deleting
the node.
POP(S)
if IS_EMPTY(S)
...
else
x = S.top.data

Now if the stack has only one node (top and head are same), we will just
make both top and head null.
POP(S)
if IS_EMPTY(S)
...
else
...
if S.top == S.head //only one node
S.top = NULL
S.head = NULL

If the stack has more than one node, we will move to the node previous to
the top node and make the next of point it to null and also point the top to it.

POP(S)
...
...
if S.top == S.head //only one node
...
else
tmp = S.head
while tmp.next != S.top //iterating to the node previous
to top
tmp = tmp.next
tmp.next = NULL //making the next of the node null
S.top = tmp //changing the top pointer

We first iterated to the node previous to the top node and then we marked
its next to null - tmp.next = NULL. After this, we pointed the top pointer to it -
S.top = tmp.

At last, we will return the data stored in the temporary variable - return x.
POP(S)

if IS_EMPTY(S)

Error "Stack Underflow"

else

x = S.top.data

if S.top == S.head //only one node

S.top = NULL

S.head = NULL

else

tmp = S.head

while tmp.next != S.top //iterating to the node previous


to top

tmp = tmp.next

tmp.next = NULL //making the next of the node null

S.top = tmp //changing the top pointer

return x

Prefix and Postfix Expressions

Stacks can be used to implement algorithms involving Infix, postfix and prefix
expressions. So let us learn about them:-

INFIX:-
An infix expression is a single letter, or an operator, proceeded by one infix
string and followed by another infix string.
A
A+B
(A + B) + (C – D)
PREFIX:-
A prefix expression is a single letter, or an operator, followed by two prefix
strings. Every prefix string longer than a single variable contains an operator,
first operand and second operand

A
+AB
++AB–CD

POSTFIX:-
A postfix expression (also called Reverse Polish Notation) is a single letter or
an operator, preceded by two postfix strings. Every postfix string longer than a
single variable contains first and second operands followed by an operator.

A
AB+
AB+CD–
Prefix and postfix notations are methods of writing mathematical expressions
without parenthesis. Time to evaluate a postfix and prefix expression is O(n),
where n is the number of elements in the array.

INFIX PREFIX POSTFIX

A+B +AB AB+

A+B–C –+ABC AB+C–

(A + B) * C – D –*+ABCD AB+C*D–

Infix to postfix conversion

Conversion of Infix to Postfix


One of the applications of postfix notation is to build a calculator or
evaluate expressions in a programming language. In addition, we can
evaluate postfix expressions efficiently using a stack data structure.
Therefore, postfix notation is effective for implementing
algorithms such as postfix notation evaluation and expression
parsing.
The process of converting an infix expression to a postfix expression
involves the following steps:

1. First, we create an empty stack and an empty postfix expression


2. Next, we iterate through the infix expression from left to right and
append operands to the postfix expression
3. If an operator is encountered, we pop operators from the stack
and append them to the postfix expression until an operator with
lower or equal precedence is found
4. The current operator is then pushed onto the stack
5. If a left parenthesis is encountered, we push it onto the stack
6. If a right parenthesis is encountered, we pop operators from the
stack and append them to the postfix expression until a left
parenthesis is found
7. Finally, we pop any remaining operators from the stack and
append them to the postfix expression

Considering the previously defined steps, we can convert an infix


expression like “5 + 6 * 2 – 3 / 2” into the postfix expression “5 6 2 * +
3 2 / -“. This notation facilitates a computer to evaluate the expression.

TOKEN OPERATOR PRECEDENCE ASSOCIATIVITY

unary minus or plus


–+
9 right-to-left

*/% multiplicative 8 left-to-right

+– binary add or subtract 7 left-to-right

& bitwise AND 6 left-to-right

^ bitwise XOR 5 left-to-right

| bitwise OR 4 left-to-right
&& logical AND 3 left-to-right

|| logical OR 2 left-to-right

() Brackets 1

Evaluation of Postfix Expression

Evaluation of Postfix Expression using Stack:

To evaluate a postfix expression we can use a stack.


Iterate the expression from left to right and keep on storing the
operands into a stack. Once an operator is received, pop the two
topmost elements and evaluate them and push the result in the stack
again.
Examples:
Input: str = “2 3 1 * + 9 -“
Output: -4

Explanation: If the expression is converted into an infix expression, it


will be 2 + (3 * 1) – 9 = 5 – 9 = -4.

Consider the expression: exp = “2 3 1 * + 9 -“


 Scan 2, it’s a number, So push it into stack. Stack contains ‘2’.
Push 2 into stack

 Scan 3, again a number, push it to stack, stack now contains ‘2 3’


(from bottom to top)

Push 3 into stack

 Scan 1, again a number, push it to stack, stack now contains ‘2 3 1’

Push 1 into stack


 Scan *, it’s an operator. Pop two operands from stack, apply the *
operator on operands. We get 3*1 which results in 3. We push the
result 3 to stack. The stack now becomes ‘2 3’.

Evaluate * operator and push result in stack

 Scan +, it’s an operator. Pop two operands from stack, apply the +
operator on operands. We get 3 + 2 which results in 5. We push the
result 5 to stack. The stack now becomes ‘5’.

Evaluate + operator and push result in stack

 Scan 9, it’s a number. So we push it to the stack. The stack now


becomes ‘5 9’.

Push 9 into stack

 Scan -, it’s an operator, pop two operands from stack, apply the –
operator on operands, we get 5 – 9 which results in -4. We push the
result -4 to the stack. The stack now becomes ‘-4’.
Evaluate ‘-‘ operator and push result in stack

 There are no more elements to scan, we return the top element


from the stack (which is the only element left in a stack).
So the result becomes -4.
Follow the steps mentioned below to evaluate postfix expression using
stack:
 Create a stack to store operands (or values).
 Scan the given expression from left to right and do the following for
every scanned element.
 If the element is a number, push it into the stack.
 If the element is an operator, pop operands for the operator
from the stack. Evaluate the operator and push the result
back to the stack.
 When the expression is ended, the number in the stack is the final
answer.

Queue:
Queue is an abstract data structure, somewhat similar to Stacks.
Unlike stacks, a queue is open at both its ends. One end is always
used to insert data (enqueue) and the other is used to remove data
(dequeue). Queue follows First-In-First-Out methodology, i.e., the data
item stored first will be accessed first.

Or

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.

Similar to stacks, a queue is also an Abstract Data Type or ADT.


A queue follows FIFO (First-in, First out) policy. It is equivalent to the
queues in our general life.

a new element enters a queue at the last (tail of the queue) and removal of an
element occurs from the front (head of the queue).

Similar to the stack, we will implement the queue using a linked list as well as
with an array.

Rear → Enqueue is an operation which adds an element to the queue. As


stated earlier, any new item enters at the tail of the queue, so Enqueue adds
an item to the tail of a queue.

Front→ It is similar to the pop operation of stack i.e., it returns and deletes the
front element from the queue.
isEmpty → It is used to check whether the queue has any element or not.
isFull → It is used to check whether the queue is full or not.
Front → It is similar to the top operation of a stack i.e., it returns the front
element of the queue (but don’t delete it).
Before moving forward to code up these operations, let’s discuss the
applications of a queue.

Applications of Queue

Queues are used in a lot of applications, few of them are:

 Queue is used to implement many algorithms like Breadth First Search


(BFS), etc.
 It can be also used by an operating system when it has to schedule jobs
with equal priority
 Customers calling a call center are kept in queues when they wait for
someone to pick up the calls

Array and Linked implementation of QUEUE

Queue Using an Array

We will maintain two pointers – tail (rear) and head (front) to represent a
queue. Head (front) will always point to the oldest element which was added
and tail (rear) will point where the new element is going to be added.
To insert any element, we add that element at tail(rear) and increase
the tail(rear) by one to point to the next element of the array.

Suppose tail (rear) is at the last element of the queue and there are empty
blocks before head (front) as shown in the picture given below.

In this case, our tail (rear) will point to the first element of the array and will
follow a circular order.

Initially, the queue will be empty i.e., both head (front) and tail (rear) will point
to the same location i.e., at index 1. We can easily check if a queue is empty
or not by checking if head(front) and tail (rear) are pointing to the same
location or not at any time.
Queue Using Linked List

As we know that a linked list is a dynamic data structure and we can change
the size of it whenever it is needed. So, we are not going to consider that
there is a maximum size of the queue and thus the queue will never overflow.
However, one can set a maximum size to restrict the linked list from growing
more than that size.
As told earlier, we are going to maintain a head and a tail pointer to the
queue. In the case of an empty queue, head will point to NULL.

s told earlier, we are going to maintain a head and a tail pointer to the queue.
In the case of an empty queue, head will point to NULL.

IS_EMPTY(Q)

if Q.head == null

return True

return False

We will point the head pointer to the first element of the linked list and
the tail pointer to the last element of it as shown in the picture given below.

The enqueue operation simply adds a new element to the last of a linked list.
However, if the queue is empty, we will simply make the new
node head and tail of the queue.

Operation on QUEUE:

Basic Operations of Queue


The following operations are possible with a queue, which is an object
(abstract data structure – ADT):

 Enqueue: Insert an element at the end of the queue.


 Dequeue: Simply remove an element from the front of the queue.
 IsEmpty: Used to check if the queue is completely empty.
 IsFull: Used to check if the queue is completely full.
 Peek: Without removing it, obtain the value from the front of the
queue.
peek()

This function is used to see the data at the front of the queue. The
peek() function’s algorithm is as follows −

Algorithm
begin procedure peek

return queue[front]

end procedure

C programming language implementation of the peek() function −


int peek() {

return queue[front];

isfull()

We simply check for the rear pointer to reach at MAXSIZE to check


that the queue is full because we are utilizing a single dimension array
to create the queue. The algorithm will be different if we retain the
queue as a circular linked list. The isfull() function’s algorithm −

Algorithm
begin procedure isfull

if rear equals to MAXSIZE

return true

else

return false

endif
end procedure

C programming language implementation of the isfull() function −


bool isfull() {

if(rear == MAXSIZE - 1)

return true;

else

return false;

isempty()

This function is used to check if a queue is empty. We can say that a


queue is empty if no element is present in it. Also we can find a queue
is empty if the front is less than min or front is greater than rear.

Algorithm
begin procedure isempty

if front is less than MIN OR front is greater than rear

return true

else

return false

endif

end procedure

If the value of front is less than MIN or 0, it signifies that the queue is
not yet initialized, hence empty.
C programming language implementation of the isempty()
function −
bool isempty() {

if(front < 0 || front > rear)

return true;

else

return false;

Enqueue Operation

Front and rear data pointers are kept in queues. As a result, compared
to stack operations, its operations are more complex to implement.

To enqueue (insert) data into a queue, execute these instructions:

Step 1: Determine whether the queue is full.

Step 2: Produce an overflow error and quit if the queue is full.

Step 3: If the queue is not full, move the rear pointer forward to the
next empty space.

Step 4: Where the rear is pointing, add the data element to the queue
location.

Step 5: Return a success.


To prepare for any unforeseen circumstances, we may also check to
verify if a queue has been initialized or not.

Algorithm for enqueue operation


procedure enqueue(data)

if queue is full

return overflow

endif

rear ← rear + 1

queue[rear] ← data

return true

end procedure

C programming language implementation of the enqueue()


function −
int enqueue(int data)

if(isfull())

return 0;

rear = rear + 1;

queue[rear] = data;

return 1;
Dequeue Operation

It takes two steps to access data from a queue: first, access the data
where the front is pointing, and second, remove the data after access.
The dequeue operation is carried out in the manner described below:

Step1: Check whether the queue is empty.

Step 2: If there is no one in the queue, generate an underflow error


and exit.

Step 3: Access the information at the front of the queue if it is not


empty.

Step 4: Increment the front pointer to the next element.

Step 5: Successful return.

Algorithm for dequeue operation


procedure dequeue

if queue is empty

return underflow

end if
data = queue[front]

front ← front + 1

return true

end procedure

C programming language implementation of the dequeue()


function −
int dequeue() {

if(isempty())

return 0;

int data = queue[front];

front = front + 1;

return data;

Priority Queue.

Priority Queue:
A priority queue is a collection of elements such that each element has been
assigned a priority. We can insert an element in priority queue at the rare
position. We can delete an element from the priority queue based on the
elements priority and such that the order in which elements are deleted and
processed comes from the following rules:
1. An element of higher priority is processed before any element of lower
priority.
2. Two elements with same priority are processed according to the order in
which they were added to the queue. It follows FIFO or FCFS (First Comes
First serve) rules.
We always remove an element with the highest priority, which is given by the
minimal integer priority assigned.

A prototype of a priority queue is time sharing system: programs of high


priority are processed first, and programs with the same priority form a
standard queue. An efficient implementation for the Priority Queue is to use
heap, which in turn can be used for sorting purpose called heap sort
Priority queues are two types:
1. Ascending order priority queue
2. Descending order priority queue

1. Ascending order priority queue: It is Lower priority number to high priority


number.
Examples: order is 1,2,3,4,5,6,7,8,9,10
2. Descending order priority queue: It is high priority number to lowest priority
number.
Examples: Order is 10,9,8,7,6,5,4,3,2,1
Implementation of Priority Queue:
Implementation of priority queues are two types:
1. Through Queue(Using Array)
2. Through Sorted List(Using Linked List)

1. Through Queue (Using Array): In this case element is simply added at


the rear end as usual. For deletion, the element with highest priority is
searched and then deleted.
2. Through sorted List (Using Linked List): In this case insertion is costly
because the element insert at the proper place in the list based on the priority.
Here deletion is easy since the element with highest priority will always be in
the beginning of the list.
1. Difference between stacks
and Queues?

stacks Queues
1.A stack is a linear list of elements 1.A Queue is a linerar list of
in which the element may be elements in which the elements are
inserted or deleted at one end. added at one end and deletes the
2. In stacks, elements which are elements at another end.
inserted last is the first element to 2. . In Queue the element which is
be deleted. inserted first is the element deleted
3.Stacks are called LIFO (Last In first.
First Out)list 3. Queues are called FIFO (First In
4.In stack elements are removed in First Out)list.
reverse order in which thy are 4. In Queue elements are removed
inserted. in the same order in which thy are
5.suppose the elements a,b,c,d,e inserted.
are inserted in the stack, the 5. Suppose the elements a,b,c,d,e
deletion of elements will be are inserted in the Queue, the
e,d,c,b,a. deletion of elements will be in the
6.In stack there is only one pointer same order in which thy are
to insert and delete called “Top”. inserted.
7.Initially top=-1 indicates a stack is 6. In Queue there are two pointers
empty. one for insertion called “Rear” and
8.Stack is full represented by the another for deletion called “Front”.
condition TOP=MAX-1(if array 7. Initially Rear=Front=-1 indicates
index starts from ‘0’). a Queue is empty.
9.To push an element into a stack, 8.Queue is full represented by the
Top is incremented by one condition
10.To POP an element from Rear=Max-1.
stack,top is decremented by one. 9.To insert an element into Queue,
Rear is incremented by one.
10.To delete an element from
Queue,

UNIT-3

SORTING AND SEARCHING


SORTING-INTRODUCTION

Sorting is a technique of organizing the data. It is a process of arranging the


records, either in ascending or descending order i.e. bringing some order lines
in the data.
Sort methods are very important in Data structures.

Sorting can be performed on any one or combination of one or more attributes


present in each record.
It is very easy and efficient to perform searching, if data is stored in sorting
order.
The sorting is performed according to the key value of each record.
Depending up on the makeup of key, records can be stored either numerically
or alphanumerically.
In numerical sorting, the records arranged in ascending or descending order
according to the numeric value of the key.
Let A be a list of n elements A1, A2, A3 …………………….An in memory.
Sorting A refers to the operation of rearranging the contents of A so that they
are increasing in order, that is, so that A1 <=A2 <=A3 <=…………….<=An.
Since A has n elements, there are n! Ways that the contents can appear in A.
these ways corresponding precisely to the n! Permutations of 1,2,3,………n.
accordingly each sorting algorithm must take care of these n! Possibilities.

Ex: suppose an array DATA contains 8elements as follows:

DATA: 70, 30,40,10,80,20,60,50.

After sorting DATA must appear in memory as follows:


DATA: 10 20 30 40 50 60 70 80

Since DATA consists of 8 elements, there are 8!=40320 ways that the
numbers 10,20,30,40,50,60,70,80 can appear in DATA.

The factors to be considered while choosing sorting techniques are:


Programming Time
Execution Time
Number of Comparisons
Memory Utilization
Computational Complexity

Types of Sorting Techniques:

Sorting techniques are categorized into 2 types.

They are Internal Sorting and External Sorting.


Internal Sorting: Internal sorting method is used when small amount of data
has to be sorted. In this method, the data to be sorted is stored in the main
memory (RAM).Internal sorting method can access records randomly. EX:
Bubble Sort, Insertion Sort, Selection Sort, Quick Sort, Radix Sort, Heap Sort
etc.
External Sorting: External sorting method is used when large amount of data
has to be sorted. In this method, the data to be sorted is stored in the main
memory as well as in the secondary memory such as disk. External sorting
methods an access records only in a sequential order. Ex: Merge Sort, Multi
way Mage Sort.

Complexity of sorting Algorithms: The complexity of sorting algorithm


measures the running time as a function of the number n of items to be
stored.

Each sorting algorithm S will be made up of the following operations, where


A1, A2, A3 …………………….An contain the items to be sorted and B is an
auxiliary location. 38

Comparisons, which test whether Ai < Aj or test whether Ai <B.


Interchanges which switch the contents of Ai and Aj or of Ai and B.
Assignment which set B: Ai and then set Aj := B or Aj:= Ai

Normally, the complexity function measures only the number of comparisons,


since the number of other operations is at most a constant factor of the
number of comparisons.
SELECTION SORT

In selection sort, the smallest value among the unsorted elements of the array
is selected in every pass and inserted to its appropriate position into the array.
First, find the smallest element of the array and place it on the first position.
Then, find the second smallest element of the array and place it on the
second position. The process continues until we get the sorted array. The
array with n elements is sorted by using n-1 pass of selection sort algorithm.
In 1st pass, smallest element of the array is to be found along with its index
pos. then, swap A[0] and A[pos]. Thus A[0] is sorted, we now have n -1
elements which are to be sorted.
In 2nd pas, position pos of the smallest element present in the sub-array
A[n-1] is found. Then, swap, A[1] and A[pos]. Thus A[0] and A[1] are sorted,
we now left with n-2 unsorted elements.
In n-1th pass, position pos of the smaller element between A[n-1] and A[n-
2] is to be found. Then, swap, A[pos] and A[n-1].

Therefore, by following the above explained process, the elements A[0], A[1],
A[2], ... , A[n-1] are sorted.
Example: Consider the following array with 6 elements. Sort the elements of
the array by using selection sort.
A = {10, 2, 3, 90, 43, 56}.
BUBBLE SORT

Bubble Sort: This sorting technique is also known as exchange sort, which
arranges values by iterating over the list several times and in each iteration
the larger value gets bubble up to the end of the list. This algorithm uses
multiple passes and in each pass the first and second data items are
compared. if the first data item is bigger than the second, then the two items
are swapped. Next the items in second and third position are compared and if
the first one is larger than the second, then they are swapped, otherwise no
change in their order. This process continues for each successive pair of data
items until all items are sorted.
Bubble Sort Algorithm:
Step 1: Repeat Steps 2 and 3 for i=1 to 10
Step 2: Set j=1
Step 3: Repeat while j<=n
(A)
if a[i] < a[j] Then
interchange a[i] and a[j]
[End of if]
(B) Set j = j+1
[End of Inner Loop]
[End of Step 1 Outer Loop]
Step 4: Exit
INSERTION SORT

Insertion sort is one of the best sorting techniques. It is twice as fast as


Bubble sort. In Insertion sort the elements comparisons are as less as
compared to bubble sort. In this comparison the value until all prior elements
are less than the compared values is not found. This means that all the
previous values are lesser than compared value. Insertion sort is good choice
for small values and for nearly sorted values.
Working of Insertion sort:
The Insertion sort algorithm selects each element and inserts it at its proper
position in a sub list sorted earlier. In a first pass the elements A1 is compared
with A0 and if A[1] and A[0] are not sorted they are swapped.
In the second pass the element[2] is compared with A[0] and A[1]. And it is
inserted at its proper position in the sorted sub list containing the elements
A[0] and A[1]. Similarly doing ith iteration the element A[i] is placed at its
proper position in the sorted sub list, containing the elements
A[0],A[1],A[2],…………A[i-1].
To understand the insertion sort consider the unsorted Array
A={7,33,20,11,6}.
The steps to sort the values stored in the array in ascending order using
Insertion sort are given below:
Step 1: The first value i.e; 7 is trivially sorted by itself.
Step 2: the second value 33 is compared with the first value 7. Since 33 is
greater than 7, so no changes are made.
Step 3: Next the third element 20 is compared with its previous element
(towards left).Here 20 is less than 33.but 20 is greater than 7. So it is inserted
at second position. For this 33 is shifted towards right and 20 is placed at its
appropriate position.

Step 4: Then the fourth element 11 is compared with its previous elements.
Since 11 is less than 33 and 20 ; and greater than 7. So it is placed in
between 7 and 20. For this the elements 20 and 33 are shifted one position
towards the right.

Step5: Finally the last element 6 is compared with all the elements preceding
it. Since it is smaller than all other elements, so they are shifted one position
towards right and 6 is inserted at the first position in the array. After this pass,
the Array is sorted.

Step 6: Finally the sorted Array is as follows:


ALGORITHM:

Insertion_sort(ARR,SIZE)
Step 1: Set i=1;
Step 2: while(i<SIZE)
Set temp=ARR[i]
J=i=1;
While(Temp<=ARR[j] and j>=0)
Set ARR[j+1]=ARR[i]
Set j=j-1
End While
SET ARR(j+1)=Temp;
Print ARR after ith pass
Set i=i+1
End while
Step 3: print no.of passes i-1
Step 4: end

Advantages of Insertion Sort:


It is simple sorting algorithm, in which the elements are sorted by
considering one item at a time. The implementation is simple.
It is efficient for smaller data set and for data set that has been substantially
sorted before.
It does not change the relative order of elements with equal keys
It reduces unnecessary travels through the array
It requires constant amount of extra memory space.

Disadvantages:-
It is less efficient on list containing more number of elements.
As the number of elements increases the performance of program would be
slow

QUICK SORT

The Quick Sort algorithm follows the principal of divide and Conquer. It first
picks up the partition element called ‘Pivot’, which divides the list into two sub
lists such that all the elements in the left sub list are smaller than pivot and all
the elements in the right sub list are greater than the pivot. The same process
is applied on the left and right sub lists separately. This process is repeated
recursively until each sub list containing more than one element.

Working of Quick Sort:

The main task in Quick Sort is to find the pivot that partitions the given list into
two halves, so that the pivot is placed at its appropriate position in the array.
The choice of pivot as a significant effect on the efficiency of Quick Sort
algorithm. The simplest way is to choose the first element as the Pivot.
However the first element is not good choice, especially if the given list is
ordered or nearly ordered .For better efficiency the middle element can be
chosen as Pivot.
Initially three elements Pivot, Beg and End are taken, such that both Pivot and
Beg refers to 0th position and End refers to the (n-1)th position in the list. The
first pass terminates when Pivot, Beg and End all refers to the same array
element. This indicates that the Pivot element is placed at its final position.
The elements to the left of Pivot are smaller than this element and the
elements to it right are greater.
To understand the Quick Sort algorithm, consider an unsorted array as
follows. The steps to sort the values stored in the array in the ascending order
using Quick Sort are given below.

Step 1: Initially the index ‘0’ in the list is chosen as Pivot and the index
variable Beg and End are initiated with index ‘0’ and (n-1) respectively.

Step 2: The scanning of the element starts from the end of the list.
A[Pivot]>A[End]
i.e; 8>4 so they are swapped.

Step 3: Now the scanning of the elements starts from the beginning of the list.
Since A[Pivot]>A[Beg]. So Beg is incremented by one and the list remains
unchanged.
Step 4: The element A[Pivot] is smaller than A[Beg].So they are swapped.

Step 5: Again the list is scanned form right to left. Since A[Pivot] is smaller
than A[End], so the value of End is decreased by one and the list remains
unchanged.

Step 6: Next the element A[Pivot] is smaller than A[End], the value of End is
increased by one. and the list remains unchanged.

Step 7: A[Pivot>>A[End] so they are swapped.


Step 8: Now the list is scanned from left to right. Since A[Pivot]>A[Beg],value
of Beg is increased by one and the list remains unchanged.

At this point the variable Pivot, Beg, End all refers to same element, the first
pass is terminated and the value 8 is placed at its appropriate position. The
elements to its left are smaller than 8 and the elements to its right are greater
than 8.The same process is applied on left and right sub lists.

ALGORITHM

Step 1: Select first element of array as Pivot

Step 2: Initialize i and j to Beg and End elements respectively

Step 3: Increment i until A[i]>Pivot.

Stop

Step 4: Decrement j until A[ j]>Pivot

Stop

Step 5: if i<j interchange A[i] with A[j].

Step 6: Repeat steps 3,4,5 until i>j i.e: i crossed j.

Step 7: Exchange the Pivot element with element placed at j, which is correct
place for Pivot.
Advantages of Quick Sort:

This is fastest sorting technique among all.

It efficiency is also relatively good.

It requires small amount of memory

Disadvantages:

It is somewhat complex method for sorting.

It is little hard to implement than other sorting methods

It does not perform well in the case of small group of elements.

MERGE SORT

The Merge Sort algorithm is based on the fact that it is easier and faster to
sort two smaller arrays than one large array. It follows the principle of “Divide
and Conquered”. In this sorting the list is first divided into two halves. The left
and right sub lists obtained are recursively divided into two sub lists until each
sub list contains not more than one element. The sub list containing only one
element do not require any sorting. After that merge the two sorted sub lists to
form a combined list and recursively applies the merging process till the
sorted array is achieved.
Let us apply the Merge Sort to sort the following list
Advantages:
Merge sort is stable sort
It is easy to understand
It gives better performance.

Disadvantages:
It requires extra memory space
Copy of elements to temporary array
It requires additional array
It is slow process.

LINEAR SEARCH

The Linear search or Sequential Search is most simple searching method. It


does not expect the list to be sorted. The Key which to be searched is
compared with each element of the list one by one. If a match exists, the
search is terminated. If the end of the list is reached, it means that the search
has failed and the Key has no matching element in the list.
Ex: consider the following Array A
23 15 18 17 42 96 103
Now let us search for 17 by Linear search. The searching starts from the first
position.
Since A[0] ≠17.
The search proceeds to the next position i.e; second position A[1] ≠17.
The above process continuous until the search element is found such as
A[3]=17.
Here the searching element is found in the position 4.
Algorithm:
LINEAR(DATA, N,ITEM, LOC)
Here DATA is a linear Array with N elements. And ITEM is a given item of
information. This algorithm finds the location LOC of an ITEM in DATA. LOC=-
1 if the search is unsuccessful.
Step 1: Set DATA[N+1]=ITEM
Step 2: Set LOC=1
Step 3: Repeat while (DATA [LOC] != ITEM)
Set LOC=LOC+1
Step 4: if LOC=N+1 then
Set LOC= -1.
Step 5: Exit
Advantages:
It is simplest known technique.
The elements in the list can be in any order.
Disadvantages:
This method is in efficient when large numbers of elements are present in list
because time taken for searching is more.

You might also like