0% found this document useful (0 votes)
12 views46 pages

DS Note

Uploaded by

mdjavad8
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
12 views46 pages

DS Note

Uploaded by

mdjavad8
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 46

Data Structures

Introduction to Data Structures

1. What is Data Structure?


● A data structure is a particular way of organizing data in a computer so that it can be
used effectively. The idea is to reduce the space and time complexities of different tasks.

2. Need Of Data Structure:


The structure of the data and the synthesis of the algorithm are relative to each other. Data
presentation must be easy to understand so the developer, as well as the user, can make an
efficient implementation of the operation.
Data structures provide an easy way of organizing, retrieving, managing, and storing data.

Here is a list of the needs for data.


- Data structure modification is easy.
- It requires less time.
- Save storage memory space.
- Data representation is easy.
- Easy access to the large database

3. Applications of Data Structures:


Data structures are used in various fields such as:
- Operating system
- Graphics
- Computer Design
- Blockchain
- Genetics
- Image Processing
- Simulation, etc.
Data Structures

4. Classification/Types of Data Structures:


● Linear data structure: Data structure in which data elements are arranged sequentially
or linearly, where each element is attached to its previous and next adjacent elements, is
called a linear data structure.
Examples of linear data structures are array, stack, queue, linked list, etc.
○ Static data structure: Static data structure has a fixed memory size. It is easier
to access the elements in a static data structure.
An example of this data structure is an array.
○ Dynamic data structure: In the dynamic data structure, the size is not fixed. It
can be randomly updated during the runtime which may be considered efficient
concerning the memory (space) complexity of the code.
Examples of this data structure are queue, stack, etc.
● Non-linear data structure: Data structures where data elements are not placed
sequentially or linearly are called non-linear data structures. In a non-linear data
structure, we can’t traverse all the elements in a single run only.
Examples of non-linear data structures are trees and graphs.
Data Structures

5. How does Data Structure vary from Data Type?


A few differences between data type and data structure:

Data Type Data Structure

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.

The implementation of a data type is known as Data structure implementation is known as


abstract implementation. concrete implementation.

There is no time complexity in the case of data In data structure objects, time complexity plays
types. an important role.

While in the case of data structures, the data


In the case of data types, the value of data is and its value acquire the space in the
not stored because it only represents the type computer’s main memory. Also, a data structure
of data that can be stored. can hold different kinds and types of data within
one single object.

Data structure examples are stack, queue, tree,


Data type examples are int, float, double, etc.
etc.
Data Structures

6. Data Structure Alignment : How data is arranged and accessed


in Computer Memory?
Data structure alignment is the way data is arranged and accessed in computer memory. Data
alignment and Data structure padding are two different issues but are related to each other and
together known as Data Structure alignment.
Data alignment: Data alignment means putting the data in memory at an address equal to
some multiple of the word size. This increases the performance of the system due to the way
the CPU handles memory.
Data Structure Padding: Now, to align the data, it may be necessary to insert some extra bytes
between the end of the last data structure and the start of the next data structure as the data is
placed in memory as multiples of fixed word size. This insertion of extra bytes of memory to
align the data is called data structure padding.

Consider the structure as shown below:


struct
{
char a;
short int b;
int c;
char d;
}

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:

// first structure // second structure


struct test1 struct test2
{ {
short s; int i;
int i; char c;
char c; short s;
}; };

size of struct test1 is 12 size of struct test2 is 8

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:

struct test1 struct test2


{ {
short s; int i;
// 2 bytes // 4 bytes
// 2 padding bytes char c;
int i; // 1 byte
// 4 bytes // 1 padding byte
char c; short s;
// 1 byte // 2 bytes
// 3 padding bytes };
};
Data Structures

Most Used Data Structures


PART I
Data Structures

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.

String Data Type


In most programming languages, strings are treated as a distinct data type. This means that
strings have their own set of operations and properties. They can be declared and manipulated
using specific string-related functions and methods.

Note: In some languages, strings are implemented as arrays of characters, making them a
derived data type.
Data Structures

How is String represented in Memory?


In C, a string can be referred to either using a character pointer or as a character array. When
strings are declared as character arrays, they are stored like other types of arrays in C. For
example, if str[] is an auto variable then the string is stored in the stack segment, if it’s a global
or static variable then stored in the data segment, etc.

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

General Operations performed on String:

1. Finding the Length of String

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.

a) Find a character in string:


