KP Report
KP Report
Training Report
on
Session: 2023-24
i
ACKNOWLEDGEMENT
ii
CONTENT
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
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
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 ([email protected])
INTRODUCTION
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
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
not
o insert(x), This is used to add x into the queue at the rear end
List −
o size(), this function is used to get number of elements
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
consumed for addition of two bits. Here, we observe that t(N) grows linearly as input
size increases.
RECURSION
on the stack. A recursive function calls itself, the memory for a called
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
process continues.
b) TAIL RECURSION:
Tail recursion is defined as a recursive function in which the recursive
void print(int n)
{
if (n < 0)
return;
cout << " " << n;
c) HEAD RECURSION:
If a recursive function calling itself and that recursive call is the first
#include <bits/stdc++.h>
using namespace std;
// Recursive function
void fun(int n)
{
if (n > 0) {
// 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.
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:
Static Arrays:
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.
c) 2D ARRAYS:
data_type array_name[rows][columns];
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:
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;
// insert x at pos
arr[pos - 1] = x;
return 0;
#include<bits/stdc++.h>
using namespace std;
// 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:
#include <stdio.h>
// Driver's code
int main(void)
{
int arr[] = { 2, 3, 4, 10, 40 };
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:
else
mid = (low + high) / 2
if x == arr[mid]
side
return mid
STRING:
a) INTRODUCTION TO STRINGS:
A string is generally considered as a data type and is often implemented
may also denote more general arrays or other sequence (or list) data
// 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:
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:
#include <bits/stdc++.h>
using namespace std;
C) SYMMETRIC MATRIX:
#include <iostream>
using namespace std;
// 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;
}
. 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. }
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();
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
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
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
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.
4. Simple Graph:
A simple graph is a graph that does not contain more than one edge between
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.
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.
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
OMEGA NOTATION :
The notation
Ω(n) is the formal way to express the lower bound of an algorithm's running time. It measures the best cas
an algorithm can possibly take to complete.
Theta Notation,
θ
The notation
θ(n) is the formal way to express both the lower bound and the upper bound of an algorithm's running tim
CONCLUSION:
THANK YOU