Data Structure Papar
Data Structure Papar
Data Structure Papar
Is
there any time-space trade-off between
the complexity.
The trade-offs between time and space complexity are often inversely
proportional, meaning that improving one may worsen the other. For
example, a hash table is a data structure that can perform insertions,
deletions, and searches in constant time, O(1), regardless of the input
size.
Time complexity is a type of computational complexity that describes the time required
to execute an algorithm.
Advantages of Algorithms
Easy to understand: Since it is a stepwise representation of a solution to
a given problem, it is easy to understand.
Language Independent: It is not dependent on any programming
language, so it can easily be understood by anyone.
Debug / Error Finding: Every step is independent / in a flow so it will be
easy to spot and fix the error.
Sub-Problems: It is written in a flow so now the programmer can divide
the tasks which makes them easier to code.
Disadvantages of Algorithms
Creating efficient algorithms is time-consuming and requires good logical
skills.
Nasty to show branching and looping in algorithms.
Re-Rendering or Stored images: In this case, storing only the source and
rendering it as an image would take more space but less time i.e., storing an
image in the cache is faster than re-rendering but requires more space in
memory.
Algorithm
Algorithm:
Partition Algorithm:
Since, pivot is at left, so algorithm starts from right and move towards left.
Now, a[pivot] < a[right], so algorithm moves forward one position towards left, i.e. -
Now, a[left] = 24, a[right] = 19, and a[pivot] = 24.
Because, a[pivot] > a[right], so, algorithm will swap a[pivot] with a[right], and pivot
moves to right, as -
Now, a[left] = 19, a[right] = 24, and a[pivot] = 24. Since, pivot is at right, so algorithm
starts from left and moves to right.
Now, a[left] = 29, a[right] = 24, and a[pivot] = 24. As a[pivot] < a[left], so, swap a[pivot]
and a[left], now pivot is at left, i.e. -
Since, pivot is at left, so algorithm starts from right, and move to left. Now, a[left] = 24,
a[right] = 29, and a[pivot] = 24. As a[pivot] < a[right], so algorithm moves one position
to left, as -
Now, a[pivot] = 24, a[left] = 24, and a[right] = 14. As a[pivot] > a[right], so, swap a[pivot]
and a[right], now pivot is at right, i.e. -
Now, a[pivot] = 24, a[left] = 14, and a[right] = 24. Pivot is at right, so the algorithm starts
from left and move to right.
Now, a[pivot] = 24, a[left] = 24, and a[right] = 24. So, piv
Now, in a similar manner, quick sort algorithm is separately applied to the left and right
sub-arrays. After sorting gets done, the array will be -
What is the need of dynamic data
structure? Discuss.
Data structure is a way of storing and organizing data efficiently such that
the required operations on them can be performed be efficient with respect
to time as well as memory. Simply, Data Structure are used to reduce
complexity (mostly the time complexity) of the code. Data structures can be
two types : 1. Static Data Structure 2. Dynamic Data Structure
A dynamic data structure has a dynamic size, that is, its size can grow
and shrink based on the elements present in it at runtime. It makes
efficient use of memory by using only that amount of space in memory
that is required at any time. Dynamic memory allocation can be done
in both the stack and the heap.
What is a Static Data structure?
In Static data structure the size of the structure is fixed. The content of the data
structure can be modified but without changing the memory space allocated to it.
1. Vector
2. Linked List
3. Stack
4. Queue
5. Tree
Arrays, Stacks, Queues, Trees Lists, Trees (with variable size), Hash
Examples
(with fixed size) tables
What is the need of dynamic data structure?
The main advantage of dynamic data structures is their flexibility. They can grow or
shrink as needed, which makes them more efficient for large data sets.
1. It is difficult to program the dynamic data structures as the system needs to keep track of
the size and data item's locations at all times.
2. Since the memory allocation is dynamic, there is a possibility
of overflow and underflow in case the structure exceeds its maximum limit or if the
structure becomes empty respectively.
3. It is slow for implementing searches such as accessing an element in a linked list takes a
linear time.
Types of Arrays
There are majorly three types of arrays:
1. One-dimensional array (1-D arrays)
2. Two-dimensional (2D) array
3. Three-dimensional array
You can imagine a 1d array as a row, where elements are stored one after
another.
1D array
data_type array_name[array_size];
where,
data_type: is a type of data of each array block.
array_name: is the name of the array using which we can refer to it.
array_size: is the number of blocks of memory array going to have.
For Example
int nums[5];
1-D array
2D array
To find the address of any element in a 2-Dimensional array there are the
following two ways-
1. Row Major Order
2. Column Major Order
1. Row Major Order:
Row major ordering assigns successive elements, moving across the rows
and then down the next row, to successive memory locations. In simple
language, the elements of an array are stored in a Row-Wise fashion.
To find the address of the element using row-major order uses the following
formula:
Address of A[I][J] = B + W * ((I – LR) * N + (J – LC))
I = Row Subset of an element whose address to be found,
J = Column Subset of an element whose address to be found,
B = Base address,
W = Storage size of one element store in an array(in byte),
LR = Lower Limit of row/start row index of the matrix(If not given assume it
as zero),
LC = Lower Limit of column/start column index of the matrix(If not given
assume it as zero),
N = Number of column given in the matrix.
Example: Given an array, arr[1………10][1………15] with base
value 100 and the size of each element is 1 Byte in memory. Find the
address of arr[8][6] with the help of row-major order.
Solution:
Given:
Base address B = 100
Storage size of one element store in any array W = 1 Bytes
Row Subset of an element whose address to be found I = 8
Column Subset of an element whose address to be found J = 6
Lower Limit of row/start row index of matrix LR = 1
Lower Limit of column/start column index of matrix = 1
Number of column given in the matrix N = Upper Bound – Lower Bound + 1
= 15 – 1 + 1
= 15
Formula:
Address of A[I][J] = B + W * ((I – LR) * N + (J – LC))
Solution:
Address of A[8][6] = 100 + 1 * ((8 – 1) * 15 + (6 – 1))
= 100 + 1 * ((7) * 15 + (5))
= 100 + 1 * (110)
Address of A[I][J] = 210
2. Column Major Order:
If elements of an array are stored in a column-major fashion means moving
across the column and then to the next column then it’s in column-major
order. To find the address of the element using column-major order use the
following formula:
Address of A[I][J] = B + W * ((J – LC) * M + (I – LR))
I = Row Subset of an element whose address to be found,
J = Column Subset of an element whose address to be found,
B = Base address,
W = Storage size of one element store in any array(in byte),
LR = Lower Limit of row/start row index of matrix(If not given assume it as
zero),
LC = Lower Limit of column/start column index of matrix(If not given assume
it as zero),
M = Number of rows given in the matrix.
Example: Given an array arr[1………10][1………15] with a base value
of 100 and the size of each element is 1 Byte in memory find the address of
arr[8][6] with the help of column-major order.
Solution:
Given:
Base address B = 100
Storage size of one element store in any array W = 1 Bytes
Row Subset of an element whose address to be found I = 8
Column Subset of an element whose address to be found J = 6
Lower Limit of row/start row index of matrix LR = 1
Lower Limit of column/start column index of matrix = 1
Number of Rows given in the matrix M = Upper Bound – Lower Bound + 1
= 10 – 1 + 1
= 10
Formula: used
Address of A[I][J] = B + W * ((J – LC) * M + (I – LR))
Address of A[8][6] = 100 + 1 * ((6 – 1) * 10 + (8 – 1))
= 100 + 1 * ((5) * 10 + (7))
= 100 + 1 * (57)
Address of A[I][J] = 157
3D array
where,
data_type: is a type of data of each array block.
array_name: is the name of the array using which we can refer to it.
sizeof_dimension: is the number of blocks of memory array going to
have in the corresponding dimension.
For Example
int nums[5][10][2];
A 3-Dimensional array is a collection of 2-Dimensional arrays. It is specified
by using three subscripts:
1. Block size
2. Row size
3. Column size
More dimensions in an array mean more data can be stored in that array.
Example:
3-D array
To find the address of any element in 3-Dimensional arrays there are the
following two ways-
Row Major Order
Column Major Order
1. Row Major Order:
To find the address of the element using row-major order, use the following
formula:
Address of A[i][j][k] = B + W *(P* N * (i-x) + P*(j-y) + (k-z))
Here:
B = Base Address (start address)
W = Weight (storage size of one element stored in the array)
M = Row (total number of rows)
N = Column (total number of columns)
P = Width (total number of cells depth-wise)
x = Lower Bound of Row
y = Lower Bound of Column
z = Lower Bound of Width
Example: Given an array, arr[1:9, -4:1, 5:10] with a base value of 400 and
the size of each element is 2 Bytes in memory find the address of
element arr[5][-1][8] with the help of row-major order?
Solution:
Given:
Block Subset of an element whose address to be found I = 5
Row Subset of an element whose address to be found J = -1
Column Subset of an element whose address to be found K = 8
Base address B = 400
Storage size of one element store in any array(in Byte) W = 2
Lower Limit of blocks in matrix x = 1
Lower Limit of row/start row index of matrix y = -4
Lower Limit of column/start column index of matrix z = 5
M(row) = Upper Bound – Lower Bound + 1 = 1 – (-4) + 1 = 6
N(Column)= Upper Bound – Lower Bound + 1 = 10 – 5 + 1 = 6
Formula used:
Address of[I][J][K] =B + W (M * N(i-x) + N *(j-y) + (k-z))
Solution:
Address of arr[5][-1][8] = 400 + 2 * {[6 * 6 * (5 – 1)] + 6 * [(-1 + 4)]} + [8 – 5]
= 400 + 2 * (6*6*4)+(6*3)+3
= 400 + 2 * (165)
= 730
Example: Given an array arr[1:8, -5:5, -10:5] with a base value of 400 and
the size of each element is 4 Bytes in memory find the address of
element arr[3][3][3] with the help of column-major order?
Solution:
Given:
Row Subset of an element whose address to be found I = 3
Column Subset of an element whose address to be found J = 3
Block Subset of an element whose address to be found K = 3
Base address B = 400
Storage size of one element store in any array(in Byte) W = 4
Lower Limit of blocks in matrix x = 1
Lower Limit of row/start row index of matrix y = -5
Lower Limit of column/start column index of matrix z = -10
M (row)= Upper Bound – Lower Bound + 1 = 5 +5 + 1 = 11
N (column)= Upper Bound – Lower Bound + 1 = 5 + 10 + 1 = 16
Formula used:
Address of A[i][j][k]=B+W×(M×P×(k−z)+M×(j−y)+(i−x))
Solution:
Address of arr[3][3][3] = 400 + 4 * ((11*16*(3-1)+11*(3-(-10)+(3-(-5)))
= 400 + 4 * ((176*2 + 11*13 + 8)
= 400 + 4 * (503)
= 400 + 2012
= 2412
The above figure shows an array of character type having 10 values. If we want to search
'E', then the searching begins from the 0th element and scans each element until the
element, i.e., 'E' is not found. We cannot directly jump from the 0th element to the
4th element, i.e., each element is scanned one by one till the element is not found.
In the above case, 'a' is the name of the array, mid is the index of the element calculated
recursively, data is the element that is to be searched, left denotes the left element of the array
and right denotes the element that occur on the right side of the array.
Definition The linear search starts searching from It finds the position of the searched
the first element and compares each element by finding the middle
element with a searched element till the element of the array.
element is not found.
Sorted data In a linear search, the elements don't The pre-condition for the binary
need to be arranged in sorted order. search is that the elements must be
arranged in a sorted order.
Implementation The linear search can be implemented The implementation of binary search
on any linear data structure such as an is limited as it can be implemented
array, linked list, etc. only on those data structures that
have two-way traversal.
Approach It is based on the sequential approach. It is based on the divide and conquer
approach.
Size It is preferrable for the small-sized data It is preferrable for the large-size data
sets. sets.
Efficiency It is less efficient in the case of large- It is more efficient in the case of large-
size data sets. size data sets.
Worst-case In a linear search, the worst- case In a binary search, the worst-case
scenario scenario for finding the element is O(n). scenario for finding the element is
O(log2n).
Set j to 1
If j > n, jump to step 7
If X[j] == i, jump to step 6
Then, increment j by 1 i.e. j = j+1
Go back to step 2
Display the element i which is found at particular index i, then jump to step 8
Display element not found in the set of input elements.
Exit/End
Binary Search Algorithm:
In this algorithm,
Divide the search space into two halves by finding the middle index
“mid”.
Compare the middle element of the search space with the key.
If the key is found at middle element, the process is terminated.
If the key is not found at middle element, choose which half will be used
as the next search space.
If the key is smaller than the middle element, then the left side is
used for next search.
If the key is larger than the middle element, then the right side is
used for next search.
This process is continued until the key is found or the total search space
is exhausted.
What is Stack?
Stack is a linear data structure that follows LIFO (Last In First Out)
Principle , so the last element inserted is the first to be popped out. In this
article, we will cover all the basics of Stack, Operations on Stack, its
implementation, advantages, disadvantages which will help you solve all the
problems based on Stack.
Types of Stack:
Fixed Size Stack : As the name suggests, a fixed size stack has a fixed
size and cannot grow or shrink dynamically. If the stack is full and an
attempt is made to add an element to it, an overflow error occurs. If the
stack is empty and an attempt is made to remove an element from it, an
underflow error occurs.
Dynamic Size Stack : A dynamic size stack can grow or shrink
dynamically. When the stack is full, it automatically increases its size to
accommodate the new element, and when the stack is empty, it
decreases its size. This type of stack is implemented using a linked list,
as it allows for easy resizing of the stack.
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 if stack is empty else false.
isFull() returns true if the stack is full else false.
Push Operation in Stack:
Adds an item to the stack. If the stack is full, then it is said to be an Overflow
condition.
Algorithm for Push Operation:
Before pushing the element to the stack, we check if the stack is full .
If the stack is full (top == capacity-1) , then Stack Overflows and we
cannot insert the element to the stack.
Otherwise, we increment the value of top by 1 (top = top + 1) and the
new value is inserted at top position .
The elements can be pushed into the stack till we reach the capacity of
the stack.
isEmpty Operation in Stack:
Returns true if the stack is empty, else false.
Algorithm for isEmpty Operation :
Check for the value of top in stack.
If (top == -1) , then the stack is empty so return true .
Otherwise, the stack is not empty so return false .
#include<conio.h>
#define size 6
int top=-1,item;
int stack[size];
int pop()
if(top<0)
return NULL;
item=stack[top--];
return item;
{
if(top>=size-1)
printf("stack is full");
else
stack[++top]=item;
void main()
int choice;
clrscr();
scanf("%d",&choice);
while(choice!=0)
switch(choice)
case 1:
scanf("%d",&choice);
push(item);
break;
case 2:
item=pop();
printf("\nitem %d deleted",item);
break;
default:
printf("invalid selection");
fflush(stdin);
scanf("%d",&choice);
getch();
Output:
Inserts an element at the end of the queue i.e. at the rear end.
The following steps should be taken to enqueue (insert) data into a queue:
Check if the queue is full.
If the queue is full, return overflow error and exit.
If the queue is not full, increment the rear pointer to point to the next
empty space.
Add the data element to the queue location, where the rear is pointing.
return success.
This operation removes and returns an element that is at the front end of the queue.
The following steps are taken to perform the dequeue operation:
Check if the queue is empty.
If the queue is empty, return the underflow error and exit.
If the queue is not empty, access the data where the front is pointing.
Increment the front pointer to point to the next available data element.
The Return success.
This operation returns the element at the front end without removing it.
The following steps are taken to perform the front operation:
If the queue is empty return the most minimum value.
otherwise, return the front value.
This operation returns the element at the rear end without removing it.
The following steps are taken to perform the rear operation:
If the queue is empty return the most minimum value.
otherwise, return the rear value.
This operation returns a boolean value that indicates whether the queue is
empty or not.
The following steps are taken to perform the Empty operation:
check if front value is equal to -1 or not, if yes then return true means
queue is empty.
Otherwise return false, means queue is not empty
This operation returns a boolean value that indicates whether the queue is
full or not.
The following steps are taken to perform the isFull() operation:
Check if front value is equal to zero and rear is equal to the capacity of
queue if yes then return true.
otherwise return false
This operation returns the size of the queue i.e. the total number of elements
it contains.
queuename.size()
Parameters :
No parameters are passed
Returns :
Number of elements in the container
It is the simplest type of linked list in which every node contains some data
and a pointer to the next node of the same data type.
The node contains a pointer to the next node means that the node stores the
address of the next node in the sequence. A single linked list allows the
traversal of data only in one way. Below is the image for the same:
A doubly linked list or a two-way linked list is a more complex type of linked
list that contains a pointer to the next as well as the previous node in
sequence.
Therefore, it contains three parts of data, a pointer to the next node, and a
pointer to the previous node. This would enable us to traverse the list in the
backward direction as well. Below is the image for the same:
A circular linked list is that in which the last node contains the pointer to the
first node of the list.
While traversing a circular linked list, we can begin at any node and traverse
the list in any direction forward and backward until we reach the same node
we started. Thus, a circular linked list has no beginning and no end. Below is
the image for the same:
Example:
Input: LinkedList = 2->3->4->5, NewNode = 1, InsertAfter = 2
Output: LinkedList = 2->1->3->4->5
Input: LinkedList = , NewNode = 1, InsertAfter = 2
Output: No such node found
Given a Linked List, the task is to insert a new node in this given Linked List
at the following positions:
At the front of the linked list
After a given node.
At the end of the linked list.
Approach:
To insert a node at the start/beginning/front of a Linked List, we need to:
Make the first node of Linked List linked to the new node
Remove the head from the original first node of Linked List
Make the new node as the Head of the Linked List.
To insert a node after a given node in a Linked List, we need to:
Check if the given node exists or not.
If it do not exists,
terminate the process.
If the given node exists,
Make the element to be inserted as a new node
Change the next pointer of given node to the new node
Now shift the original next pointer of given node to the
next pointer of new node
Approach:
To insert a node at the end of a Linked List, we need to:
Go to the last node of the Linked List
Change the next pointer of last node from NULL to the new node
Make the next pointer of new node as NULL to show the end of Linked
List
2. How to Insert a Node after a Given Node in Linked List
if(position == 1)
{
temp -> next = head;
return temp;
}
if(curr == NULL)
{
return head;
}
A doubly linked list (DLL) is a special type of linked list in which each node contains a pointer
to the previous node as well as the next node of the linked list.
1. struct node
2. {
3. struct node *prev;
4. int data;
5. struct node *next;
6. };
7. struct node *head;
SN Operation Description
1 Insertion at beginning Adding the node into the linked list at beginning.
2 Insertion at end Adding the node into the linked list to the end.
3 Insertion after specified Adding the node into the linked list after the specified node.
node
5 Deletion at the end Removing the node from end of the list.
6 Deletion of the node Removing the node which is present just after the node containing the
having given data given data.
7 Searching Comparing each node data with the item to be searched and return the
location of the item in the list if the item found else return null.
8 Traversing Visiting each node of the list at least once in order to perform some
specific operation like searching, sorting, display, etc.
Insertion in doubly linked list at beginning
o Allocate the space for the new node in the memory. This will be done by using
the following statement.
2. ptr->next = NULL;
3. ptr->prev=NULL;
4. ptr->data=item;
5. head=ptr;
6. ptr->next = head;
7. head→prev=ptr;
1. ptr→prev =NULL
2. head = ptr
Algorithm :
o Step 1: IF ptr = NULL
Write-OVERFLOW
Go-to-Step-9
[END OF IF]
WRITE-UNDERFLOW
GOTO STEP 6
Write OVERFLOW
Go to Step 11
[END OF IF]
[END OF LOOP]
Write-UNDERFLOW
Go-to-Step-7
[END OF IF]
[END OF LOOP]
1. First, compare the element to be searched with the root element of the tree.
2. If root is matched with the target element, then return the node's location.
3. If it is not matched, then check whether the item is less than the root element, if it
is smaller than the root element, then move to the left subtree.
4. If it is larger than the root element, then move to the right subtree.
5. Repeat the above procedure recursively until the match is found.
6. If the element is not found or not present in the tree, then return NULL.
Algorithm
Delete (TREE, ITEM)
A binary tree
Height of the given binary tree is 2 and the maximum number of nodes
that should be there are 2h+1 – 1 = 22+1 – 1 = 23 – 1 = 7.
But the number of nodes in the tree is 6. Hence it is not a perfect
binary tree.
Now for a complete binary tree, It is full up to height h-1 i.e.; 1, and the
last level element are stored in left to right order. Hence this is
a complete binary tree. Store the element in an array and it will be
like;
Element stored in an array level by level
This algorithm follows the dynamic programming approach to find the shortest
paths.