Given a string and a character, your task is to find the first position of the character in the string.
These types of problems are very competitive programming where you need to locate the
position of the character in a string.
b) Find a substring in another string:
Consider there to be a string of length N and a substring of length M. Then run a nested loop,
where the outer loop runs from 0 to (N-M) and the inner loop from 0 to M. For every index check
if the sub-string traversed by the inner loop is the given substring or not.

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.

Operations performed on array:


- Initialization: An array can be initialized with values at the time of declaration or later
using an assignment statement.
- Accessing elements: Elements in an array can be accessed by their index, which starts
from 0 and goes up to the size of the array minus one.
- Searching for elements: Arrays can be searched for a specific element using linear
search or binary search algorithms.
- Sorting elements: Elements in an array can be sorted in ascending or descending order
using algorithms like bubble sort, insertion sort, or quick sort.
- Inserting elements: Elements can be inserted into an array at a specific location, but this
operation can be time-consuming because it requires shifting existing elements in the
array.
- Deleting elements: Elements can be deleted from an array by shifting the elements that
come after it to fill the gap.
- Updating elements: Elements in an array can be updated or modified by assigning a new
value to a specific index.
- Traversing elements: The elements in an array can be traversed in order, visiting each
element once.

Advantages of array data structure:


- Efficient access to elements: Arrays provide direct and efficient access to any element in
the collection. Accessing an element in an array is an O(1) operation, meaning that the
time required to access an element is constant and does not depend on the size of the
array.
- Fast data retrieval: Arrays allow for fast data retrieval because the data is stored in
contiguous memory locations. This means that the data can be accessed quickly and
efficiently without the need for complex data structures or algorithms.
Data Structures

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

Disadvantages of array data structure:


- Fixed size: Arrays have a fixed size that is determined at the time of creation. This
means that if the size of the array needs to be increased, a new array must be created
and the data must be copied from the old array to the new array, which can be
time-consuming and memory-intensive.
- Memory allocation issues: Allocating a large array can be problematic, particularly in
systems with limited memory. If the size of the array is too large, the system may run out
of memory, which can cause the program to crash.
- Insertion and deletion issues: Inserting or deleting an element from an array can be
inefficient and time-consuming because all the elements after the insertion or deletion
point must be shifted to accommodate the change.
- Wasted space: If an array is not fully populated, there can be wasted space in the
memory allocated for the array. This can be a concern if memory is limited.
- Limited data type support: Arrays have limited support for complex data types such as
objects and structures, as the elements of an array must all be of the same data type.
- Lack of flexibility: The fixed size and limited support for complex data types can make
arrays inflexible compared to other data structures such as linked lists and trees.

Applications of Array:
Different applications of an array are as follows:
- An array is used in solving matrix problems.
Data Structures

- Database records are also implemented by an array.


- It helps in implementing a sorting algorithm.
- It is also used to implement other data structures like Stacks, Queues, Heaps, Hash
tables, etc.
- An array can be used for CPU scheduling.
- Can be applied as a lookup table in computers.
- Arrays can be used in speech processing where every speech signal is an array.
- The screen of the computer is also displayed by an array. Here we use a
multidimensional array.
- The array is used in many management systems like a library, students, parliament, etc.
- The array is used in the online ticket booking system. Contacts on a cell phone are
displayed by this array.
- In games like online chess, where the player can store his past moves as well as current
moves. It indicates a hint of position.
- To save images in a specific dimension in the android Like 360*1200

Real-Life Applications of Array:


- An array is frequently used to store data for mathematical computations.
- It is used in image processing.
- It is also used in record management.
- Book pages are also real-life examples of an array.
- It is used in ordering boxes as well.

Advantages of Structure over Array:


- The structure can store different types of data whereas an array can only store similar
data types.
- Structure does not have a limited size like an array.
- Structure elements may or may not be stored in contiguous locations but array elements
are stored in contiguous locations.
- In structures, object instantiation is possible whereas in arrays objects are not possible.
Data Structures

There are majorly three types of arrays:

One-dimensional array (1-D arrays) Two-dimensional (2D) array

A 1d array can be considered as a row, Multidimensional arrays can be considered as


where elements are stored one after another. an array of arrays or as a matrix consisting of
rows and columns.

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

A 3-D Multidimensional array contains three dimensions, so it can be considered an array of


two-dimensional arrays.

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

iii. Linked Lists:


Like arrays, Linked List is a linear data structure. Unlike arrays, linked list elements are not
stored at a contiguous location; the elements are linked using pointers. A linked list is a linear
data structure in which elements are not stored at contiguous memory locations. A linked list is
a fundamental data structure in computer science. It consists of nodes where each node
contains data and a reference (link) to the next node in the sequence. This allows for dynamic
memory allocation and efficient insertion and deletion operations compared to arrays.
The elements in a linked list are linked using pointers as shown in the below image:

Allocation strategies in Linked List Allocation


In Linked List Allocation, the allocator searches the linked list for a memory block of the desired
size according to the allocation strategies. In Linked List distribution, there are three typical
distribution methods −
- First-fit − In this tactic, the memory allocator begins its look at the head of the linked list
and allocates the first memory block that is big enough to accommodate the request.
The memory may become fragmented, but this is the simplest and fastest allocation
method.
- Best-fit − In this approach, the allocator looks through the complete linked list in search
of the smallest memory block that is sizable enough to accommodate the request. While
fragmentation is reduced, the additional searching that must be done could slow down
allocation periods.
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.

Characteristics of a Linked list:


A linked list has various characteristics which are as follows:
- A linked list uses extra memory to store links.
- During the initialization of a linked list, there is no need to know the size of the elements.
- Linked lists are used to implement stacks, queues, graphs, etc.
- The first node of the linked list is called the Head.
- The next pointer of the last node always points to NULL.
- In a linked list, insertion and deletion are possible easily.
- Each node of the linked list consists of a pointer/link which is the address of the next
node.
- Linked lists can shrink or grow at any point in time easily.

Operations performed on Linked list:


A linked list is a linear data structure where each node contains a value and a reference to the
next node. Here are some common operations performed on linked lists:
- Initialization: A linked list can be initialized by creating a head node with a reference to
the first node. Each subsequent node contains a value and a reference to the next node.
- Inserting elements: Elements can be inserted at the head, tail, or at a specific position in
the linked list.
- Deleting elements: Elements can be deleted from the linked list by updating the
reference of the previous node to point to the next node, effectively removing the current
node from the list.
- Searching for elements: Linked lists can be searched for a specific element by starting
from the head node and following the references to the next nodes until the desired
element is found.
- Updating elements: Elements in a linked list can be updated by modifying the value of a
specific node.
Data Structures

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

Applications of the Linked list:


Different applications of linked lists are as follows:
- Linked lists are used to implement stacks, queues, graphs, etc.
- Linked lists are used to perform arithmetic operations on long integers.
- It is used for the representation of sparse matrices.
- It is used in the linked allocation of files.
- It helps in memory management.
- It is used in the representation of Polynomial Manipulation where each polynomial term
represents a node in the linked list.
- Used to display image containers. Users can visit past, current, and next images.
- They are used to store the history of the visited page.
- They are used to perform undo operations.
- Used in software development where they indicate the correct syntax of a tag.
- Linked lists are used to display social media feeds.

Real-Life Applications of a Linked list:


- A linked list is used in Round-Robin scheduling to keep track of the turn in multiplayer
games.
- It is used in image viewer. The previous and next images are linked, and hence can be
accessed by the previous and next buttons.
- In a music playlist, songs are linked to the previous and next songs.
Data Structures

Linked List vs Array

Advantages of Linked List over an Array


- Linked lists are dynamic data structures, which means they can grow or shrink during the
execution of a program.
- There is no need to define an initial size or to specify how many nodes are required.
- Therefore, linked lists have efficient memory utilization and no wastage of memory.
- In Linked list memory is not preallocated. Memory is allocated whenever it is required
and it is de-allocated or removed when it is no longer needed.
- The main advantage of a linked list over an array is Insertion and Deletion operations are
easier and more efficient.
- Linked lists provide flexibility in inserting a data item at a specified position and deletion
of the data item from the given position.
- No need for reallocation or reorganization of the entire structure of the list because the
data items are not stored contiguously in memory or on disk. This will also lead to a
reduction in the data access time in the linked list. But, doing this in an array at run-time
is a very expensive operation. Because the arrays are a type of static data structure,
therefore, the size remains fixed and we would need to allocate all the storage at the
starting.
- Many complex applications can be easily carried out with linked lists.
Data Structures

Types of Linked List


- Singly linked lists.
- Doubly linked lists.
- Circular linked lists.
- Circular doubly linked lists.
Data Structures

Singly Linked List


A singly linked list is a linear data structure in which the elements are not stored in contiguous
memory locations and each element is connected only to its next element using a pointer.
Data Structures

Operations on Linked List:

Insertion in Linked List


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.

A. Insert a Node at the Front/Beginning of Linked List


Approach:
To insert a node at the start/beginning/front of a Linked List, we need to:
1. Make the first node of Linked List linked to the new node
2. Remove the head from the original first node of Linked List
3. Make the new node as the Head of the Linked List.

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

B. Insert a Node after a Given Node in Linked List


Approach:
To insert a node after a given node in a Linked List, we need to:
1. Check if the given node exists or not.
2. If it do not exists,
a. terminate the process.
3. If the given node exists,
a. Make the element to be inserted as a new node
b. Change the next pointer of given node to the new node
c. Now shift the original next pointer of given node to the next pointer of new node

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

C. Insert a Node at the End of Linked List


Approach:
To insert a node at the end of a Linked List, we need to:
1. Go to the last node of the Linked List
2. Change the next pointer of last node from NULL to the new node
3. Make the next pointer of new node as NULL to show the end of Linked List

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

Doubly Linked List


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.

Advantages of Doubly Linked List 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 Doubly Linked List 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.

Applications of Doubly Linked List:


- It is used by web browsers for backward and forward navigation of web pages
- LRU ( Least Recently Used ) / MRU ( Most Recently Used ) Cache are constructed using
Doubly Linked Lists.
- Used by various applications to maintain undo and redo functionalities.
- In Operating Systems, a doubly linked list is maintained by thread scheduler to keep
track of processes that are being executed at that time.
Data Structures

Insertion in a Doubly Linked List

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.

Time Complexity: O(1)


Auxiliary Space: O(1)
Data Structures

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‘.

Time Complexity: O(1) Time Complexity: O(1)


Auxiliary Space: O(1) Auxiliary Space: O(1)
Data Structures

C. Insert a node at the end in a Doubly Linked List:


The new node is always added after the last node of the given Linked List. This can be done
using the following 7 steps:
i. Create a new node (say new_node).
ii. Put the value in the new node.
iii. Make the next pointer of new_node as null.
iv. If the list is empty, make new_node as the head.
v. Otherwise, travel to the end of the linked list.
vi. Now make the next pointer of the last node point to new_node.
vii. Change the previous pointer of new_node to the last node of the list.
Illustration:
See the below illustration where ‘D‘ is inserted at the end of the linked list.

Time Complexity: O(n)


Auxiliary Space: O(1)
Data Structures

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.

There are generally two types of circular linked lists:

Circular Singly linked list: Circular Doubly linked list:

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.

Advantages of Circular Linked Lists:


- Any node can be a starting point. We can traverse the whole list by starting from any
point. We just need to stop when the first visited node is visited again.
Data Structures

- Useful for implementation of a queue. Unlike this implementation, we don’t need to


maintain two pointers for front and rear if we use a circular linked list. We can maintain a
pointer to the last inserted node and the front can always be obtained as next or last.
- Circular lists are useful in applications to repeatedly go around the list. For example,
when multiple applications are running on a PC, it is common for the operating system to
put the running applications on a list and then cycle through them, giving each of them a
slice of time to execute, and then making them wait while the CPU is given to another
application. It is convenient for the operating system to use a circular list so that when it
reaches the end of the list it can cycle around to the front of the list.
- Circular Doubly Linked Lists are used for the implementation of advanced data
structures like the Fibonacci Heap.
- Implementing a circular linked list can be relatively easy compared to other more
complex data structures like trees or graphs.

Disadvantages of circular linked list:


- Compared to singly linked lists, circular lists are more complex.
- Reversing a circular list is more complicated than singly or doubly reversing a circular
list.
- It is possible for the code to go into an infinite loop if it is not handled carefully.
- It is harder to find the end of the list and control the loop.
- Although circular linked lists can be efficient in certain applications, their performance
can be slower than other data structures in certain cases, such as when the list needs to
be sorted or searched.
- Circular linked lists don’t provide direct access to individual nodes
Data Structures

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.

Node representation of a Circular Linked List:

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

three.next = one // Connect nodes


one.next = two;
two.next = three;
three.next = one;

PHP:
class Node {
public $data;
public $next;

function __construct($data) {
$this->data = $data;
$this->next = null;
}
}

$one = new Node(3);


$two = new Node(5);
$three = new Node(9);

// Connect nodes
$one->next = $two;
$two->next = $three;
$three->next = $one;
Data Structures

Circular Doubly Linked List


A circular doubly linked list is defined as a circular linked list in which each node has two links
connecting it to the previous node and the next node.

Characteristics of Circular Doubly Linked List :


A circular doubly linked list has the following properties:
- Circular: A circular doubly linked list’s main feature is that it is circular in design.
- Doubly Linked: Each node in a circular doubly linked list has two pointers – one pointing
to the node before it and the other pointing to the node after it.
- Header Node: At the start of circular doubly linked lists, a header node or sentinel node
is frequently used. This node is used to make the execution of certain operations on the
list simpler even though it is not a component of the list’s actual contents.

Advantages of Circular Doubly Linked List :


Circular doubly linked lists in Data Structures and Algorithms (DSA) have the following benefits:
- Efficient Traversal: A circular doubly linked list’s nodes can be efficiently traversed in
both ways, or forward and backward.
- Insertion and deletion: A circular doubly linked list makes efficient use of insertion and
deletion operations. The head and tail nodes are connected because the list is circular,
making it simple to add or remove nodes from either end.
- Implementation of Circular Data Structures: The implementation of circular data
structures like circular queues and circular buffers makes extensive use of circular
doubly linked lists.

Disadvantages of Circular Doubly Linked List :


Circular doubly linked lists have the following drawbacks when used in DSA:
- Complexity: Compared to a singly linked list, the circular doubly linked list has more
complicated operations, which can make it more difficult to develop and maintain.
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.

Real-Life Applications of Stack:


- Real life example of a stack is the layer of eating plates arranged one above the other.
When you remove a plate from the pile, you can take the plate to the top of the pile. But
this is exactly the plate that was added most recently to the pile. If you want the plate at
the bottom of the pile, you must remove all the plates on top of it to reach it.
- Browsers use stack data structures to keep track of previously visited sites.
- Call log in mobile also uses stack data structure.

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.

Real-Life Applications of Queue:


- A real-world example of a queue is a single-lane one-way road, where the vehicle that
enters first will exit first.
- A more real-world example can be seen in the queue at the ticket windows.
- A cashier line in a store is also an example of a queue.
- People on an escalator

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

vii. Binary Tree:


Unlike Arrays, Linked Lists, Stack and queues, which are linear data structures, trees are
hierarchical data structures. A binary tree is a tree data structure in which each node has at
most two children, which are referred to as the left child and the right child. It is implemented
mainly using Links.
A Binary Tree is represented by a pointer to the topmost node in the tree. If the tree is empty,
then the value of root is NULL. A Binary Tree node contains the following parts.
Data Structures

viii. Binary Search Tree:


A Binary Search Tree is a Binary Tree following the additional properties:
- The left part of the root node contains keys less than the root node key.
- The right part of the root node contains keys greater than the root node key.
- There is no duplicate key present in the binary tree.
A Binary tree having the following properties is known as Binary search tree (BST).
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

x. Hashing Data Structure:


Hashing is an important Data Structure which is designed to use a special function called the
Hash function which is used to map a given value with a particular key for faster access of
elements. The efficiency of mapping depends on the efficiency of the hash function used.
Let a hash function H(x) maps the value x at the index x%10 in an Array. For example, if the list
of values is [11, 12, 13, 14, 15] it will be stored at positions {1, 2, 3, 4, 5} in the array or Hash
table respectively.
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.

You might also like