DS Note
DS Note
The data type is the form of a variable to which Data structure is a collection of different kinds of
a value can be assigned. It defines that the data. That entire data can be represented using
particular variable will assign the values of the an object and can be used throughout the
given data type only. program.
It can hold value but not data. Therefore, it is It can hold multiple types of data within a single
dataless. object.
There is no time complexity in the case of data In data structure objects, time complexity plays
types. an important role.
Now we may think that the processor will allocate memory to this structure as shown below:
The total memory allocated in this case is 8 bytes. But this never happens as the processor can
access memory with a fixed word size of 4 bytes. So, the integer variable c can not be allocated
Data Structures
memory as shown above. An integer variable requires 4 bytes. The correct way of allocation of
memory is shown below for this structure using padding bytes.
The processor will require a total of 12 bytes for the above structure to maintain the data
alignment.
Example: Consider two structures given below in C:
For the first structure test1 the short variable takes 2 bytes. Now the next variable is int which
requires 4 bytes. So, 2 bytes of padding are added after the short variable. Now, the char
variable requires 1 byte but memory will be accessed in word size of 4 bytes so 3 bytes of
padding is added again. So, a total of 12 bytes of memory is required. We can similarly
calculate the padding for the second structure also. Padding for both of the structures is
shown below:
i. Strings
In data structures, a string is a sequence of characters used to represent text. Strings are
commonly used for storing and manipulating textual data in computer programs.
Strings are considered a data type in general and are typically represented as arrays of bytes
(or words) that store a sequence of characters. Strings are defined as an array of characters.
The difference between a character array and a string is that the string is terminated with a
special character ‘\0’.
They can be manipulated using various operations like concatenation, substring extraction, and
comparison.
Note: In some languages, strings are implemented as arrays of characters, making them a
derived data type.
Data Structures
String Operations
Strings support a wide range of operations, including concatenation, substring extraction, length
calculation, and more. These operations allow developers to manipulate and process string data
efficiently.
Below are fundamental operations commonly performed on strings in programming.
- Concatenation: Combining two strings to create a new string.
- Length: Determining the number of characters in a string.
- Access: Accessing individual characters in a string by index.
- Substring: Extracting a portion of a string.
- Comparison: Comparing two strings to check for equality or order.
- Search: Finding the position of a specific substring within a string.
- Modification: Changing or replacing characters within a string.
Data Structures
One of the most general operations on String is to find the length/size of a given string. Length
is defined as the number of characters in a string is called the length of that string.
Below is the algorithm for finding Length of string without using any inbuilt methods:
Algorithm: LENGTH(STRING)
1. SET LEN = 0 AND I = 0.
2. Repeat Steps 3 to 4 while STRING[I] is not NULL:
3. LEN = LEN + 1.
4. SET I = I + 1.
5. Exit.
Data Structures
2. Concatenation of Strings
The process of combining more than one string together is known as Concatenation. String
Concatenation is the technique of combining two strings.
Below is the algorithm for String concatenation without using any inbuilt methods:
Algorithm: CONCATENATE (STR1, STR2, STR3)
1. LEN1 = LENGTH(STR1).
2. LEN2 = LENGTH(STR2).
3. SET I = 0.
4. Repeat Steps 5 and 6 while I < LEN1-1:
5. STR3[I] = STR1[I].
6. SET I = I+1.
7. SET J = 0.
8. Repeat Steps 9 to 11 while I < (LEN1 + LEN2 - 2):
9. STR3[I] = STR2[J].
10. J = J+1.
11. I = I+1.
12.Exit.
Data Structures
3. Find in String
A very basic operation performed on Strings is to find something in the given whole string. Now,
this can be to find a given character in a string, or to find a complete string in another string.
An efficient solution is to use an O(n) searching algorithm like KMP algorithm, Z algorithm, etc.
Data Structures
ii. Array:
An array is a collection of data 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).
Characteristics of an Array:
An array has various characteristics which are as follows:
- Arrays use an index-based data structure which helps to identify each of the elements in
an array easily using the index.
- If a user wants to store multiple values of the same data type, then the array can be
utilized efficiently.
Data Structures
- An array can also handle complex data structures by storing data in a two-dimensional
array.
- An array is also used to implement other data structures like Stacks, Queues, Heaps,
Hash tables, etc.
- The search process in an array can be done very easily.
- Memory efficiency: Arrays are a memory-efficient way of storing data. Because the
elements of an array are stored in contiguous memory locations, the size of the array is
known at compile time. This means that memory can be allocated for the entire array in
one block, reducing memory fragmentation.
- Versatility: Arrays can be used to store a wide range of data types, including integers,
floating-point numbers, characters, and even complex data structures such as objects
and pointers.
- Easy to implement: Arrays are easy to implement and understand, making them an ideal
choice for beginners learning computer programming.
- Compatibility with hardware: The array data structure is compatible with most hardware
architectures, making it a versatile tool for programming in a wide range of
environments.
Applications of Array:
Different applications of an array are as follows:
- An array is used in solving matrix problems.
Data Structures
Syntax: Syntax:
data_type array_name[array_size]; data_type
Example: array[1st_dim_size][2nd_dim_size];
int nums[5]; Example:
where, int nums[5][10];
data_type: is a type of data of each array block. where,
array_name: is the name of the array using which data_type: is a type of data of each array block.
we can refer to it. array_name: is the name of the array using which
array_size: is the number of blocks the memory we can refer to it.
array going to have. sizeof_dimension: is the number of blocks of
memory array going to have in the corresponding
dimension.
Three-dimensional array
Example:
int nums[5][10][2];
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
Syntax: memory array going to have in the
data_type
array_name[1st_dim_size][2nd_dim_size] corresponding dimension.
[3rd_dim_size];
Data Structures
- Worst-fit − Using this tactic, the allocator looks through the complete linked list for the
biggest memory block that satisfies the request. While this may lead to bigger unused
memory blocks and more fragmentation, it can be advantageous when large memory
blocks are required.
- Traversing elements: The elements in a linked list can be traversed by starting from the
head node and following the references to the next nodes until the end of the list is
reached.
- Reversing a linked list: The linked list can be reversed by updating the references of
each node so that they point to the previous node instead of the next node.
Complexity Analysis:
Time Complexity: O(1), We have a pointer to the head and we can directly attach a node and
change the pointer. So the Time complexity of inserting a node at the head position is O(1) as it
does a constant amount of work.
Auxiliary Space: O(1)
Data Structures
Complexity Analysis:
Time complexity: O(1), since prev_node is already given as argument in a method, no need to
iterate over list to find prev_node
Auxiliary Space: O(1) since using constant space to modify pointers
Data Structures
Complexity Analysis:
Time complexity: O(N), where N is the number of nodes in the linked list. Since there is a loop
from head to end, the function does O(n) work.
This method can also be optimized to work in O(1) by keeping an extra pointer to the tail of the
linked list/
Auxiliary Space: O(1)
Data Structures
Inserting a new node in a doubly linked list is very similar to inserting a new node in a linked list.
There is a little extra work required to maintain the link of the previous node. A node can be
inserted in a Doubly Linked List in four ways:
A. At the front of the DLL.
B. In between two nodes
a. After a given node.
b. Before a given node.
C. At the end of the DLL.
A. Insert a node at the front in a Doubly Linked List: The new node is always added before
the head of the given Linked List. The task can be performed by using the following 5 steps:
i. Firstly, allocate a new node (say new_node).
ii. Now put the required data in the new node.
iii. Make the next of new_node point to the current head of the doubly linked list.
iv. Make the previous of the current head point to new_node.
v. Lastly, point head to new_node.
Illustration:
See the below illustration where E is being inserted at the beginning of the doubly linked list.
B. Insert a node in between two nodes: It is further classified into the following two parts:
After a given node Before a given node
We are given a pointer to a node as Let the pointer to this given node be
prev_node, and the new node is inserted after next_node.
the given node.
This can be done using the following 6 steps: This can be done using the following 6 steps.
i. Firstly create a new node (say new_node). i. Allocate memory for the new node, let it be
ii. Now insert the data in the new node. called new_node.
iii. Point the next of new_node to the next of ii. Put the data in new_node.
prev_node. iii. Set the previous pointer of this new_node as
iv. Point the next of prev_node to new_node. the previous node of the next_node.
v. Point the previous of new_node to iv. Set the previous pointer of the next_node as
prev_node. the new_node.
vi. Change the pointer of the new node’s v. Set the next pointer of this new_node as the
previous pointer to new_node. next_node.
vi. Now set the previous pointer of new_node.
- If the previous node of the new_node is
not NULL, then set the next pointer of
this previous node as new_node.
- Else, if the prev of new_node is NULL,
it will be the new head node.
Illustration: Illustration:
See the below illustration where ‘E‘ is being See the below illustration where ‘B‘ is being
inserted after ‘B‘. inserted before ‘C‘.
In a circular Singly linked list, the last node of Circular Doubly Linked List has properties of
the list contains a pointer to the first node of both doubly linked list and circular linked list
the list. We traverse the circular singly linked in which two consecutive elements are linked
list until we reach the same node where we or connected by the previous and next pointer
started. The circular singly linked list has no and the last node points to the first node by
beginning or end. No null value is present in the next pointer and also the first node points
the next part of any of the nodes. to the last node by the previous pointer.
Time Complexity: O(N), Worst case occurs when the element to be deleted is the last element
and we need to move through the whole list.
Auxiliary Space: O(1), As constant extra space is used.
Circular linked lists are similar to Single Linked Lists with the exception of connecting the last
node to the first node.
C: C++:
// node structure // Class Node, similar to the
struct Node { linked list
int data; class Node{
struct Node *next; int value;
}; // Points to the next node.
// driver code Node next;
Node* one = createNode(3); }
Node* two = createNode(5); // driver code
Node* three = createNode(9); // Initialize the Nodes.
Node one = new Node(3);
// Connect nodes Node two = new Node(5);
one->next = two; Node three = new Node(9);
two->next = three;
three->next = one; // Connect nodes
one.next = two;
two.next = three;
three.next = one;
Python: Java:
# Class Node, similar to the public class Node {
linked list int data;
class Node: Node next;
def __init__(self,data):
self.data = data public Node(int data) {
self.next = None this.data = data;
this.next = null;
# Initialize the Nodes. }
one = Node(3) }
two = Node(5)
three = Node(9) // Initialize the Nodes.
Node one = new Node(3);
# Connect nodes Node two = new Node(5);
one.next = two Node three = new Node(9);
two.next = three
Data Structures
PHP:
class Node {
public $data;
public $next;
function __construct($data) {
$this->data = $data;
$this->next = null;
}
}
// Connect nodes
$one->next = $two;
$two->next = $three;
$three->next = $one;
Data Structures
- Cost of Circularity: In some circumstances, the list’s circularity may result in additional
overhead. For instance, it may be challenging to tell whether the traversal of the list has
completely circled the object and returned to its beginning place.
- More Complex to Debug: Circular doubly linked lists can be more difficult to debug than
single-linked lists because the circular nature of the list might introduce loops that are
challenging to find and repair.
Data Structures
iv. Stack:
Stack is a linear data structure which follows a particular order in which the operations are
performed. The order may be LIFO(Last In First Out) or FILO(First In Last Out). In stack, all
insertion and deletion are permitted at only one end of the list.
Characteristics of a Stack:
Stack has various different characteristics which are as follows:
- Stack is used in many different algorithms like Tower of Hanoi, tree traversal, recursion,
etc.
- Stack is implemented through an array or linked list.
- It follows the Last In First Out operation i.e., an element that is inserted first will pop in
last and vice versa.
- The insertion and deletion are performed at one end i.e. from the top of the stack.
- In stack, if the allocated space for the stack is full, and still anyone attempts to add more
elements, it will lead to stack overflow.
Data Structures
Applications of Stack:
Different applications of Stack are as follows:
- The stack data structure is used in the evaluation and conversion of arithmetic
expressions.
- It is used for parenthesis checking.
- While reversing a string, the stack is used as well.
- Stack is used in memory management.
- It is also used for processing function calls.
- The stack is used to convert expressions from infix to postfix.
- The stack is used to perform undo as well as redo operations in word processors.
- The stack is used in virtual machines like JVM.
- The stack is used in the media players. Useful to play the next and previous song.
- The stack is used in recursion operations.
Stack Operations:
- push(): When this operation is performed, an element is inserted into the stack.
- pop(): When this operation is performed, an element is removed from the top of the stack
and is returned.
- top(): This operation will return the last inserted element that is at the top without
removing it.
- size(): This operation will return the size of the stack i.e. the total number of elements
present in the stack.
- isEmpty(): This operation indicates whether the stack is empty or not.
Data Structures
v. Queue:
Like Stack, Queue is a linear structure which follows a particular order in which the operations
are performed. The order is First In First Out (FIFO). In the queue, items are inserted at one end
and deleted from the other end. A good example of the queue is any queue of consumers for a
resource where the consumer that came first is served first. The difference between stacks and
queues is in removing. In a stack we remove the item the most recently added; in a queue, we
remove the item the least recently added.
Characteristics of a Queue:
The queue has various different characteristics which are as follows:
- The queue is a FIFO (First In First Out) structure.
- To remove the last element of the Queue, all the elements inserted before the new
element in the queue must be removed.
- A queue is an ordered list of elements of similar data types.
Applications of Queue:
Different applications of Queue are as follows:
- Queue is used for handling website traffic.
- It helps to maintain the playlist in media players.
- Queue is used in operating systems for handling interrupts.
- It helps in serving requests on a single shared resource, like a printer, CPU task
scheduling, etc.
Data Structures
- It is used in the asynchronous transfer of data e.g. pipes, file IO, and sockets.
- Queues are used for job scheduling in the operating system.
- In social media to upload multiple photos or videos, a queue is used.
- To send an e-mail queue data structure is used.
- To handle website traffic at a time queues are used.
- In the Windows operating system, to switch multiple applications.
Queue Operations:
- Enqueue(): Adds (or stores) an element to the end of the queue..
- Dequeue(): Removal of elements from the queue.
- Peek() or front(): Acquires the data element available at the front node of the queue
without deleting it.
- rear(): This operation returns the element at the rear end without removing it.
- isFull(): Validates if the queue is full.
- isNull(): Checks if the queue is empty.
Data Structures
vi. Matrix:
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.
A matrix with 9 elements is shown below.
Data Structures
PART II
Data Structures
ix. Heap:
A Heap is a special Tree-based data structure in which the tree is a complete binary tree.
Generally, Heaps can be of two types:
- Max-Heap: In a Max-Heap the key present at the root node must be greatest among the
keys present at all of its children. The same property must be recursively true for all
sub-trees in that Binary Tree.
- Min-Heap: In a Min-Heap the key present at the root node must be minimum among the
keys present at all of its children. The same property must be recursively true for all
sub-trees in that Binary Tree.
Data Structures
xi. Trie:
Trie is an efficient information retrieval data structure. Using Trie, search complexities can be
brought to an optimal limit (key length). If we store keys in the binary search tree, a
well-balanced BST will need time proportional to M * log N, where M is maximum string length
and N is the number of keys in the tree. Using Trie, we can search the key in O(M) time.
However, the penalty is on Trie storage requirements.