DS Unit-1[1]
DS Unit-1[1]
OUTCOM PA
COVERED SUB TOPICS
E (WRITE RT
(SYLLBUS (WHAT TO BE TAUGHT)
THE CO) NO.
TOPICS)
1. What is data structures?
2. What is data type?
3. Differences between data type and data structures.
Data structure 4. Characteristics of data structures?
1 Definition of data 5. Basic Terminologies of data structures.
structure
1. What is ADT?
2. Exercises to implement basic operations of various
data structures.
Data structure 3. Real-world examples to demonstrate the practical
1
operations applications of data structures.
CO1
Implement
various list
1. Definition of Lists
operations
2 List: Introduction 2. Operations on Lists
using array
3. Applications
and linked
list Representation 1. Array Implementation and Linked List
2 using array and implementation.
2. Procedures and codings.
linked list
1. Node creation.
2. Insertion at the Beginning, at the End, at a
Specific Position.
Operations of 3. Deletion at the Beginning, at the End, at a Specific
2
Linked Lists Position.
4.Traversal and Searching
A data type is a classification that specifies which type of value a variable can hold in programming
languages. It defines the operations that can be done on the data, the meaning of the data, and the way
values of that type can be stored.
A Data type is one of the forms of a variable to A Data structure is a collection of data of different
which the value can be assigned of a given type data types. This collection of data can be
only. This value can be used throughout the represented using an object and can be used
program. throughout the program.
The implementation of data type is known as an The implementation of data structure is known as a
abstract implementation. concrete implementation.
It can hold value but not data. Therefore, we can It can hold multiple types of data within a single
say that it is data-less. object.
In case of data type, a value can be assigned In the case of data structure, some operations are
directly to the variables. used to assign the data to the data structure object.
`There is no problem in the time complexity. When we deal with a data structure object, time
complexity plays an important role.
The examples of data type are int, float, char. The examples of data structure are stack, queue,
tree, graph.
Data structures possess several characteristics that influence their behaviour and usage in computer
science and software development. Some of the key characteristics of data structures include:
2. Access and Retrieval: Different data structures provide various methods for accessing and
retrieving stored data. Some structures offer fast access times for specific operations (e.g.,
constant time lookup in hash tables), while others may require more time (e.g., linear search
in linked lists).
3. Insertion and Deletion: Data structures have different capabilities and complexities
regarding the insertion and deletion of elements. Some structures, like arrays, may require
shifting elements to accommodate insertions or deletions, while others, like linked lists, can
perform these operations more efficiently.
4. Search and Sorting: Efficient searching and sorting algorithms are essential for data
structures. The time complexity of search and sorting operations varies depending on the
structure used. For example, binary search trees offer efficient searching, while bubble sort
may be less efficient for sorting large datasets.
5. Dynamic Size: Some data structures have dynamic sizing capabilities, meaning they can
grow or shrink in size as needed. Dynamic sizing is advantageous when the number of
elements to be stored is unknown or changes over time.
6. Traversal: Traversal refers to the process of visiting each element in a data structure.
Different structures support different traversal methods, such as depth-first traversal in trees
or linear traversal in arrays.
8. Complexity Analysis: Understanding the time and space complexities of data structure
operations is essential for evaluating their performance. Analyzing complexity helps
developers choose the most suitable data structure for specific tasks and optimize algorithm
design.
Here are some fundamental terminologies commonly associated with data structures:
1. Data: Refers to information that can be processed or manipulated by a computer. Data can be
numeric, alphanumeric, textual, etc.
2. Data Structure: A particular way of organizing and storing data in a computer's memory so
that it can be efficiently accessed and manipulated.
3. Element: Each individual piece of data stored within a data structure. Elements can be of any
data type depending on the structure.
4. Collection: A group of elements treated as a single entity. Data structures often hold
collections of elements.
5. Container: Another term for a data structure that holds a collection of elements. Containers
provide methods for accessing, adding, removing, and manipulating the elements they
contain.
6. Operations: Actions that can be performed on a data structure, such as insertion, deletion,
searching, traversal, and sorting.
7. Access: The process of retrieving or reading the value of an element within a data structure.
8. Update: The process of modifying the value of an existing element within a data structure.
9. Insertion: Adding a new element into a data structure, typically at a specified position or
location.
10. Deletion: Removing an element from a data structure, either by specifying the element to be
removed or its position within the structure.
11. Traversal: Visiting and accessing each element of a data structure in a specific order, such as
linear traversal or depth-first traversal.
12. Search: The process of finding a particular element within a data structure based on some
specified criteria.
13. Sorting: Arranging the elements of a data structure in a specific order, such as ascending or
descending, based on their values.
15. Memory Allocation: The process of reserving memory space to store data elements within a
data structure.
16. Memory Deallocation: The process of releasing previously allocated memory space when
elements are removed from a data structure or when the structure is destroyed.
17. Complexity: Refers to the time and space requirements of various operations performed on a
data structure, often analyzed using Big O notation.
1. Primitive Data Structures are the data structures consisting of the numbers and the
characters that come in-built into programs.
2. These data structures can be manipulated or operated directly by machine-level
instructions.
3. Basic data types like Integer, Float, Character, and Boolean come under the
Primitive Data Structures.
4. These data types are also called Simple data types, as they contain characters that
can't be divided further
1. Non-Primitive Data Structures are those data structures derived from Primitive Data
Structures.
2. These data structures can't be manipulated or operated directly by machine-level
instructions.
3. The focus of these data structures is on forming a set of data elements that is
either homogeneous (same data type) or heterogeneous (different data types).
4. Based on the structure and arrangement of data, we can divide these data structures
into two sub-categories -
a. Linear Data Structures
b. Non-Linear Data Structures
Primitive data structure is a kind of data Non-primitive data structure is a type of data
structure that stores the data of only one structure that can store the data of more than one
type. type.
Examples of primitive data structure are Examples of non-primitive data structure are
integer, character, float. Array, Linked list, stack.
Primitive data structure will contain some Non-primitive data structure can consist of a
value, i.e., it cannot be NULL. NULL value.
The size depends on the type of the data In case of non-primitive data structure, size is not
structure. fixed.
Primitive data structure can be used to call Non-primitive data structure cannot be used to
the methods. call the methods.
Based on memory allocation, the Linear Data Structures are further classified into two types:
1. Static Data Structures: The data structures having a fixed size are known as Static
Data Structures. The memory for these data structures is allocated at the compiler
time, and their size cannot be changed by the user after being compiled; however, the
data stored in them can be altered.
The Array is the best example of the Static Data Structure as they have a fixed size,
and its data can be modified later.
2. Dynamic Data Structures: The data structures having a dynamic size are known as
Dynamic Data Structures. The memory of these data structures is allocated at the run
time, and their size varies during the run time of the code. Moreover, the user can
change the size as well as the data elements stored in these data structures at the run
time of the code.
Linked Lists, Stacks, and Queues are common examples of dynamic data structures
1. Arrays
An Array is a data structure used to collect multiple data elements of the same data type into one
variable. Instead of storing multiple values of the same data types in separate variable names, we
could store all of them together into one variable.
Thus, the key feature of the arrays to understand is that the data is stored in contiguous
memory locations, making it possible for the users to traverse through the data elements of
the array using their respective indexes.
a. One-Dimensional Array: An Array with only one row of data elements is known as
a One-Dimensional Array. It is stored in ascending storage location.
b. Two-Dimensional Array: An Array consisting of multiple rows and columns of data
elements is called a Two-Dimensional Array. It is also known as a Matrix.
c. Multidimensional Array: We can define Multidimensional Array as an Array of
Arrays. Multidimensional Arrays are not bounded to two indices or two dimensions as
they can include as many indices are per the need.
a. We can store a list of data elements belonging to the same data type.
b. Array acts as an auxiliary storage for other data structures.
c. The array also helps store data elements of a binary tree of the fixed count.
d. Array also acts as a storage of matrices.
2. Linked Lists
A Linked List is another example of a linear data structure used to store a collection
of data elements dynamically. Data elements in this data structure are represented by
the Nodes, connected using links or pointers. Each node contains two fields, the
information field consists of the actual data, and the pointer field consists of the
address of the subsequent nodes in the list. The pointer of the last node of the linked
list consists of a null pointer, as it points to nothing. Unlike the Arrays, the user can
dynamically adjust the size of a Linked List as per the requirements.
a. Singly Linked List: A Singly Linked List is the most common type of Linked List.
Each node has data and a pointer field containing an address to the next node.
b. Doubly Linked List: A Doubly Linked List consists of an information field and two
pointer fields. The information field contains the data. The first pointer field contains
an address of the previous node, whereas another pointer field contains a reference to
the next node. Thus, we can go in both directions (backward as well as forward).
c. Circular Linked List: The Circular Linked List is similar to the Singly Linked List.
The only key difference is that the last node contains the address of the first node,
forming a circular loop in the Circular Linked List.
a. The Linked Lists help us implement stacks, queues, binary trees, and graphs of
predefined size.
b. We can also implement Operating System's function for dynamic memory
management.
c. Linked Lists also allow polynomial implementation for mathematical operations.
d. We can use Circular Linked List to implement Operating Systems or application
functions that Round Robin execution of tasks.
e. Circular Linked List is also helpful in a Slide Show where a user requires to go back
to the first slide after the last slide is presented.
f. Doubly Linked List is utilized to implement forward and backward buttons in a
browser to move forward and backward in the opened pages of a website.
3. Stacks
A Stack is a Linear Data Structure that follows the LIFO (Last In, First Out) principle that allows
operations like insertion and deletion from one end of the Stack, i.e., Top. Stacks can be implemented
with the help of contiguous memory, an Array, and non-contiguous memory, a Linked List. Real-life
examples of Stacks are piles of books, a deck of cards, piles of money, and many more.
a. Push: Operation to insert a new element in the Stack is termed as Push Operation.
b. Pop: Operation to remove or delete elements from the Stack is termed as Pop
Operation.
4. Queues
A Queue is a linear data structure similar to a Stack with some limitations on the insertion
and deletion of the elements. The insertion of an element in a Queue is done at one end, and
the removal is done at another or opposite end. Thus, we can conclude that the Queue data
structure follows FIFO (First In, First Out) principle to manipulate the data elements.
Implementation of Queues can be done using Arrays, Linked Lists, or Stacks. Some real-life
examples of Queues are a line at the ticket counter, an escalator, a car wash, and many more.
a. Enqueue: The insertion or Addition of some data elements to the Queue is called
Enqueue. The element insertion is always done with the help of the rear pointer.
b. Dequeue: Deleting or removing data elements from the Queue is termed Dequeue.
The deletion of the element is always done with the help of the front pointer.
1. Trees
A Tree is a Non-Linear Data Structure and a hierarchy containing a collection of nodes such
that each node of the tree stores a value and a list of references to other nodes (the
"children").
The Tree data structure is a specialized method to arrange and collect data in the computer to
be utilized more effectively. It contains a central node, structural nodes, and sub-nodes
connected via edges. We can also say that the tree data structure consists of roots, branches,
and leaves connected.
Trees can be classified into different types:
a. Binary Tree: A Tree data structure where each parent node can have at most two children is
termed a Binary Tree.
b. Binary Search Tree: A Binary Search Tree is a Tree data structure where we can easily
maintain a sorted list of numbers.
c. AVL Tree: An AVL Tree is a self-balancing Binary Search Tree where each node maintains
extra information known as a Balance Factor whose value is either -1, 0, or +1.
d. B-Tree: A B-Tree is a special type of self-balancing Binary Search Tree where each node
consists of multiple keys and can have more than two children.
a. Trees implement hierarchical structures in computer systems like directories and file systems.
b. Trees are also used to implement the navigation structure of a website.
c. We can generate code like Huffman's code using Trees.
d. Trees are also helpful in decision-making in Gaming applications.
e. Trees are responsible for implementing priority queues for priority-based OS scheduling
functions.
f. Trees are also responsible for parsing expressions and statements in the compilers of different
programming languages.
g. We can use Trees to store data keys for indexing for Database Management System (DBMS).
h. Spanning Trees allows us to route decisions in Computer and Communications Networks.
i. Trees are also used in the path-finding algorithm implemented in Artificial Intelligence (AI),
Robotics, and Video Games Applications.
2. Graphs
G = (V,E)
The above figure represents a Graph having seven vertices A, B, C, D, E, F, G, and ten edges
[A, B], [A, C], [B, C], [B, D], [B, E], [C, D], [D, E], [D, F], [E, F], and [E, G].
Depending upon the position of the vertices and edges, the Graphs can be classified into
different types:
a. Null Graph: A Graph with an empty set of edges is termed a Null Graph.
b. Trivial Graph: A Graph having only one vertex is termed a Trivial Graph.
c. Simple Graph: A Graph with neither self-loops nor multiple edges is known as a Simple
Graph.
d. Multi Graph: A Graph is said to be Multi if it consists of multiple edges but no self-loops.
e. Pseudo Graph: A Graph with self-loops and multiple edges is termed a Pseudo Graph.
f. Non-Directed Graph: A Graph consisting of non-directed edges is known as a Non-Directed
Graph.
g. Directed Graph: A Graph consisting of the directed edges between the vertices is known as a
Directed Graph.
h. Connected Graph: A Graph with at least a single path between every pair of vertices is
termed a Connected Graph.
i. Disconnected Graph: A Graph where there does not exist any path between at least one pair
of vertices is termed a Disconnected Graph.
j. Regular Graph: A Graph where all vertices have the same degree is termed a Regular
Graph.
k. Complete Graph: A Graph in which all vertices have an edge between every pair of vertices
is known as a Complete Graph.
l. Cycle Graph: A Graph is said to be a Cycle if it has at least three vertices and edges that
form a cycle.
m. Cyclic Graph: A Graph is said to be Cyclic if and only if at least one cycle exists.
n. Acyclic Graph: A Graph having zero cycles is termed an Acyclic Graph.
o. Finite Graph: A Graph with a finite number of vertices and edges is known as a Finite
Graph.
p. Infinite Graph: A Graph with an infinite number of vertices and edges is known as an
Infinite Graph.
q. Bipartite Graph: A Graph where the vertices can be divided into independent sets A and B,
and all the vertices of set A should only be connected to the vertices present in set B with
some edges is termed a Bipartite Graph.
r. Planar Graph: A Graph is said to be a Planar if we can draw it in a single plane with two
edges intersecting each other.
s. Euler Graph: A Graph is said to be Euler if and only if all the vertices are even degrees.
t. Hamiltonian Graph: A Connected Graph consisting of a Hamiltonian circuit is known as a
Hamiltonian Graph.
Some Applications of Graphs:
a. Graphs help us represent routes and networks in transportation, travel, and communication
applications.
b. Graphs are used to display routes in GPS.
c. Graphs also help us represent the interconnections in social networks and other network-
based applications.
d. Graphs are utilized in mapping applications.
e. Graphs are responsible for the representation of user preference in e-commerce applications.
f. Graphs are also used in Utility networks in order to identify the problems posed to local or
municipal corporations.
g. Graphs also help to manage the utilization and availability of resources in an organization.
h. Graphs are also used to make document link maps of the websites in order to display the
connectivity between the pages through hyperlinks.
i. Graphs are also used in robotic motions and neural networks.
1. Traversal: Traversing a data structure means accessing each data element exactly once so it
can be administered. For example, traversing is required while printing the names of all the
employees in a department.
2. Search: Search is another data structure operation which means to find the location of one or
more data elements that meet certain constraints. Such a data element may or may not be
present in the given set of data elements. For example, we can use the search operation to find
the names of all the employees who have the experience of more than 5 years.
3. Insertion: Insertion means inserting or adding new data elements to the collection. For
example, we can use the insertion operation to add the details of a new employee the
company has recently hired.
4. Deletion: Deletion means to remove or delete a specific data element from the given list of
data elements. For example, we can use the deleting operation to delete the name of an
employee who has left the job.
5. Sorting: Sorting means to arrange the data elements in either Ascending or Descending order
depending on the type of application. For example, we can use the sorting operation to
arrange the names of employees in a department in alphabetical order or estimate the top three
performers of the month by arranging the performance of the employees in descending order
and extracting the details of the top three.
6. Merge: Merge means to combine data elements of two sorted lists in order to form a single
list of sorted data elements.
Basic In this structure, the elements In this structure, the elements are
are arranged sequentially or arranged hierarchically or non-linear
linearly and attached to one manner.
another.
Types Arrays, linked list, stack, Trees and graphs are the types of a non-
queue are the types of a linear data structure.
linear data structure.
Arrangement Each data item is attached to Each item is attached to many other
the previous and next items. items.
Levels This data structure does not In this, the data elements are arranged in
contain any hierarchy, and all multiple levels.
the data elements are
organized in a single level.
Time complexity The time complexity of The time complexity of non-linear data
linear data structure increases structure often remains same with the
with the increase in the input increase in the input size.
size.
Applications Linear data structures are Non-linear data structures are used
mainly used for developing in image processing and Artificial
the software. Intelligence.
What is ADT?
Abstract Data type (ADT) is a type (or class) for objects whose behavior is defined
by a set of values and a set of operations. The definition of ADT only mentions what
operations are to be performed but not how these operations will be implemented. It
does not specify how data will be organized in memory and what algorithms will be
used for implementing the operations. It is called “abstract” because it gives an
implementation-independent view.
The process of providing only the essentials and hiding the details is known as
abstraction.
Data structures play a crucial role in various real-world applications, enabling efficient
storage, retrieval, and manipulation of data. Here are some examples that demonstrate the
practical applications of data structures:
1. Databases: Databases utilize data structures such as B-trees, hash tables, and indexes to store
and organize large volumes of data efficiently. For example, in a relational database
management system (RDBMS), B-trees are commonly used for indexing to facilitate fast
searches and retrievals of records based on keys.
2. File Systems: File systems rely on data structures like linked lists, trees, and hash maps to
organize and manage files and directories on storage devices. For instance, in the UNIX file
system (UFS), an inode structure is used to represent files and directories, while directories
are typically organized as tree structures for efficient traversal.
3. Compiler Design: Compilers use various data structures such as parse trees, symbol tables,
and stacks to analyze, process, and optimize source code. For example, parse trees, often
represented as abstract syntax trees (ASTs), are used to represent the hierarchical structure of
code, facilitating semantic analysis and code generation phases.
4. Graph Algorithms: Graph algorithms leverage data structures like adjacency matrices,
adjacency lists, and priority queues to model and solve real-world problems involving
networks and relationships. For instance, Dijkstra's algorithm uses priority queues to find the
shortest path between nodes in a weighted graph, applicable in navigation systems and
network routing protocols.
5. Operating Systems: Operating systems utilize data structures such as queues, stacks, and
page tables to manage system resources efficiently. For example, scheduling algorithms in
operating systems use queues to prioritize and manage tasks, while page tables are used to
map virtual memory addresses
Linked list
Linked list is a linear data structure that includes a series of connected nodes. Linked list can
be defined as the nodes that are randomly stored in the memory. A node in the linked list
contains two parts, i.e., first is the data part and second is the address part. The last node of
the list contains a pointer to the null. After array, linked list is the second most used data
structure. In a linked list, every link contains a connection to another link.
Suppose we have three nodes, and the address of these nodes are 100, 200 and 300,
respectively. The representation of these nodes in a doubly-linked list is shown below:
o Dynamic data structure - The size of the linked list may vary according to the
requirements. Linked list does not have a fixed size.
o Insertion and deletion - Unlike arrays, insertion, and deletion in linked list is easier.
Array elements are stored in the consecutive location, whereas the elements in the
linked list are stored at a random location. To insert or delete an element in an array,
we have to shift the elements for creating the space. Whereas, in linked list, instead of
shifting, we just have to update the address of the pointer of the node.
o Memory efficient - The size of a linked list can grow or shrink according to the
requirements, so memory consumption in linked list is efficient.
o Implementation - We can implement both stacks and queues using linked list.
o Memory usage - In linked list, node occupies more memory than array. Each node of
the linked list occupies two types of variables, i.e., one is a simple variable, and
another one is the pointer variable.
o Traversal - Traversal is not easy in the linked list. If we have to access an element in
the linked list, we cannot access it randomly, while in case of array we can randomly
access it by index. For example, if we want to access the 3rd node, then we need to
traverse all the nodes before it. So, the time required to access a particular node is
large.
o Reverse traversing - Backtracking or reverse traversing is difficult in a linked list. In
a doubly-linked list, it is easier but requires more memory to store the back pointer.
o With the help of a linked list, the polynomials can be represented as well as we can
perform the operations on the polynomial.
o A linked list can be used to represent the sparse matrix.
o The various operations like student's details, employee's details, or product details can
be implemented using the linked list as the linked list uses the structure data type that
can hold different data types.
o Using linked list, we can implement stack, queue, tree, and other various data
structures.
o The graph is a collection of edges and vertices, and the graph can be represented as an
adjacency matrix and adjacency list. If we want to represent the graph as an adjacency
matrix, then it can be implemented as an array. If we want to represent the graph as an
adjacency list, then it can be implemented as a linked list.
o A linked list can be used to implement dynamic memory allocation. The dynamic
memory allocation is the memory allocation done at the run-time.
Insertion
SN Operation Description
1 Insertion at It involves inserting any element at the front of the list. We just need to a
beginning few link adjustments to make the new node as the head of the list.
2 Insertion at end It involves insertion at the last of the linked list. The new node can be
of the list inserted as the only node in the list or it can be inserted as the last one.
Different logics are implemented in each scenario.
3 Insertion after It involves insertion after the specified node of the linked list. We need to
specified node skip the desired number of nodes in order to reach the node after which the
new node will be inserted. .
SN Operation Description
1 Deletion at It involves deletion of a node from the beginning of the list. This is the
beginning simplest operation among all. It just need a few adjustments in the node
pointers.
2 Deletion at the It involves deleting the last node of the list. The list can either be empty or
end of the list full. Different logic is implemented for the different scenarios.
3 Deletion after It involves deleting the node after the specified node in the list. we need to
specified node skip the desired number of nodes to reach the node after which the node will
be deleted. This requires traversing through the list.
4 Traversing In traversing, we simply visit each node of the list at least once in order to
perform some specific operation on it, for example, printing data part of
each node present in the list.
5 Searching In searching, we match each element of the list with the given element. If the
element is found on any of the location then location of that element is
returned otherwise null is returned. .
Array elements store in a contiguous Linked list elements can be stored anywhere in
memory location. the memory or randomly stored.
Array works with a static memory. Here The Linked list works with dynamic memory.
static memory means that the memory size is Here, dynamic memory means that the
fixed and cannot be changed at the run time. memory size can be changed at the run time
according to our requirements.
Array elements are independent of each Linked list elements are dependent on each
other. other. As each node contains the address of the
next node so to access the next node, we need
to access its previous node.
Array takes more time while performing any Linked list takes less time while performing
operation like insertion, deletion, etc. any operation like insertion, deletion, etc.
Accessing any element in an array is faster as Accessing an element in a linked list is slower
the element in an array can be directly as it starts traversing from the first element of
accessed through the index. the linked list.
In the case of an array, memory is allocated In the case of a linked list, memory is allocated
at compile-time. at run time.
Memory utilization is inefficient in the array. Memory utilization is efficient in the case of a
For example, if the size of the array is 6, and linked list as the memory can be allocated or
array consists of 3 elements only then the deallocated at the run time according to our
rest of the space will be unused. requirement.
Node Creation
struct node
{
int data;
struct node *next;
};
struct node *head, *ptr;
ptr = (struct node *)malloc(sizeof(struct node *));
o Allocate the space for the new node and store data into the data part of the node. This
will be done by the following statements.
o Make the link part of the new node pointing to the existing first node of the list. This
will be done by using the following statement.
ptr->next = head;
o At the last, we need to make the new node as the first node of the list this will be done
by using the following statement.
head = ptr;
Insertion in singly linked list at the end
o The condition Head = NULL would fail, since Head is not null. Now, we need to declare a
temporary pointer temp in order to traverse through the list. temp is made to point the first
node of the list.
Temp = head
o Then, traverse through the entire linked list using the statements:
temp = head;
while (temp -> next != NULL)
{
temp = temp -> next;
}
temp->next = ptr;
ptr->next = NULL;
Insertion in singly linked list after specified Node
o In order to insert an element after the specified number of nodes into the linked list,
we need to skip the desired number of elements in the list to move the pointer at the
position after which the node will be inserted. This will be done by using the
following statements.
emp=head;
for(i=0;i<loc;i++)
{
temp = temp->next;
if(temp == NULL)
{
return;
}
o Allocate the space for the new node and add the item to the data part of it. This will be
done by using the following statements.
now, we just need to make the next part of the temp, point to the new node ptr. This will
insert the new node ptr, at the specified position.
ptr = head;
head = ptr->next;
Now, free the pointer ptr which was pointing to the head node of the list. This will be done by
using the following statement.
free(ptr)
For this purpose, just declare a temporary pointer temp and assign it to head of the list. We
also need to keep track of the second last node of the list. For this purpose, two pointers ptr
and ptr1 will be used where ptr will point to the last node and ptr1 will point to the second
last node of the list
ptr = head;
while(ptr->next != NULL)
{
ptr1 = ptr;
ptr = ptr ->next;
}
Now, we just need to make the pointer ptr1 point to the NULL and the last node of the list
that is pointed by ptr will become free. It will be done by using the following statements.
ptr1->next = NULL;
free(ptr);
ptr=head;
for(i=0;i<loc;i++)
{
ptr1 = ptr;
ptr = ptr->next;
if(ptr == NULL)
{
printf("\nThere are less than %d elements in the list..",loc);
return;
}
}
Now, our task is almost done, we just need to make a few pointer adjustments. Make the next
of ptr1 (points to the specified node) point to the next of ptr (the node which is to be deleted).
ptr = head;
while (ptr!=NULL)
{
ptr = ptr -> next;
}
Searching in singly linked list
Searching is performed in order to find the location of a particular element in the list. Searching
any element in the list needs traversing through the list and make the comparison of every element
of the list with the specified element. If the element is matched with any of the list element then
the location of the element is returned from the function.
Algorithm
o Step 1: SET PTR = HEAD
o Step 2: Set I = 0
o STEP 3: IF PTR = NULL
WRITE "EMPTY LIST"
GOTO STEP 8
END OF IF
o STEP 4: REPEAT STEP 5 TO 7 UNTIL PTR != NULL
o STEP 5: if ptr → data = item
write i+1
End of IF
o STEP 6: I = I + 1
o STEP 7: PTR = PTR → NEXT
[END OF LOOP]
o STEP 8: EXIT
struct node
{
struct node *prev;
int data;
struct node *next;
}
The prev part of the first node and the next part of the last node will always contain null
indicating end in each direction.
In a singly linked list, we could traverse only in one direction, because each node contains
address of the next node and it doesn't have any record of its previous nodes. However,
doubly linked list overcome this limitation of singly linked list. Due to the fact that, each
node of the list contains the address of its previous node, we can find all the details about the
previous node as well by using the previous address stored inside the previous part of each
node.
In the following image, the first element of the list that is i.e. 13 stored at address 1. The head
pointer points to the starting address 1. Since this is the first element being added to the list
therefore the prev of the list contains null. The next node of the list resides at address 4
therefore the first node contains 4 in its next pointer.
We can traverse the list in this way until we find any node containing null or -1 in its next
part.
1. struct node
2. {
3. struct node *prev;
4. int data;
5. struct node *next;
6. };
7. struct node *head;
All the remaining operations regarding doubly linked list are described in the following table.
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 Adding the node into the linked list after the specified node.
specified 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.
o the condition head == NULL become false and the node will be inserted in
beginning. The next pointer of the node will point to the existing head pointer of the
node. The prev pointer of the existing head will point to the new node being inserted.
o This will be done by using the following statements.
ptr->next = head;
head→prev=ptr;
Since, the node being inserted is the first node of the list and therefore it must contain NULL
in its prev pointer. Hence assign null to its previous part and make the head point to this node.
ptr→prev =NULL
head = ptr
Insertion in doubly linked list at the end
In order to insert a node in doubly linked list at the end, we must make sure whether the list is
empty or it contains any element. Use the following steps in order to insert the node in doubly
linked list at the end.
o the condition head == NULL become false. The new node will be inserted as the last
node of the list. For this purpose, we have to traverse the whole list in order to reach
the last node of the list. Initialize the pointer temp to head and traverse the list by
using this pointer.
Temp = head;
while (temp != NULL)
{
temp = temp → next;
}
the pointer temp point to the last node at the end of this while loop. Now, we just need to
make a few pointer adjustments to insert the new node ptr to the list. First, make the next
pointer of temp point to the new node being inserted i.e. ptr.
temp→next =ptr;
make the previous pointer of the node ptr point to the existing last node of the list i.e. temp.
make the next pointer of the node ptr point to the null as it will be the new last node of the
list.
ptr → next = NULL
o Allocate the memory for the new node. Use the following statements for this.
o Traverse the list by using the pointer temp to skip the required number of nodes in
order to reach the specified node.
temp=head;
for(i=0;i<loc;i++)
{
temp = temp->next;
if(temp == NULL) // the temp will be //null if the list doesn't last long //up to mention
ed location
{
return;
}
}
o The temp would point to the specified node at the end of the for loop. The new node
needs to be inserted after this node therefore we need to make a fer pointer
adjustments here. Make the next pointer of ptr point to the next node of temp.
make the next pointer of temp point to the new node ptr.
make the previous pointer of the next node of temp point to the new node.
Deletion at beginning
Deletion in doubly linked list at the beginning is the simplest operation. We just need to copy
the head pointer to pointer ptr and shift the head pointer to its next.
Ptr = head;
head = head → next;
now make the prev of this new head node point to NULL. This will be done by using the
following statements.
free(ptr)
In order to delete the last node of the list, we need to follow the following steps.
o If the list is already empty then the condition head == NULL will become true and therefore
the operation can not be carried on.
o If there is only one node in the list then the condition head → next == NULL become true. In
this case, we just need to assign the head of the list to NULL and free head in order to
completely delete the list.
o Otherwise, just traverse the list to reach the last node of the list. This will be done by using
the following statements.
ptr = head;
if(ptr->next != NULL)
{
ptr = ptr -> next;
}
o The ptr would point to the last node of the ist at the end of the for loop. Just make the next
pointer of the previous node of ptr to NULL.
free(ptr)
o Check if this is the last node of the list. If it is so then we can't perform deletion.
o Check if the node which is to be deleted, is the last node of the list, if it so then we
have to make the next pointer of this node point to null so that it can be the new last
node of the list.
o Otherwise, make the pointer ptr point to the node which is to be deleted. Make the
next of temp point to the next of ptr. Make the previous of next node of ptr point to
temp. free the ptr.
ptr = head
o declare a local variable I and assign it to 0.
i=0
o Traverse the list until the pointer ptr becomes null. Keep shifting pointer to its next and
increasing i by +1.
o Compare each element of the list with the item which is to be searched.
o If the item matched with any node value then the location of that value I will be returned from
the function else NULL is returned.
Algorithm
o Step 1: IF HEAD == NULL
WRITE "UNDERFLOW"
GOTO STEP 8
[END OF IF]
return i
[END OF IF]
o Step 6: i = i + 1
o Step 7: PTR = PTR → next
o Step 8: Exit
1. Ptr = head
then, traverse through the list by using while loop. Keep shifting value of pointer
variable ptr until we find the last node. The last node contains null in its next part.
while(ptr != NULL)
{
printf("%d\n",ptr->data);
ptr=ptr->next;
}
Although, traversing means visiting each node of the list once to perform some specific
operation. Here, we are printing the data associated with each node of the list.
Definition A single linked list is a list A doubly linked list is also a collection of
of nodes in which node has nodes in which node has three fields, the
two parts, the first part is first field is the pointer containing the
the data part, and the next address of the previous node, the second is
part is the pointer pointing the data field, and the third is the pointer
to the next node in the containing the address of the next node.
sequence of nodes.
Access The singly linked list can be The doubly linked list can be accessed in
traversed only in the both directions.
forward direction.
List pointer It requires only one list It requires two list pointer
pointer variable, i.e., the variables, head and last. The head pointer
head pointer pointing to the points to the first node, and the last pointer
first node. points to the last node of the list.
Complexity In a singly linked list, the In a doubly-linked list, the time complexity
time complexity for for inserting and deleting an element
inserting and deleting an is O(1).
element from the list
is O(n).
Polynomial Manipulation
Polynomial manipulations are one of the most important applications of linked lists.
Polynomials are an important part of mathematics not inherently supported as a data type by
most languages. A polynomial is a collection of different terms, each comprising coefficients,
and exponents. It can be represented using a linked list. This representation makes
polynomial manipulation efficient.
While representing a polynomial using a linked list, each polynomial term represents a node
in the linked list. To get better efficiency in processing, we assume that the term of every
polynomial is stored within the linked list in the order of decreasing exponents. Also, no two
terms have the same exponent, and no term has a zero coefficient and without coefficients.
The coefficient takes a value of 1.
o The first part contains the value of the coefficient of the term.
o The second part contains the value of the exponent.
o The third part, LINK points to the next term (next node).
The structure of a node of a linked list that represents a polynomial is shown below:
Consider a polynomial P(x) = 7x2 + 15x3 - 2 x2 + 9. Here 7, 15, -2, and 9 are the coefficients,
and 4,3,2,0 are the exponents of the terms in the polynomial. On representing this polynomial
using a linked list, we have
Observe that the number of nodes equals the number of terms in the polynomial. So we have
4 nodes. Moreover, the terms are stored to decrease exponents in the linked list. Such
representation of polynomial using linked lists makes the operations like subtraction,
addition, multiplication, etc., on polynomial very easy.
Addition of Polynomials:
To add two polynomials, we traverse the list P and Q. We take corresponding terms of the list
P and Q and compare their exponents. If the two exponents are equal, the coefficients are
added to create a new coefficient. If the new coefficient is equal to 0, then the term is
dropped, and if it is not zero, it is inserted at the end of the new linked list containing the
resulting polynomial. If one of the exponents is larger than the other, the corresponding term
is immediately placed into the new linked list, and the term with the smaller exponent is held
to be compared with the next term from the other list. If one list ends before the other, the rest
of the terms of the longer list is inserted at the end of the new linked list containing the
resulting polynomial.
Let us consider an example an example to show how the addition of two polynomials is
performed,
Q (x) = 5x3 + 4 x2 - 5
These polynomials are represented using a linked list in order of decreasing exponents as
follows:
To generate a new linked list for the resulting polynomials that is formed on the addition of
given polynomials P(x) and Q(x), we perform the following steps,
1. Traverse the two lists P and Q and examine all the nodes.
2. We compare the exponents of the corresponding terms of two polynomials. The first
term of polynomials P and Q contain exponents 4 and 3, respectively. Since the
exponent of the first term of the polynomial P is greater than the other polynomial Q,
the term having a larger exponent is inserted into the new list. The new list initially
looks as shown below:
3. We then compare the exponent of the next term of the list P with the exponents of the
present term of list Q. Since the two exponents are equal, so their coefficients are
added and appended to the new list as follows:
4. Then we move to the next term of P and Q lists and compare their exponents. Since
exponents of both these terms are equal and after addition of their coefficients, we get
0, so the term is dropped, and no node is appended to the new list after this,
5. Moving to the next term of the two lists, P and Q, we find that the corresponding
terms have the same exponents equal to 0. We add their coefficients and append them
to the new list for the resulting polynomial as shown below: