You are on page 1of 63

A

Training Report
on
DATA STRUCTURESAnd
Instrumentation & ALGORITHMS
Control
In In
In GeeksForGeeks
IFFCO, AONLA
Submitted in the partial fulfillment of the requirements of the Degree of Bachelor of Technology
in Electrical & Electronics Engg.
By
Abhinav Singh
DIPANSHU TRIPATHI
2000270210042
Roll no. 1802721003

DEPARTMENT OF ELECTRICAL & ELECTRONICS ENGG.

AJAY KUMAR GARG ENGINEERING COLLEGE


GHAZIABAD (U.P)
Session: 2023-24
2021-22

i
ACKNOWLEDGEMENT

I express my deepest sense of gratitude towards Mr. Sandeep


Mr.OP MathurJain(Founder of
(Senior Manager
GeeksForGeeks)
Training), IFFCO, Aonla for his patience, inspiration, guidance, constant encouragement,
moral support, keen interest, and valuable suggestions during preparation of this Training report.
My heartfelt gratitude goes to all faculty members of Electrical & Electronics Engineering
Deptt., who with their encouraging and caring words and most valuable suggestions have
contributed, directly or indirectly, in a significant way towards completion of this Training
report.
I am indebted to all my classmates for taking interest in discussing my problem and
encouraging me.
I owe a debt of gratitude to my father and mother for their consistent support, sacrifice,
candid views, and meaningful suggestion given to me at different stages of this work.
Last but not the least I am thankful to the Almighty who gave me the strength and health for
completing my report.

Abhinav Singh
DIPANSHU TRIPATHI

ii
lOMoARcPSD|29361042

CONTENT

1) ESSENTIAL C AND C++ CONCEPTS


o ARRAY BASICS
o STRUCTURES
o POINTERS
o REFERENCE IN C++
o POINTER TO STRUCTURE
o FUNCTION
o PARAMETER PASSING METHODS
o ARRAY AS PARAMETER
o STRUCTURE AS PARAMETER
o CONSTRUCTOR
o TEMPLATE

2) INTRODUCTION
 STACK VS HEAP MEMORY
 PHYSICAL VS LOGICAL DATA STRUCTURES
 ADT
 TIME AND SPACE COMPLEXITY

3) RECURSION
 HOW RECURSION WORKS
 GENERALISING RECURSION
 HOW RECURSION USES STACK
 RECURRENCE RELATION-TIME COMPLEXITY OF RECURSION
 STATIC AND GLOBAL VARIABLES
 TAIL RECURSION
 HEAD RECURSION
 TREE RECURSION
 INDIRECT RECURSION
 NESTED RECURSION
 PROGRAMS OF RECURSION

4) ARRY REPRESENTATION

 INTRODUCTION TO ARRAY
 STATIC VS DYNAMIC ARRAYS
 HOW TO INCREASE ARRAY SIZE
 2D-ARRAY

Downloaded by Krishna Patel (patelkrishna90050@gmail.com)


lOMoARcPSD|29361042

 ARRAY REPRESENTATION BY COMPILER


 FORMULA GENERATION FOR ARRAYS

5) ARRAY ADT
 ARRAY ADT
 INSERTING IN ARRAY
 DELETING FROM ARRAY
 LINERA SEARCH
 INPROVING LINEAR SEARCH
 BINARY SEARCH
 BINARY SEARCH ALGORITHIM
 ANALYSIS OF BINARY SEARCH
 GET ()/SET ()/AVG () FUNCTIONS ON ARRAY
 REVERSE AND SHIFT AN ARRAY
 CHECK IF ARRAY IS SORTED
 MERGING ARRAYS
 SET OPERATOR ON ARRAY -: UNION, INTERSECTION, DIFFERNCE

6) STRINGS
 INTRODUCTION TO STRINGS
 FINDING LENGTH OF A STRING
 CHANGING CASE OF A STRING
 COUNTING WORDS AND VOWELS ON A STRING
 VALIDATING A STRING
 REVERSING A STRING
 COMPARING STRINGS CHECKING PLAINDROME
 FINDING DUPLICATES IN A STRING
 FINDING FUPLICATES IN A SGTRING USING BITWISE OPERATIONS
 CHECKING IF 2 STRINGS ARE ANAGRAM

7) MATRICES

 INTRODUCTION
 DIAGONAL MATRIX
 C++ CLASS FOR DIAGONAL MATRIX
 LOWER TRIANGULAR MATRIX ROW-MAJOR MAPPING
 UPPER TRIANGULAR MATRIX ROW-MAJOR MAPPING
 UPPER TRIANGULAR MATRIX COLIMN-MAJOR MAPPING
 SYMMETRIC MATRIX
 TRI-DIGONAL AND TRI-BAND MATRIX

Downloaded by Krishna Patel (patelkrishna90050@gmail.com)


lOMoARcPSD|29361042

 TOEPLITZ MATRIX
 MENU DRIVEN PROGRAMS FOR MATRICES

9) LINKED LIST

 WHY WE NEED DYNAMIC DATASTRUCTURES


 ABOUT LINKED LIST
 DISPLAY LINKED LIST
 RECURSIVE DISPLAY FOR LINKED LIST
 COUNTING NODES IN LINKED LIST
 SUM OF ALL ELEMENTS IN A LINKED LIST
 SEARCHING IN A LINKED LIST
 INSERTING IN A LINKED LIST
 CREATING A LINKED LIST USING INSERT
 CREATING A LINKED LIST BY INSERTING AT LAST
 INSERTING IN A SORTED LINKED LIST
 DELETING FROM A LINKED LIST
 CHECK IF A LINKED LIST IS SORTED
 REMOVE DUPLICATES FROM A SORTED LINKED LIST
 REVERSING A LINKED LIST
 REVERSING USING SLIDING POINTERS
 CONCATENATING 2 LINKED LIST
 MERGING 2 LINKED LISTS
 CHECK FOR LOOP IN LINKED LIST
 CIRCULAR LINKED LIST
 DISPLAY CIRCULAR LINKED LIST
 INSERTING IN A CIRCULAR LINKED LIST
 DELETING FROM A CIRCULAR LINKED LIST
 DOUBLY LINKED LIST
 INSERTING IN A BOUBLY LINKED LIST
 FELETING FROM A DOUBLY LINKED LIST
 REVERSE A DOUBLY LINKED LIST
 CIRCULAR DOUBLY LINKED LIST
 COMPARISON OF ARRAY WITH LINKED LIST

10) STACK

 INTRODUCTION TO STACK
 STACK USING ARRAY
 IMPLEMENTATION OF STACK USING ARRAY
 STACK USING LINKED LIST

Downloaded by Krishna Patel (patelkrishna90050@gmail.com)


lOMoARcPSD|29361042

 STACK OPERTIONS USING LINKED LIST


 PARENTHSIS MATCHING
 INFIX TO POSTFIX CONVERSION
 ASSOCIATIVITY AND UNARY OPERATORS

11) QUEUES

 QUEUE ADT
 QUEUE USING SINGLE POINTER
 QUEUE USING TWO POINTERS
 IMPLEMENTATION QUEUE USING ARRAY
 DRAWBACKS OF QUEUE USING ARRAY
 CIRCULAR QUEUE
 QUEUE USING LINKED LIST
 PRIORITY QUEUES
12) TREES

 TERMINOLOGY
 NUMBER OF BINARY TREES USING N NODES
 HEIGHT VS NODES IN A BINARY TREE
 INTERNAL NODES VS EXTERNAL NODES IN BINARY TREE
 STRICT BINARY TREE
 HEIGHT VS NODE OF A STRICT BINARY TREE
 INTERNAL VS EXTERNAL NODES OF A STRICT BINARY TREE
 N-ARY TREES
 REPRESENTATION
 OF BINARY TREE
 LINKED REPRESENTATION OF BINARY TREE
 FULL VS COMPLETE BINARY TREE
 STRICT VS COMPLETE BINARY TREE
 BINARY TREE TRAVERSALS
 CREATING BINARY TREE
 PREORDER TREE TRAVERSAL
 INORDER TREE TRAVERSALS FUNCTIONS
 ITERATIVE PREORDER

13) BINARY SEARCH TREES

 SEARCHING IN A BINARY SEARCH TREE


 INSERTING IN A BINARY SEARCH TREE
 RECURSIVE INSERT IN A BINARY SEARCH TREE
 DELETING FROM A BINARY SEARCH TREE
 GENERATING BST FROM PREORDER

Downloaded by Krishna Patel (patelkrishna90050@gmail.com)


lOMoARcPSD|29361042

 DRAWBACKS OF BINARY SEARCH TREE


14) AVL TREES

 INTRODUCTION
 INSERTION IN AVL TREES WITH ROTATIONS
 GENERATING AVL TREE
15) SEARCH TREES

 2-3 TREES
 2-3-4 TREES
 RED BLACK TREES
16) HEAP

 INTRODUCTION TO HEAP
 INSERTING IN A HEAP
 PROGRAM TO INSERT IN A HEAP
 CREATING A HEAP
 DELEATING FROM HEAP
 HEAP AS PRIORITY QUEUE

17) SORTING TECHNIQUES

 BUBBLE SORT
 INSERTION SORT
 SELECTION SORT
 QUICK SORT
 MERGING
 COUNT SORT
 BUCKET SORT
 RADIX SORT
 SHELL SORT
18) HASHING TECHNIQUE

 INTRODUCTION
 CHAINING
 LINEAR PROBING
 QUADRATIC PROBING
 DOUBLING HASHING
19) GRAPHS

 INTRODUCTION
 REPRESENTATION OF UNDIRECTED GRAPSH

Downloaded by Krishna Patel (patelkrishna90050@gmail.com)


lOMoARcPSD|29361042

 REPRESENTATION OF DIRECTED GRAPSH


 BREADTH FIRST SEARCH DEAPTH FIRST SEARCH
 SPANNING TREES
20) ASYMPTOTIC NOTATIONS

INTRODUCTION

a) STACK VS HEAP MEMORY:

Stack Allocation: The allocation happens on contiguous blocks of


memory. We call it a stack memory allocation because the allocation
happens in the function call stack. The size of memory to be allocated is
known to the compiler and whenever a function is called, its variables get
memory allocated on the stack. And whenever the function call is over,
the memory for the variables is de-allocated. This all happens using some
predefined routines in the compiler.

Heap Allocation: The memory is allocated during the execution of


instructions written by programmers. Note that the name heap has
nothing to do with the heap data structure. It is called heap because it is a
pile of memory space available to programmers to allocate and de-
allocate. Every time when we made an object it always creates in Heap-
space and the referencing information to these objects are always stored
in Stack-memory.

Key Differences Between Stack and Heap Allocations

1. In a stack, the allocation and de-allocation are automatically done


by the compiler whereas in heap, it needs to be done by the
programmer manually.
2. Handling of Heap frame is costlier than the handling of the stack
frame.

Downloaded by Krishna Patel (patelkrishna90050@gmail.com)


lOMoARcPSD|29361042

3. Memory shortage problem is more likely to happen in stack


whereas the main issue in heap memory is fragmentation.
4. Stack frame access is easier than the heap frame as the stack have
a small region of memory and is cache-friendly, but in case of heap
frames which are dispersed throughout the memory so it causes
more cache misses.

b) PHYSICAL VS LOGICAL DATA STRUCTURES

The Array and Linked List are the two physical data structures. We can have more
physical data structures by taking the combination of these two data structures i.e. array
and linked list.

Logical Data Structure:


The following is a list of logical data structures.
1. Stack
2. Queue
3. Tree
4. Graph
5. Hash Table

Stack works on the discipline of LIFO i.e. Last in First Out. Queue works on the discipline
of FIFO i.e. First in First Out. The trees are a non-linear data structure and they will be
organized in a hierarchy. The graph is a collection of nodes and the links between the
nodes. These data structures are actually used in applications and algorithms.

Downloaded by Krishna Patel (patelkrishna90050@gmail.com)


lOMoARcPSD|29361042

The most important point that you need to remember is for implementing the logical data
structures (Stack, Queue, Trees, Graphs, Hash Tables) we either use an array or linked
list or a combination of array and linked list physical data structures. So, that is all we have
given the introduction of various types of data structures. This was just the introduction to
give us awareness.

c) ADT (ABSTRACT DATA TYPE)

The abstract datatype is special kind of datatype, whose behavior is defined by a


set of values and set of operations. The keyword <Abstract= is used as we can use
these datatypes, we can perform different operations. But how those operations are
working that is totally hidden from the user. The ADT is made of with primitive
datatypes, but operation logics are hidden.

Let us see some operations of those mentioned ADT −

 Stack −
o isFull(), This is used to check whether stack is full or not
o isEmpry(), This is used to check whether stack is empty or
not
o push(x), This is used to push x into the stack
o pop(), This is used to delete one element from top of the
stack
o peek(), This is used to get the top most element of the stack
o size(), this function is used to get number of elements
present into the stack
 Queue −
o isFull(), This is used to check whether queue is full or not
o isEmpry(), This is used to check whether queue is empty or
not
o insert(x), This is used to add x into the queue at the rear end
o delete(), This is used to delete one element from the front
end of the queue
o size(), this function is used to get number of elements
present into the queue

 List −

Downloaded by Krishna Patel (patelkrishna90050@gmail.com)


lOMoARcPSD|29361042

o size(), this function is used to get number of elements


present into the list
o insert(x), this function is used to insert one element into the
list
o remove(x), this function is used to remove given element
from the list
o get(i), this function is used to get element at position i
o replace(x, y), this function is used to replace x with y value

d) TIME AND SPACE COMPLEXITY:

Space Complexity
Space complexity of an algorithm represents the amount of memory space needed
the algorithm in its life cycle.
Space needed by an algorithm is equal to the sum of the following two components

A fixed part that is a space required to store certain data and variables (i.e. simple
variables and constants, program size etc.), that are not dependent of the size of the
problem.

A variable part is a space required by variables, whose size is totally dependent on


the size of the problem. For example, recursion stack space, dynamic memory
allocation etc.

Space complexity S(p) of any algorithm p is S(p) = A + Sp(I) Where A is treated as the
fixed part and S(I) is treated as the variable part of the algorithm which depends on
instance characteristic I. Following is a simple example that tries to explain the
concept

Time Complexity
Time Complexity of an algorithm is the representation of the amount of time required
by the algorithm to execute to completion. Time requirements can be denoted or
defined as a numerical function t(N), where t(N) can be measured as the number of
steps, provided each step takes constant time.

For example, in case of addition of two n-bit integers, N steps are taken.
Consequently, the total computational time is t(N) = c*n, where c is the time

Downloaded by Krishna Patel (patelkrishna90050@gmail.com)


lOMoARcPSD|29361042

consumed for addition of two bits. Here, we observe that t(N) grows linearly as input
size increases.

 RECURSION

a) HOW RECURSION WORKS:

When any function is called from main(), the memory is allocated to it


on the stack. A recursive function calls itself, the memory for a called
function is allocated on top of memory allocated to the calling function
and a different copy of local variables is created for each function call.
When the base case is reached, the function returns its value to the
function by whom it is called and memory is de-allocated and the
process continues.

b) TAIL RECURSION:
Tail recursion is defined as a recursive function in which the recursive
call is the last statement that is executed by the function. So basically
nothing is left to execute after the recursion call.

// An example of tail recursive function

void print(int n)
{
if (n < 0)
return;
cout << " " << n;

// The last executed statement is recursive call


print(n - 1);
}

c) HEAD RECURSION:

Downloaded by Krishna Patel (patelkrishna90050@gmail.com)


lOMoARcPSD|29361042

If a recursive function calling itself and that recursive call is the first
statement in the function then it9s known as Head Recursion. There9s
no statement, no operation before the call. The function doesn9t have
to process or perform any operation at the time of calling and all
operations are done at returning time.
Example:

// C++ program showing Head Recursion

#include <bits/stdc++.h>
using namespace std;

// Recursive function
void fun(int n)
{
if (n > 0) {

// First statement in the function


fun(n - 1);

cout << " "<< n;


}
}

// Driver code
int main()
{
int x = 3;
fun(x);
return 0;
}

d) TREE RECURSION:

A function that calls itself, is a recursive function. If it is calling itself more than one time,
then it is a tree recursion. Please have a look at the below example which is an example
of a tree recursive function. As you can see fun is calling itself 2 times (more than 1 time).
In our example, we have shown the recursive call like 2 times, but it can also be more than
2 times.

Downloaded by Krishna Patel (patelkrishna90050@gmail.com)


lOMoARcPSD|29361042

e) INDIRECT RECURSION:
In Indirect recursion, there may be more than one function and they are calling
one another in a circular fashion. For example, if the first function calls the second
function, the second function calls the third function, and again the third function calls
back the first function, then it becomes a cycle which is also a recursion i.e. Indirect
Recursion.

f) NESTED RECURSION:

In Nested recursion, the recursive function will pass the parameter as a recursive call. For
better understanding, please have a look at the below image. In the below image nested
is a recursive function which calls itself. But the parameter itself is a recursive call i.e.
nested(v-1). This is called nested recursion.

Downloaded by Krishna Patel (patelkrishna90050@gmail.com)


lOMoARcPSD|29361042

 ARRAY REPRESENTATION:

a) INRODUCTION TO ARRAY:

An array is a collection of items stored at contiguous memory


locations. The idea is to store multiple items of the same type together. This makes it
easier to calculate the position of each element by simply adding an offset to a base value,
i.e., the memory location of the first element of the array (generally denoted by the name
of the array).

b) STATIC VS DYNAMIC ARRAYS:

Downloaded by Krishna Patel (patelkrishna90050@gmail.com)


lOMoARcPSD|29361042

Dynamic Arrays:

Dynamic arrays differ from static arrays in that they don’t have a
fixed size. However, this is at the cost of having quick appends. How
a dynamic array works is that it resizes itself whenever it runs out of
space. This is usually by doubling itself. For example, if its size
defaulted to 10 indices then it would double to 20. Let’s take a closer
look at how it does this:

1. When you allocate a dynamic array your language of choice


will make a static array with a set size. Let’s say that this
size is 10.

2. Let’s say you go to append an 11th item to your array. This


will make your array run out of space causing it to create a
bigger array that’s double its size (20).

Static Arrays:

When you allocate an array in a low-level language like C++ or Java,


you have to specify upfront how many indices you want your array to
have like so:

This makes the array static because it only has five indices that you
can use. This makes it impossible to append items when all five
indices are filled with values. The upside to this is that if you know
that you are only going to have five elements, then appending to this
array becomes worst case O(1) time.

Downloaded by Krishna Patel (patelkrishna90050@gmail.com)


lOMoARcPSD|29361042

c) 2D ARRAYS:

The two-dimensional array can be defined as an array of arrays. The


2D array is organized as matrices which can be represented as the
collection of rows and columns. However, 2D arrays are created to
implement a relational database lookalike data structure

Declaration of two dimensional Array in C


The syntax to declare the 2D array is given below.

data_type array_name[rows][columns];

d) HOW TO INCREASE SIZE OF ARRAY:

If you want to change the size, you need to create a new array of the
desired size, and then copy elements from the old array to the
new array, and use the new array. In our example, arr can only hold
int values. Arrays can hold primitive values, unlike ArrayList, which
can only hold object values.

 ARRAY ADT:

a) ARRAY ADYT:

ADT indicates for Abstract Data Type.

Arrays are defined as ADT’s because they are capable of holding contiguous
elements in the same order. And they permit

access for the specific element via index or position.


They are abstract because they can be String, int or Person

Downloaded by Krishna Patel (patelkrishna90050@gmail.com)


lOMoARcPSD|29361042

Advantages
 Fast, random access of items or elements.
 Very memory efficient, very little memory is needed other than that
needed to store the contents.

Disadvantages
 Slow insertion and deletion of elements
 Array size must be known when the array is created and is fixed (static)

b) Insertion in array:
Given an array arr of size n, this article tells how to insert an
element x in this array arr at a specific position pos.

#include <stdio.h>

int main()
{
int arr[100] = { 0 };
int i, x, pos, n = 10;

// initial array of size 10


for (i = 0; i < 10; i++)
arr[i] = i + 1;

// print the original array


for (i = 0; i < n; i++)
printf("%d ", arr[i]);
printf("\n");

Downloaded by Krishna Patel (patelkrishna90050@gmail.com)


lOMoARcPSD|29361042

// element to be inserted
x = 50;

// position at which element


// is to be inserted
pos = 5;

// increase the size by 1


n++;

// shift elements forward


for (i = n - 1; i >= pos; i--)
arr[i] = arr[i - 1];

// insert x at pos
arr[pos - 1] = x;

// print the updated array


for (i = 0; i < n; i++)
printf("%d ", arr[i]);
printf("\n");

return 0;
}

c) DELETING FROM ARRAY:


Given an array and a number 8x9, write a function to delete 8x9
from the given array. We assume that array maintains two things
with it, capacity and size. So when we remove an item, capacity
does not change, only size changes.

#include<bits/stdc++.h>
using namespace std;

// This function removes an element x from arr[] and


// returns new size after removal (size is reduced only
// when x is present in arr[]
int deleteElement(int arr[], int n, int x)
{
// Search x in array
int i;
for (i=0; i<n; i++)

Downloaded by Krishna Patel (patelkrishna90050@gmail.com)


lOMoARcPSD|29361042

if (arr[i] == x)
break;

// If x found in array
if (i < n)
{
// reduce size of array and move all
// elements on space ahead
n = n - 1;
for (int j=i; j<n; j++)
arr[j] = arr[j+1];
}

return n;
}

d) LINEAR SEARCH:

Follow the given steps to solve the problem:


 Start from the leftmost element of arr[] and one by one compare x
with each element of arr[]
 If x matches with an element, return the index.
 If x doesn9t match with any of the elements, return -1.

#include <stdio.h>

int search(int arr[], int N, int x)


{
int i;
for (i = 0; i < N; i++)
if (arr[i] == x)
return i;
return -1;
}

// Driver's code
int main(void)
{
int arr[] = { 2, 3, 4, 10, 40 };

Downloaded by Krishna Patel (patelkrishna90050@gmail.com)


lOMoARcPSD|29361042

int x = 10;
int N = sizeof(arr) / sizeof(arr[0]);

// Function call
int result = search(arr, N, x);
(result == -1)
? printf("Element is not present in array")
: printf("Element is present at index %d", result);
return 0;
}

e) BINARY SEARCH:

Binary Search Algorithm: The basic steps to perform Binary Search are:
 Begin with the mid element of the whole array as a search key.
 If the value of the search key is equal to the item then return an
index of the search key.
 Or if the value of the search key is less than the item in the middle
of the interval, narrow the interval to the lower half.
 Otherwise, narrow it to the upper half.
 Repeatedly check from the second point until the value is found or
the interval is empty.

1) ITERATIVE METHOD:

binarySearch(arr, x, low, high)


repeat till low = high
mid = (low + high)/2
if (x == arr[mid])
return mid

else if (x > arr[mid]) // x is on the right side


low = mid + 1

else // x is on the left side


high = mid – 1
2) RECURSIVE METHOD:

Downloaded by Krishna Patel (patelkrishna90050@gmail.com)


lOMoARcPSD|29361042

binarySearch(arr, x, low, high)


if low > high
return False

else
mid = (low + high) / 2
if x == arr[mid]
return mid

else if x > arr[mid] // x is on the right


side
return binarySearch(arr, x, mid + 1, high)

else // x is on the right


side
return binarySearch(arr, x, low, mid - 1)

 STRING:

a) INTRODUCTION TO STRINGS:
A string is generally considered as a data type and is often implemented
as an array data structure of bytes (or words) that stores a sequence of
elements, typically characters, using some character encoding. String
may also denote more general arrays or other sequence (or list) data
types and structures.

Downloaded by Krishna Patel (patelkrishna90050@gmail.com)


lOMoARcPSD|29361042

b) FINDING LENGTH OF A STRING:

#include <stdio.h>

#include <string.h>

int main()
{
char Str[1000];
int i;

printf("Enter the String: ");


scanf("%s", Str);

for (i = 0; Str[i] != '\0'; ++i);

printf("Length of Str is %d", i);

return 0;
}

c) REVERSING A STRING:

Different Methods to Reverse a String in C++ are:

Downloaded by Krishna Patel (patelkrishna90050@gmail.com)


lOMoARcPSD|29361042

 Making our own reverse function


 Using 8inbuilt9 reverse function
 Using Constructor
 Using a temp file

#include <bits/stdc++.h>

using namespace std;

// Function to reverse a string


void reverseStr(string& str)
{
int n = str.length();

// Swap character starting from two


// corners
for (int i = 0; i < n / 2; i++)
swap(str[i], str[n - i - 1]);
}

// Driver program
int main()
{
string str = "geeksforgeeks";
reverseStr(str);
cout << str;
return 0;
}

d) PERMUTATION OF A STRING:

Downloaded by Krishna Patel (patelkrishna90050@gmail.com)


lOMoARcPSD|29361042

#include <bits/stdc++.h>
using namespace std;

// Function to print permutations of string


// This function takes three parameters:
// 1. String
// 2. Starting index of the string
// 3. Ending index of the string.
void permute(string a, int l, int r)
{
// Base case
if (l == r)
cout<<a<<endl;
else
{
// Permutations made
for (int i = l; i <= r; i++)
{

// Swapping done
swap(a[l], a[i]);

// Recursion called
permute(a, l+1, r);

//backtrack
swap(a[l], a[i]);
}
}
}

// Driver Code
int main()
{
string str = "ABC";
int n = str.size();
permute(str, 0, n-1);
return 0;
}

 MATRICES:

a) INTRODUCTION:

Downloaded by Krishna Patel (patelkrishna90050@gmail.com)


lOMoARcPSD|29361042

What is Matíix in Data Stíuctuíe?

A matrix represents a collection of numbers arranged in an order of rows and columns. It


is necessary to enclose the elements of a matrix in parentheses or brackets.

EXAMPLE:

b) DIAGONAL MATRIX:

For example, consider the following 4 X 4 input matrix.


A00 A01 A02 A03
A10 A11 A12 A13
A20 A21 A22 A23
A30 A31 A32 A33
 The primary diagonal is formed by the elements A00, A11, A22,
A33.
Condition for Principal Diagonal:

#include <bits/stdc++.h>
using namespace std;

const int MAX = 100;

// Function to print the Principal Diagonal


void printPrincipalDiagonal(int mat[][MAX], int n)
{
cout << "Principal Diagonal: ";

for (int i = 0; i < n; i++) {


for (int j = 0; j < n; j++) {

// Condition for principal diagonal


if (i == j)

Downloaded by Krishna Patel (patelkrishna90050@gmail.com)


lOMoARcPSD|29361042

cout << mat[i][j] << ", ";


}
}
cout << endl;

C) SYMMETRIC MATRIX:

A Simple solution is to do following.


1. Create transpose of given matrix.
2. Check if transpose and given matrices are same or not

#include <iostream>
using namespace std;

const int MAX = 100;

// Returns true if mat[N][N] is symmetric, else false


bool isSymmetric(int mat[][MAX], int N)
{
for (int i = 0; i < N; i++)
for (int j = 0; j < N; j++)
if (mat[i][j] != mat[j][i])
return false;
return true;
}

// Driver code
int main()
{
int mat[][MAX] = { { 1, 3, 5 },
{ 3, 2, 4 },
{ 5, 4, 1 } };

if (isSymmetric(mat, 3))
cout << "Yes";
else
cout << "No";
return 0;
}

Downloaded by Krishna Patel (patelkrishna90050@gmail.com)


lOMoARcPSD|29361042

 LINKED LIST:

a) ABOUT LINKED LIST:

A linked list is a linear data structure, in which the elements are not stored at contiguous
memory locations

b) Display linked list:

Algorithm
1. Create a class Node which has two attributes: data and next. Next is a pointer
to the next node.
2. Create another class which has two attributes: head and tail.
3. addNode() will add a new node to the list:
a. Create a new node.
b. It first checks, whether the head is equal to null which means the list is
empty.
c. If the list is empty, both head and tail will point to the newly added node.
d. If the list is not empty, the new node will be added to end of the list such
that tail's next will point to the newly added node. This new node will
become the new tail of the list.
4. display() will display the nodes present in the list:

Downloaded by Krishna Patel (patelkrishna90050@gmail.com)


lOMoARcPSD|29361042

. Define a node current which initially points to the head of the list.
a. Traverse through the list till current points to null.
b. Display each node by making current to point to node next to it in each
iteration.

#include <stdio.h>
#include <stdlib.h>
1. //Represent a node of singly linked list
2. struct node{
3. int data;
4. struct node *next;
5. };
6.
7. //Represent the head and tail of the singly linked list
8. struct node *head, *tail = NULL;
9.
10. //addNode() will add a new node to the list
11. void addNode(int data) {
12. //Create a new node
13. struct node *newNode = (struct node*)malloc(sizeof(struct node));
14. newNode->data = data;
15. newNode->next = NULL;
16.
17. //Checks if the list is empty
18. if(head == NULL) {
19. //If list is empty, both head and tail will point to new node
20. head = newNode;
21. tail = newNode;
22. }
23. else {
24. //newNode will be added after tail such that tail's next will point to newN
ode
25. tail->next = newNode;
26. //newNode will become new tail of the list
27. tail = newNode;
28. }

Downloaded by Krishna Patel (patelkrishna90050@gmail.com)


lOMoARcPSD|29361042

29. }
30.
31. //display() will display all the nodes present in the list
32. void display() {
33. //Node current will point to head
34. struct node *current = head;
35.
36. if(head == NULL) {
37. printf("List is empty\n");
38. return;
39. }
40. printf("Nodes of singly linked list: \n");
41. while(current != NULL) {
42. //Prints each node by incrementing pointer
43. printf("%d ", current->data);
44. current = current->next;
45. }
46. printf("\n");
47. }
48.
49. int main()
50. {
51. //Add nodes to the list
52. addNode(1);
53. addNode(2);
54. addNode(3);
55. addNode(4);
56.
57. //Displays the nodes present in the list
58. display();

c) DOUBLY LINKED LIST:


A Doubly Linked List (DLL) contains an extra pointer, typically
called the previous pointer, together with the next pointer and
data which are there in the singly linked list.

Downloaded by Krishna Patel (patelkrishna90050@gmail.com)


lOMoARcPSD|29361042

Advantages of DLL over the singly linked list:


 A DLL can be traversed in both forward and backward directions.
 The delete operation in DLL is more efficient if a pointer to the node
to be deleted is given.
 We can quickly insert a new node before a given node.
 In a singly linked list, to delete a node, a pointer to the previous
node is needed. To get this previous node, sometimes the list is
traversed. In DLL, we can get the previous node using the previous
pointer.
Disadvantages of DLL over the singly linked list:
 Every node of DLL Requires extra space for a previous pointer. It is
possible to implement DLL with a single pointer though
(See this and this).
 All operations require an extra pointer previous to be maintained.
For example, in insertion, we need to modify previous pointers
together with the next pointers. For example in the following
functions for insertions at different positions, we need 1 or 2 extra
steps to set the previous pointer.

/ Node of a doubly linked list

class Node {
public:
int data;

// Pointer to next node in DLL


Node* next;

// Pointer to previous node in DLL


Node* prev;
};

c) CIRCULAR LINKED LIST:


The circular linked list is a linked list where all nodes are
connected to form a circle. In a circular linked list, the first node
and the last node are connected to each other which forms a
circle. There is no NULL at the end.

Downloaded by Krishna Patel (patelkrishna90050@gmail.com)


lOMoARcPSD|29361042

There are generally two types of circular linked lists:


 Circular singly linked list: In a circular Singly linked list, the last
node of the list contains a pointer to the first node of the list. We
traverse the circular singly linked list until we reach the same node
where we started. The circular singly linked list has no beginning or
end. No null value is present in the next part of any of the nodes.

 Circular Doubly linked list: Circular Doubly Linked List


has properties of both doubly linked list and circular linked list in
which two consecutive elements are linked or connected by the
previous and next pointer and the last node points to the first node
by the next pointer and also the first node points to the last node by
the previous pointer.

Representation of circular linked list:


Circular linked lists are similar to single Linked Lists with the exception of
connecting the last node to the first node.
// Class Node, similar to the linked list
class Node{
int value;

// Points to the next node.

Downloaded by Krishna Patel (patelkrishna90050@gmail.com)


lOMoARcPSD|29361042

Node next;
}

d) SEARCHING IN A LINKED LIST:

Search an element in a Linked List (Iterative


Approach):
Follow the below steps to solve the problem:
 Initialize a node pointer, current = head.
 Do following while current is not NULL
 If the current value (i.e., current->key) is equal to the key
being searched return true.
 Otherwise, move to the next node (current = current-
>next).
 If the key is not found, return false

#include <bits/stdc++.h>
using namespace std;

/* Link list node */


class Node {
public:
int key;
Node* next;
};

/* Given a reference (pointer to pointer) to the head


of a list and an int, push a new node on the front
of the list. */
void push(Node** head_ref, int new_key)
{
/* allocate node */
Node* new_node = new Node();

/* put in the key */


new_node->key = new_key;

/* link the old list off the new node */


new_node->next = (*head_ref);

Downloaded by Krishna Patel (patelkrishna90050@gmail.com)


lOMoARcPSD|29361042

/* move the head to point to the new node */


(*head_ref) = new_node;
}

/* Checks whether the value x is present in linked list */


bool search(Node* head, int x)
{
Node* current = head; // Initialize current
while (current != NULL) {
if (current->key == x)
return true;
current = current->next;
}
return false;
}

/* Driver code*/
int main()
{
/* Start with the empty list */
Node* head = NULL;
int x = 21;

/* Use push() to construct below list


14->21->11->30->10 */
push(&head, 10);
push(&head, 30);
push(&head, 11);
push(&head, 21);
push(&head, 14);

// Function call
search(head, 21) ? cout << "Yes" : cout << "No";
return 0;

e) DELETED FROM LINK LIST:

Delete from a Linked List:-


You can delete an element in a list from:
 Beginning
 End
 Middle

Downloaded by Krishna Patel (patelkrishna90050@gmail.com)


lOMoARcPSD|29361042

1) Delete from Beginning:

Point head to the next node i.e. second node


temp = head
head = head->next

Make sure to free unused memory


free(temp); or delete temp;

2) Delete from End:

Point head to the previous element i.e. last second element


Change next pointer to null
struct node *end = head;
struct node *prev = NULL;
while(end->next)
{
prev = end;
end = end->next;
}
prev->next = NULL;

Make sure to free unused memory


free(end); or delete end;

3) Delete from Middle:

Keeps track of pointer before node to delete and pointer to node to


delete
temp = head;
prev = head;
for(int i = 0; i < position; i++)
{
if(i == 0 && position == 1)
head = head->next;

Downloaded by Krishna Patel (patelkrishna90050@gmail.com)


lOMoARcPSD|29361042

free(temp)
else
{
if (i == position - 1 && temp)
{
prev->next = temp->next;
free(temp);
}
else
{
prev = temp;
if(prev == NULL) // position was greater than
number of nodes in the list
break;
temp = temp->next;
}
}
}

 STACK:

a) INTRODUCTION TO STACK:

Stack
It is a linear data structure that follows a particular order in which the
operations are performed.
LIFO( Last In First Out ):
This strategy states that the element that is inserted last will come out first.
You can take a pile of plates kept on top of each other as a real-life example.

Downloaded by Krishna Patel (patelkrishna90050@gmail.com)


lOMoARcPSD|29361042

The plate which we put last is on the top and since we remove the plate that
is at the top, we can say that the plate that was put last comes out first.

Basic Operations on Stack


In order to make manipulations in a stack, there are certain operations
provided to us.
 push() to insert an element into the stack
 pop() to remove an element from the stack
 top() Returns the top element of the stack.
 isEmpty() returns true is stack is empty else false
 size() returns the size of stack

Push:
Adds an item to the stack. If the stack is full, then it is said to be an Overflow
condition.
Algorithm for push:
begin
if stack is full
return
endif
else

Downloaded by Krishna Patel (patelkrishna90050@gmail.com)


lOMoARcPSD|29361042

increment top
stack[top] assign value
end else
end procedure

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 condition.
Algorithm for pop:
begin
if stack is empty
return
endif
else
store value of stack[top]
decrement top
return value
end else
end procedure

Top:
Returns the top element of the stack.
Algorithm for Top:
begin
return stack[top]
end procedure

isEmpty:
Returns true if the stack is empty, else false.
Algorithm for isEmpty:
begin
if top < 1
return true
else
return false
end procedure

Downloaded by Krishna Patel (patelkrishna90050@gmail.com)


lOMoARcPSD|29361042

Understanding stack practically:


There are many real-life examples of a stack. Consider the simple example of
plates stacked over one another in a canteen. The plate which is at the top is
the first one to be removed, i.e. the plate which has been placed at the
bottommost position remains in the stack for the longest period of time. So, it
can be simply seen to follow the LIFO/FILO order.

Complexity Analysis:
 Time Complexity
Operations Complexity

push() O(1)

pop() O(1)

isEmpty() O(1)

size() O(1)

Types of Stacks:
 Register Stack: This type of stack is also a memory element
present in the memory unit and can handle a small amount of data
only. The height of the register stack is always limited as the size of
the register stack is very small compared to the memory.
 Memory Stack: This type of stack can handle a large amount of
memory data. The height of the memory stack is flexible as it
occupies a large amount of memory data.
Applications of the stack:
 Infix to Postfix /Prefix conversion
 Redo-undo features at many places like editors, photoshop.
 Forward and backward features in web browsers
 Used in many algorithms like Tower of Hanoi, tree traversals, stock
span problems, and histogram problems.
 Backtracking is one of the algorithm designing techniques. Some
examples of backtracking are the Knight-Tour problem, N-Queen
problem, find your way through a maze, and game-like chess or
checkers in all these problems we dive into someway if that way is
not efficient we come back to the previous state and go into some
another path. To get back from a current state we need to store the
previous state for that purpose we need a stack.
 In Graph Algorithms like Topological Sorting and Strongly
Connected Components

Downloaded by Krishna Patel (patelkrishna90050@gmail.com)


lOMoARcPSD|29361042

 In Memory management, any modern computer uses a stack as the


primary management for a running purpose. Each program that is
running in a computer system has its own memory allocations
 String reversal is also another application of stack. Here one by one
each character gets inserted into the stack. So the first character of
the string is on the bottom of the stack and the last element of a
string is on the top of the stack. After Performing the pop operations
on the stack we get a string in reverse order.

 QUEUES:

A queue is defined as a linear data structure that is open at both ends and the operations are
performed in First In First Out (FIFO) order.
We define a queue to be a list in which all additions to the list are made at one end, and all
deletions from the list are made at the other end. The element which is first pushed into the
order, the operation is first performed on that.

ÏIÏO Píinciple of Queue:


 A Queue is like a line waiting to purchase tickets, where the first person in
line is the first person served. (i.e. First come first serve).
 Position of the entry in a queue ready to be served, that is, the first entry
that will be removed from the queue, is called the front of the
queue(sometimes, head of the queue), similarly, the position of the last

Downloaded by Krishna Patel (patelkrishna90050@gmail.com)


lOMoARcPSD|29361042

entry in the queue, that is, the one most recently added, is called
the rear (or the tail) of the queue. See the below figure.

FIFO property of queue

Chaíacteíistics of Queue:
 Queue can handle multiple data.
 We can access both ends.
 They are fast and flexible.

Queue Repíesentation:

Like stacks, Queues can also be represented in an array: In this representation, the Queue
is implemented using the array. Variables used in this case are
 Queue: the name of the array storing queue elements.
 Front: the index where the first element is stored in the array representing
the queue.
 Rear: the index where the last element is stored in an array representing
the queue.

a) Circular queue:
A circular queue is the extended version of a regular queue where the last
element is connected to the first element. Thus forming a circle-like
structure.

Downloaded by Krishna Patel (patelkrishna90050@gmail.com)


lOMoARcPSD|29361042

Circular queue representation


The circular queue solves the major limitation of the normal queue. In a
normal queue, after a bit of insertion and deletion, there will be non-usable
empty space.

Limitation of the regular Queue


Here, indexes 0 and 1 can only be used after resetting the queue (deletion
of all elements). This reduces the actual size of the queue.

How Circular Queue Works


Circular Queue works by the process of circular increment i.e. when we try
to increment the pointer and we reach the end of the queue, we start from
the beginning of the queue.

Downloaded by Krishna Patel (patelkrishna90050@gmail.com)


lOMoARcPSD|29361042

Here, the circular increment is performed by modulo division with the queue
size. That is,

Circular Queue Operations


The circular queue work as follows:

 two pointers FRONT and REAR

 FRONT track the first element of the queue


 REAR track the last elements of the queue
 initially, set value of FRONT and REAR to -1
1. Enqueue Operation

 check if the queue is full

 for the first element, set value of FRONT to 0


 circularly increase the REAR index by 1 (i.e. if the rear reaches the end,
next it would be at the start of the queue)
 add the new element in the position pointed to by REAR

2. Dequeue Operation

 check if the queue is empty

 return the value pointed by FRONT

 circularly increase the FRONT index by 1


 for the last element, reset the values of FRONT and REAR to -1

b) PRIORITY QUEUES:
Priority Queue is an abstract data type that is similar to
a queue, and every element has some priority value
associated with it. The priority of the elements in a priority
queue determines the order in which elements are served

Downloaded by Krishna Patel (patelkrishna90050@gmail.com)


lOMoARcPSD|29361042

(i.e., the order in which they are removed). If in any case the
elements have same priority, they are served as per their
ordering in the queue.
Operations of a Priority Queue:
A typical priority queue supports the following operations:
1) Insertion in a Priority Queue
When a new element is inserted in a priority queue, it moves to the empty
slot from top to bottom and left to right. However, if the element is not in the
correct place then it will be compared with the parent node. If the element is
not in the correct order, the elements are swapped. The swapping process
continues until all the elements are placed in the correct position.
2) Deletion in a Priority Queue
As you know that in a max heap, the maximum element is the root node. And
it will remove the element which has maximum priority first. Thus, you
remove the root node from the queue. This removal creates an empty slot,
which will be further filled with new insertion. Then, it compares the newly
inserted element with all the elements inside the queue to maintain the heap
invariant.
3) Peek in a Priority Queue
This operation helps to return the maximum element from Max Heap or the
minimum element from Min Heap without deleting the node from the priority
queue.

Types of Priority Queue:


1) Ascending Order Priority Queue
As the name suggests, in ascending order priority queue, the element with a
lower priority value is given a higher priority in the priority list. For example, if
we have the following elements in a priority queue arranged in ascending
order like 4,6,8,9,10. Here, 4 is the smallest number, therefore, it will get the
highest priority in a priority queue.
2) Descending order Priority Queue
The root node is the maximum element in a max heap, as you may know. It
will also remove the element with the highest priority first. As a result, the
root node is removed from the queue. This deletion leaves an empty space,
which will be filled with fresh insertions in the future. The heap invariant is
then maintained by comparing the newly inserted element to all other entries
in the queue.

Downloaded by Krishna Patel (patelkrishna90050@gmail.com)


lOMoARcPSD|29361042

Types of Priority Queues

Difference between Priority Queue and Normal


Queue?
There is no priority attached to elements in a queue, the rule of first-in-first-
out(FIFO) is implemented whereas, in a priority queue, the elements have a
priority. The elements with higher priority are served first.

How to Implement Priority Queue?


Priority queue can be implemented using the following data structures:
 Arrays
 Linked list
 Heap data structure
 Binary search tree

 TREES:
A tree is non-linear and a hierarchical data structure consisting of a collection
of nodes such that each node of the tree stores a value and a list of
references to other nodes (the <children=).
This data structure is a specialized method to organize and store data in the
computer to be used more effectively. It consists of a central node, structural
nodes, and sub-nodes, which are connected via edges. We can also say that

Downloaded by Krishna Patel (patelkrishna90050@gmail.com)


lOMoARcPSD|29361042

tree data structure has roots, branches, and leaves connected with one
another.

Applications of Tree data structure:

The applications of tree data structures are as follows:


1. Spanning trees: It is the shortest path tree used in the routers to direct
the packets to the destination.
2. Binary Search Tree: It is a type of tree data structure that helps in
maintaining a sorted stream of data.
1. Full Binary tree
2. Complete Binary tree
3. Skewed Binary tree
4. Stickily Binary tree
5. Extended Binary tree
3. Storing hierarchical data: Tree data structures are used to store the
hierarchical data, which means data is arranged in the form of order.
4. Syntax tree: The syntax tree represents the structure of the program9s
source code, which is used in compilers.
5. Trie: It is a fast and efficient way for dynamic spell checking. It is also
used for locating specific keys from within a set.
6. Heap: It is also a tree data structure that can be represented in a form of
an array. It is used to implement priority queues.

ypes of Tree data structures

Downloaded by Krishna Patel (patelkrishna90050@gmail.com)


lOMoARcPSD|29361042

The different types of tree data structures are as follows:


1. General tree
A general tree data structure has no restriction on the number of nodes. It
means that a parent node can have any number of child nodes.
2. Binary tree
A node of a binary tree can have a maximum of two child nodes. In the given
tree diagram, node B, D, and F are left children, while E, C, and G are the
right children.
3. Balanced tree
If the height of the left sub-tree and the right sub-tree is equal or differs at
most by 1, the tree is known as a balanced tree.

Balanced Tree Unbalanced Tree

4. Binary search tree


As the name implies, binary search trees are used for various searching and
sorting algorithms. The examples include AVL tree and red-black tree. It is a
non-linear data structure. It shows that the value of the left node is less than
its parent, while the value of the right node is greater than its parent.

 AVL TREES:

AVL Tree:
AVL tree is a self-balancing Binary Search Tree (BST) where the difference
between heights of left and right subtrees cannot be more than one for all
nodes.
Example of AVL Tree:

Downloaded by Krishna Patel (patelkrishna90050@gmail.com)


lOMoARcPSD|29361042

The above tree is AVL because the differences between heights of left and
right subtrees for every node are less than or equal to 1.
Example of a Tree that is NOT an AVL Tree:

Downloaded by Krishna Patel (patelkrishna90050@gmail.com)


lOMoARcPSD|29361042

The above tree is not AVL because the differences between the heights of
the left and right subtrees for 8 and 12 are greater than 1.

Why AVL Trees?


Most of the BST operations (e.g., search, max, min, insert, delete.. etc)
take O(h) time where h is the height of the BST. The cost of these
operations may become O(n) for a skewed Binary tree. If we make sure
that the height of the tree remains O(log(n)) after every insertion and
deletion, then we can guarantee an upper bound of O(log(n)) for all these
operations. The height of an AVL tree is always O(log(n)) where n is the
number of nodes in the tree.

Insertion in AVL Tree:


To make sure that the given tree remains AVL after every insertion, we must
augment the standard BST insert operation to perform some re-balancing.
Following are two basic operations that can be performed to balance a BST
without violating the BST property (keys(left) < key(root) < keys(right)).
 Left Rotation
 Right Rotation
T1, T2 and T3 are subtrees of the tree, rooted with y (on the left
side) or x (on the right side)

Downloaded by Krishna Patel (patelkrishna90050@gmail.com)


lOMoARcPSD|29361042

y x
/ \ Right Rotation / \
x T3 - - - - - - - > T1 y
/ \ < - - - - - - - / \
T1 T2 Left Rotation T2 T3

Keys in both of the above trees follow the following order


keys(T1) < key(x) < keys(T2) < key(y) < keys(T3)
So BST property is not violated anywhere.

Recommended Problem

AVL Tree Insertion


Binary Search Tree

Tree

Steps to follow for insertion:


Let the newly inserted node be w
 Perform standard BST insert for w.
 Starting from w, travel up and find the first unbalanced node.
Let z be the first unbalanced node, y be the child of z that comes on
the path from w to z and x be the grandchild of z that comes on the
path from w to z.
 Re-balance the tree by performing appropriate rotations on the
subtree rooted with z. There can be 4 possible cases that need to be
handled as x, y and z can be arranged in 4 ways.
 Following are the possible 4 arrangements:
 y is the left child of z and x is the left child of y (Left Left
Case)
 y is the left child of z and x is the right child of y (Left Right
Case)
 y is the right child of z and x is the right child of y (Right
Right Case)
 y is the right child of z and x is the left child of y (Right Left
Case)

 BINARY TREES

Downloaded by Krishna Patel (patelkrishna90050@gmail.com)


lOMoARcPSD|29361042

Binary Tree is defined as a Tree data structure with at most 2 children. Since each element in
a binary tree can have only 2 children, we typically name them the left and right child.

What is Binaíy ľíee Data Stíuctuíe?


Binary Tree is defined as a Tree data structure with at most 2 children. Since each element
in a binary tree can have only 2 children, we typically name them the left and right child.
Binaíy ľíee Repíesentation

A Binary tree is represented by a pointer to the topmost node of the tree. If the tree is
empty, then the value of the root is NULL.
Binary Tree node contains the following parts:
1. Data
2. Pointer to left child
3. Pointer to right child
Basic Opeíation On Binaíy ľíee:
 Inserting an element.
 Removing an element.
 Searching for an element.
 Traversing an element.
Auxiliaíy Opeíation On Binaíy ľíee:
 Finding the height of the tree
 Find the level of the tree
 Finding the size of the entire tree.

Downloaded by Krishna Patel (patelkrishna90050@gmail.com)


lOMoARcPSD|29361042

 SORTING TECHNIQUE:
Sorting refers to the operation or technique of arranging and rearranging sets of
data in some specific order. A collection of records called a list where every record
has one or more fields. The fields which contain a unique value for each record is
termed as the key field. For example, a phone number directory can be thought of as
a list where each record has three fields - 'name' of the person, 'address' of that
person, and their 'phone numbers'. Being unique phone number can work as a key to
locate any record in the list.

Sorting is the operation performed to arrange the records of a table or list in some
order according to some specific ordering criterion. Sorting is performed according
to some key value of each record.

The records are either sorted either numerically or alphanumerically. The records are
then arranged in ascending or descending order depending on the numerical value
of the key. Here is an example, where the sorting of a lists of marks obtained by a
student in any particular subject of a class.

Categories of Sorting
The techniques of sorting can be divided into two categories. These are:

 Internal Sorting
 External Sorting

Internal Sorting: If all the data that is to be sorted can be adjusted at a time in the
main memory, the internal sorting method is being performed.

External Sorting: When the data that is to be sorted cannot be accommodated in the
memory at the same time and some has to be kept in auxiliary memory such as hard
disk, floppy disk, magnetic tapes etc, then external sorting methods are performed.

The Complexity of Sorting Algorithms


The complexity of sorting algorithm calculates the running time of a function in
which 'n' number of items are to be sorted. The choice for which sorting method is
suitable for a problem depends on several dependency configurations for different
problems. The most noteworthy of these considerations are:

 The length of time spent by the programmer in programming a specific


sorting program
 Amount of machine time necessary for running the program
 The amount of memory necessary for running the program

Downloaded by Krishna Patel (patelkrishna90050@gmail.com)


lOMoARcPSD|29361042

The Efficiency of Sorting Techniques


To get the amount of time required to sort an array of 'n' elements by a particular
method, the normal approach is to analyze the method to find the number of
comparisons (or exchanges) required by it. Most of the sorting techniques are data
sensitive, and so the metrics for them depends on the order in which they appear in
an input array.

Various sorting techniques are analyzed in various cases and named these cases as
follows:

 Best case
 Worst case
 Average case

Hence, the result of these cases is often a formula giving the average time required
for a particular sort of size 'n.' Most of the sort methods have time requirements that
range from O(nlog n) to O(n2).

Types of Sorting Techniques


 Bubble Sort
 Selection Sort
 Merge Sort
 Insertion Sort
 Quick Sort
 Heap Sort

 Hashing technique:

 Hashing is the process of mapping large amount of data item to


smaller table with the help of hashing function.
 Hashing is also known as Hashing Algorithm or Message Digest
Function.
 It is a technique to convert a range of key values into a range of
indexes of an array.
 It is used to facilitate the next level searching method when compared
with the linear or binary search.

Downloaded by Krishna Patel (patelkrishna90050@gmail.com)


lOMoARcPSD|29361042

 Hashing allows to update and retrieve any data entry in a constant


time O(1).
 Constant time O(1) means the operation does not depend on the size
of the data.
 Hashing is used with a database to enable items to be retrieved more
quickly.
 It is used in the encryption and decryption of digital signatures.

What is Hash Function?

 A fixed process converts a key to a hash key is known as a Hash


Function.
 This function takes a key and maps it to a value of a certain length
which is called a Hash value or Hash.
 Hash value represents the original string of characters, but it is
normally smaller than the original.
 It transfers the digital signature and then both hash value and
signature are sent to the receiver. Receiver uses the same hash
function to generate the hash value and then compares it to that
received with the message.
 If the hash values are same, the message is transmitted without
errors.

What is Hash Table?

 Hash table or hash map is a data structure used to store key-value


pairs.
 It is a collection of items stored to make it easy to find them later.
 It uses a hash function to compute an index into an array of buckets
or slots from which the desired value can be found.
 It is an array of list where each list is known as bucket.
 It contains value based on the key.
 Hash table is used to implement the map interface and extends
Dictionary class.
 Hash table is synchronized and contains only unique elements.

Downloaded by Krishna Patel (patelkrishna90050@gmail.com)


lOMoARcPSD|29361042

 GRAPHS IN DATA STRUCTURE:

Components of a Gíaph
 Vertices: Vertices are the fundamental units of the graph. Sometimes,
vertices are also known as vertex or nodes. Every node/vertex can be
labeled or unlabelled.
 Edges: Edges are drawn or used to connect two nodes of the graph. It can
be ordered pair of nodes in a directed graph. Edges can connect any two
nodes in any possible way. There are no rules. Sometimes, edges are also
known as arcs. Every edge can be labeled/unlabelled.

Types of Graphs:
1. Finite Graphs
A graph is said to be finite if it has a finite number of vertices and a finite
number of edges.

2. Infinite Graph:
A graph is said to be infinite if it has an infinite number of vertices as well as an
infinite number of edges.

Downloaded by Krishna Patel (patelkrishna90050@gmail.com)


lOMoARcPSD|29361042

3. Trivial Graph:
A graph is said to be trivial if a finite graph contains only one vertex and no
edge.

4. Simple Graph:
A simple graph is a graph that does not contain more than one edge between
the pair of vertices. A simple railway track connecting different cities is an
example of a simple graph.

Downloaded by Krishna Patel (patelkrishna90050@gmail.com)


lOMoARcPSD|29361042

5. Multi Graph:
Any graph which contains some parallel edges but doesn’t contain any self-loop
is called a multigraph. For example a Road Map.
 Parallel Edges: If two vertices are connected with more than one
edge then such edges are called parallel edges that are many routes
but one destination.
 Loop: An edge of a graph that starts from a vertex and ends at the
same vertex is called a loop or a self-loop.

Downloaded by Krishna Patel (patelkrishna90050@gmail.com)


lOMoARcPSD|29361042

6. Null Graph:
A graph of order n and size zero is a graph where there are only isolated
vertices with no edges connecting any pair of vertices.

7. Complete Graph:
A simple graph with n vertices is called a complete graph if the degree of each
vertex is n-1, that is, one vertex is attached with n-1 edges or the rest of the
vertices in the graph. A complete graph is also called Full Graph.

8. Pseudo Graph:
A graph G with a self-loop and some multiple edges is called a pseudo graph.

Downloaded by Krishna Patel (patelkrishna90050@gmail.com)


lOMoARcPSD|29361042

9. Regular Graph:
A simple graph is said to be regular if all vertices of graph G are of equal degree.
All complete graphs are regular but vice versa is not possible.

10. Bipartite Graph:


A graph G = (V, E) is said to be a bipartite graph if its vertex set V(G) can be
partitioned into two non-empty disjoint subsets. V1(G) and V2(G) in such a way
that each edge e of E(G) has one end in V1(G) and another end in V2(G). The
partition V1 U V2 = V is called Bipartite of G. Here in the figure: V1(G)={V5, V4,
V3} and V2(G)={V1, V2}

Downloaded by Krishna Patel (patelkrishna90050@gmail.com)


lOMoARcPSD|29361042

11. Labeled Graph:


If the vertices and edges of a graph are labeled with name, date, or weight then
it is called a labeled graph. It is also called Weighted Graph.

12. Digraph Graph:


A graph G = (V, E) with a mapping f such that every edge maps onto some
ordered pair of vertices (Vi, Vj) are called a Digraph. It is also called Directed
Graph. The ordered pair (Vi, Vj) means an edge between Vi and Vj with an
arrow directed from Vi to Vj. Here in the figure: e1 = (V1, V2) e2 = (V2, V3) e4 =
(V2, V4)

Downloaded by Krishna Patel (patelkrishna90050@gmail.com)


lOMoARcPSD|29361042

 ASYMPTOTIC ANALYSIS:

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.
Usually, 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.

Downloaded by Krishna Patel (patelkrishna90050@gmail.com)


lOMoARcPSD|29361042

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.

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)

Theta Notation, θ

Downloaded by Krishna Patel (patelkrishna90050@gmail.com)


lOMoARcPSD|29361042

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 −

CONCLUSION:

CONCEPT OF PROGRAMMING ARE MADE SIMPLE AND


EASY.
Every topic is explained with real life examples
This course is designed to make you familiar with data
structure and algorithms

REFERENCES:
HP STUDENT REFERENCE GUIDE
BY ABDUL BARI

Downloaded by Krishna Patel (patelkrishna90050@gmail.com)

You might also like