0% found this document useful (0 votes)
42 views58 pages

UNIT1

Uploaded by

mohamedaufin64
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)
42 views58 pages

UNIT1

Uploaded by

mohamedaufin64
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/ 58

SCSB1201 - DATA STRUCTURES

UNIT 1: INTRODUCTION

Introduction to Data Structures - Need - Classification-Arrays - Singly linked list -


Representation of a linked list in memory - Operations on a singly linked list - Merging two
singly linked lists into one list - Reversing a singly linked list -Advantages and
disadvantages of singly linked list - Circular linked list - Doubly linked list

1.1 INTRODUCTION TO DATA STRUCTURES


Algorithms + Data Structures = Programs!
 This is the title of a book by Prof. Nicklaus Wirth, the inventor of the Pascal
programming language. The title tells it all. Well, almost all. The algorithm
and the accompanying data structures are the essence of a program. A module
is a collection of programs and subprograms.
 A module delivers functionality. A software system is a collection of modules
that are interconnected or interdependent. A Software accomplishes a goal. A
software game is a system. Each level in a game is module. Each level may
house many sub modules. Audio, graphics, movement etc. are few examples of
sub modules. Each module or sub module employs programs to carry out a
particular task.
 Data structures and algorithms that act on them added with the syntax and
semantics of a programming language make up a working program. Thus, Data
Structures and Algorithms (DSA) are the most essential and basic components
for building a complex software system.
 As an engineer you will be designing, building, testing, validating and
deploying the software. You will have to make decisions about the choice of
platform or programming language to be used. You will also decide the design
methodology. At the bottom of all, you will make decisions about the data
structures and algorithms to be used. To exercise choice, we need to have deep
knowledge about algorithms and data structures. The next sections dealt about
the basic terms and concepts of DSA.
Data
In the modern context, data stands for both singular and plural. Data means a value
or set of values. Data can be defined as an elementary value or the collection of
values, for example, student’s name and its id are the data about the student.Thus
character, string of characters, real number, integers, collection of numbers, the list of
colors is all examples of data.
Structure
A building is a structure. A bridge is structure. In general a structure is made up
of components. It has a form or shape. It is made up of parts. A structure is an
arrangement of and relations between parts or elements.

Data Structures
 A data structure is an arrangement of data elements. Data Structure can be
defined as the group of data elements which provides an efficient way of
storing and organizing data in the computer so that it can be used efficiently.
Some examples of Data Structures are arrays, Linked List, Stack, Queue, etc.
Data Structures are widely used in almost every aspect of Computer Science
i.e. Operating System, Compiler Design, Artificial Intelligence, Graphics and
many more.
 Data Structures are the main part of many computer science algorithms
as they enable the programmers to handle the data in an efficient way. It plays
a vital role in enhancing the performance of a software or a program as the
main function of the software is to store and retrieve the user’s data as
fast as possible
 Data structures are the building blocks of any program or the software.
Choosing the appropriate data structure for a program is the most crucial
task for a programmer.

1.2 Needs
As applications are getting complex and amount of data is increasing day by day,
the following issues might be araised:
1. Processor speed: To handle very large amount of data, high speed processing

is required, but as the data is growing day by day to the billions of files per
entity, processor may fail to deal with that much amount of data.
2. Data Search: Consider an inventory size of 106 items in a store; if our
application needs to search for a particular item, it needs to traverse 106 items
every time, results in slowing down the search process.
3. Multiple requests: If thousands of users are searching the data
simultaneously in a web server, it fails to process the requests.
In order to solve the above problems, data structures are used. Data is organized to
form a data structure in such a way that all items are not required to be searched and
required data can be searched instantly.
 Data structures are important as they provide the mechanism for defining what
we can do with our data. Also, data structures can have certain performance
characteristics, for example retrieving the value of an array at a specified index
will always be the same no matter how small or large the index is.
 Data structure is a particular way of storing and organizing information in a
computer so that it can be retrieved and used most productively. Using data
structures, from simple arrays to more complex trees, hash tables, or custom data
structures, allows your code to both be more organized and extensible.
 Using an array, which can either be created to hold the required number of
elements or extended to hold more after its first created keeps you from having
to rewrite your code each time the number of data items changes.
 Using an appropriate data structure allows you to design algorithms based on the
relationships between the data elements rather than some fixed ordering, giving
you more flexibility. Different kinds of data structures are meant for different
kinds of applications, and some are highly specialized to specific tasks.

1.2.1 Data structures are important for the following reasons

1. Data structures are used in almost every program or software system.


2. Specific data structures are essential ingredients of many efficient algorithms,

and make possible the management of huge amounts of data, such as large
integrated collection of databases.
3. Some programming languages emphasize data structures, rather than algorithms,

as the key organizing factor in software design.

1.2.2.Advantages of Data Structures


1. Efficiency: Efficiency of a program depends upon the choice of data
structures. For example: suppose, we have some data and we need to
perform the search for a particular record. In that case, if we organize
our data in an array, we will have to search sequentially element by
element. Hence, using array may not be very efficient here. There are
better data structures which can make the search process efficient like
ordered array, binary search tree or hash tables.
2. Reusability: Data structures are reusable, i.e. once we have implemented
a particular data structure, we can use it at any other place.
Implementation of data structures can be compiled into libraries which
can be used by different clients.
3. Abstraction: Data structure is specified by the ADT which provides a
level of abstraction. The client program uses the data structure through
interface only, without getting into the implementation details.

1.3 Classification of Data Structure

1.3.1.Primitive Data Structures


Simple data structure can be constructed with the help of primitive data structure.
A primitive data structure used to represent the standard data types of any one of the
computer languages. Variables, pointers, structures, unions, etc. are examples of
primitive data structures.

1.3.2 Non Primitive Data Structures


Non Primitive Data Structures are classified as linear or non-linear. Arrays, linked
lists, queues and stacks are linear data structures. Trees and Graphs are non-linear
data structures. Except arrays, all other data structures have many variations. Non
Primitive data structure can be constructed with the help of any one of the primitive
data structure and it is having a specific functionality. It can be designed by user.

1.1 Classification of Data Structure

1.3.3Linear Data Structures

A data structure is called linear if all of its elements are arranged in the linear
order. In linear data structures, the elements are stored in non-hierarchical way
where each element has the successors and predecessors except the first and last
element. Collection of nodes which are logically adjacent in which logical adjacency
is maintained by pointers. Linear data structures can be constructed as a continuous
arrangement of data elements in the memory. It can be constructed by using array
data type. In the linear Data Structures the relationship of adjacency is maintained
between the Data elements. In linear data structure the elements are stored in
sequential order.
Types of Linear Data Structures are given below:

Arrays: An array is a collection of similar type of data items stored in consecutive


memory location and is referred by common name; each data item is called an element
of the array. The data type of the element may be any valid data type like char,
int, float or double.

The elements of array share the same variable name but each one carries a different
index number known as subscript. The array can be one dimensional, two
dimensional or multidimensional.The individual elements of the array age are:

age[0], age[1], age[2], age[3],. age[98], age[99].

Linked List: Linked list is a linear data structure which is used to maintain a list in
the memory. It can be seen as the collection of nodes stored at non-contiguous memory
locations. Each node of the list contains a pointer to its adjacent node. It is a
collection of data of same data type but the data items need not be stored in
consecutive memory locations.

Stack: Stack is a linear list in which insertion and deletions are allowed only at one
end, called top. It is a Last-In-First-Out linear data structure.

A stack is an abstract data type (ADT), can be implemented in most of the


programming languages. It is named as stack because it behaves like a real-world
stack, for example, piles of plates or deck of cards etc.

Queue: Queue is a linear list in which elements can be inserted only at one end called
rear and deleted only at the other end called front. It is a First-In-First-Out Linear
data structure.

It is an abstract data structure, similar to stack. Queue is opened at both end


therefore it follows First-In-First-Out (FIFO) methodology for storing the data items.

Operations applied on Linear Data Structure

The following list of operations applied on linear data structures


1. Add an element
2. Delete an element
3. Traverse
4. Sort the list of elements
5. Search for a data element

By applying one or more functionalities, create different types of data structures.


For example Stack, Queue, Tables, List, and Linked Lists.

1.3.4 Non-linear Data Structures


This data structure does not form a sequence i.e. each item or element is connected
with two or more other items in a non-linear arrangement. The data elements are not
arranged in sequential structure. Non-linear data structure can be constructed as a
collection of randomly distributed set of data item joined together by using a special
pointer (tag). In non-linear Data structure the relationship of adjacency is not
maintained between the Data items.
Elements are stored based on the hierarchical relationship among the data. The
following are some of the Non-Linear data structure

Trees: Trees are multilevel data structures with a hierarchical relationship among
its elements known as nodes. The bottommost nodes in the hierarchy are called leaf
node while the topmost node is called root node. Each node contains pointers to point
adjacent nodes. Trees are used to represent data that has some hierarchical relationship
among the data elements.
Tree data structure is based on the parent-child relationship among the nodes.
Each node in the tree can have more than one child except the leaf nodes whereas
each node can have at most one parent except the root node. Trees can be classified
into many categories which will be discussed later in this tutorial.
Graphs: Graphs can be defined as the pictorial representation of the set of elements
(representesd by vertices) connected by the links known as edges. A graph is different
from tree in the sense that a graph can have cycle while the tree cannot have the one.
Graph is used to represent data that has relationship between pair of elements not
necessarily hierarchical in nature. For example electrical and communication
networks, airline routes, flow chart, graphs for planning projects.

Operations applied on non-linear data structures


The following list of operations applied on non-linear data structures.
1. Add elements

2. Delete elements

3. Display the elements

4. Sort the list of elements

5. Search for a data element


If the data contains a single value this can be organized using primitive data type.
If the data contains set of values they can be represented using non-primitive data
types.

1.4 Operations on Data Structures

The following are the operations performed on any data structure.They are
1. Insertion: Insertion can be defined as the process of adding the elements to the

data structure at any location. A new element is inserted into an existing data structure.
2. Deletion: The process of removing an element from the data structure is called

Deletion. We can delete an element from the data structure at any random
location.An existing element is deleted from a data structure.
3. Traversal: Every data structure contains the set of data elements. Traversing the data

structure means visiting each element of the data structure in order to perform some
specific operation like searching or sorting. Every element of a data structure is visited
exactly once and a process is applied.
4. Searching: The process of finding the location of an element within the data structure

is called Searching. There are two algorithms to perform searching, Linear Search and
Binary Search. A data structure is searched for locating a given element, if available.
The procedure returns the location if the element is available. Otherwise a Not
available message or equivalent is returned.
5. Sorting: The process of arranging the data structure in a specific order is known as

Sorting. There are many algorithms that can be used to perform sorting, for example,
insertion sort, selection sort, bubble sort, etc. The elements of a given data structure
are arranged in ascending or descending order.
6. Merging: When two lists List A and List B of size M and N respectively, of similar

type of elements, clubbed or joined to produce the third list, List C of size (M+N), then
this process is called merging. It is used to combine the data items of two sorted files
into single file in the sorted form.

Searching and sorting are not basic operations but complex procedures that can be
done using the basic operations 1, 2 and 3. But, these are very frequently used in
most applications. Any other complex application can be built in terms of these five
operations. All basic operations and procedures are described by a simple informal
notation called as algorithm.

Inserting It is used to add a new data item in the given collection of data items.
Eg: Suppose we have an array of size 20 used to store marks obtained by the students
in Computer Science subject. If we have already added
15 students’ marks according to an ascending order, then we can add another student
marks at appropriate place, by shifting the already stored element accordingly. Then
it is called Insertion operation.

Deleting – It is used to delete an existing data item from the given collection of data
items.
Eg: Suppose we have an array of size 20 used to store marks obtained by the students
in Computer Science subject. If we have already added
15 students’ marks according to an ascending order, then we can delete one student’s
marks from any place, by shifting the already stored elements accordingly. Then
it is called Deletion operation.
Traversing – It is used to access each data item exactly once so that itcan be processed.
Eg: Suppose we have an array of 20 students’ average makes, and if we need to
calculate the average of group, we visit (read) each individual average and accumulate
(sum) them. Then we will find the array is visited once and only once. Then it is
traversing of an array.

Searching – It is used to find out the location of the data item if it exists in the
given collection of data items.
Eg: Suppose we have an array of size 10 and assume elements stored are 1, 2, 3, 23,
34, 54, 56, 21, 32, 33 and assume we want to search the number 23. So here the
number ‘23’ is key element. The key is searched through the array starting from the
first element till end. When it is compared with the fourth element in it is present in
the list (array) of numbers. So search is successful. This type of searching is called as
Linear
Search because the last element. In order to apply linear search, the list may not be in
any particular order but when binary search is applied the list must be an ordered one.

Sorting – It is used to arrange the data items in some order i.e. in ascending or
descending order in case of numerical data and in dictionary order in case of alpha
numeric data.
Eg: Suppose we have an array of size 10 and assume elements stored are 1, 2, 3,
23, 34, 54, 56, 21, 32, 33. The elements of the array are not in proper order. If they
are arranged in ascending order the list (array) becomes1, 2, 3, 21, 23, 32, 34, 54,
56.

Merging – It is used to combine the data items of two sorted files into single file in
the sorted form.
Eg: Suppose we have a list of size 6, containing the elements 1, 2, 3, 4,
71, 87 and we have another list of size 5, containing the elements 9, 13, 21, 65, 67.
Here both the lists are in ascending order. We can produce the third list of size 11
that will also be in ascending order, containing the element 1, 2, 3, 4, 9, 13, 21, 65,
67, 71, 87. The third list is called the merged list of first and second lists. In order to
merge two lists into single list one needs to compare each element from both the lists
and one of them will go the merged list.

1.5 ARRAYS

Array Representation

The number of data items chunked together into a unit is known as data structure.
When the data structure consists simply a sequence of data items, the data structure of
this simple variety is referred as an array. An array is the most fundamental data
structure from which other data structures maybe built such as stack, queue, strings
etc. It is designed to hold number of objects (items) of same types. It is an efficient
data structure for storage and accessing of objects.

Definition: Array is a collection of homogenous (same data type) data elements that
are stored in contiguous memory locations.
Homogeneity and physical contiguity have a purpose. Since, each element
occupies the same memory space and all are continually placed the physical address
of each element can be calculated using a common formula. Let each element occupy
w word lengths. The first element’s starting address is the address A. The second
element’s starting address is A + w. In general, the ith elements starting address is A
+ (i-1) * w. The physical address of any element is computed by the same formula,
which means that it takes same amount of time. Thus the access is same for all
elements of an array. It’s random- a c c e s s memory (RAM).
Arrays are used for storing sequential data. For example:

✱ List of marks of a student

✱ Matrices

✱ Daily temperature over the last year


✱ List of students in a class

Array Syntax
Syntax to declare an array:

✱ dataType [ ] arrayName;

arrayName= new dataType[n]; //keyword new performs dynamic memory location


(or)

✱ dataType [ ] arrayName = new dataType[n];

Example:
int [ ] x; x=new int [10]; (or) int [] x=new int [10];
Array Initialization
The values of an array can be initialized as follows,

Example 1:
int [] j=new int [1]; j[0] =10;(or)int [] j= {25};

Example 2:
int [] myarray= {5, 10};

Characteristics of an Array
The following are the characteristics of an array data structure.
(i) Array stores elements of same data type.
(ii) The elements of an array are stored in subsequent memory locations.
(iii) The name of array represents the starting address of the elements.

(iv) When data objects are stored in array, individual objects are selected by an index.
(v) By default an array index starts from 0 and ends with (n-1). Index is also referred as
subscripts.
(vi) The size of the array is mentioned at the time of declaring array.

(vii) While declaring 2D array, number of columns should be specified whereas for
number of rows there is no such rule.
(viii) Size of array can’t be changed at run time.

Array Types
(i) One-Dimensional Array or Linear arrays
(ii) Multi-Dimensional Array

a. Two dimensional (2D) Arrays or Matrix Arrays


b. Three Dimensional Arrays
One-Dimensional Array
In one dimensional array each element is represented by a single subscript. The
elements are stored in consecutive memory locations. E.g. A [1], A [2], ......., A [N].

Multi-Dimensional Array
The array with more than one dimension is referred as multi-dimensional array.
All multi- dimensional arrays use a linear equation very similar to that of the one
dimensional array for computing the address of an element. The simplest form of the
multi-dimensional array is the two-dimensional array. It is useful for matrices, 3D
graphics etc.

Two dimensional (2-D) arrays or Matrix Arrays


In two dimensional arrays each element is represented by two subscripts. Thus a
two dimensional m x n array has m rows and n columns and contains m * n elements.
It is also called matrix array because in this case, the elements form a matrix. For
example A [4] [3] has 4 rows and 3 columns and 4*3 = 12 elements.

int [] [] A = new int [4] [3];

Three dimensional arrays:


In it each element is represented by three subscripts. Thus a three dimensional
m x n x l arraycontains m * n * l elements. For example A [2] [4] [3] has 2 * 4 * 3 =
24 elements.
Basic Operations in Arrays
The basic operations in the Arrays are insertion, deletion, searching, display, traverse,
and update. These operations are usually performed to either modify the data in the
array or to report the status of the array.

Following are the basic operations supported by an array.

1. Traverse − print all the array elements one by one.


2. Insertion − Adds an element at the given index.
3. Deletion − Deletes an element at the given index.
4. Search − Searches an element using the given index or by the value.
5. Update − Updates an element at the given index.
6. Display − Displays the contents of the array.

Data Type Default Value

bool false

char 0

int 0

float 0.0

double 0.0f

void

wchar_t 0
In C, when an array is initialized with size, then it assigns defaults values to its
elements in following order.

Array - Insertion Operation


In the insertion operation, we are adding one or more elements to the array. Based on
the requirement, a new element can be added at the beginning, end, or any given index
of array. This is done using input statements of the programming languages.

Algorithm
Following is an algorithm to insert elements into a Linear Array until we reach the end
of the array –

1. Start
2. Create an Array of a desired datatype and size.
3. Initialize a variable 'i' as 0.
4. Enter the element at ith index of the array.
5. Increment i by 1.
6. Repeat Steps 4 & 5 until the end of the array.
7. Stop
Example
Here, we see a practical implementation of insertion operation, where we add data at
the end of the array −

#include <stdio.h>
int main(){
int LA[3] = {}, i;
printf("Array Before Insertion:\n");
for(i = 0; i < 3; i++)
printf("LA[%d] = %d \n", i, LA[i]);
printf("Inserting Elements.. \n");
printf("The array elements after insertion :\n"); // prints array values
for(i = 0; i < 3; i++) {
LA[i] = i + 2;
printf("LA[%d] = %d \n", i, LA[i]);
}
return 0;
}

Output
Array Before Insertion:
LA[0] = 0
LA[1] = 0
LA[2] = 0
Inserting elements..
Array After Insertion:
LA[0] = 2
LA[1] = 3
LA[2] = 4
LA[3] = 5
LA[4] = 6

Array - Deletion Operation

In this array operation, we delete an element from the particular index of an


array. This deletion operation takes place as we assign the value in the consequent
index to the current index.

Algorithm

Consider LA is a linear array with N elements and K is a positive integer such that
K<=N. Following is the algorithm to delete an element available at the Kth position of
LA.

1. Start
2. Set J = K
3. Repeat steps 4 and 5 while J < N
4. Set LA[J] = LA[J + 1]
5. Set J = J+1
6. Set N = N-1
7. Stop

Example
Following are the implementations of this operation in C programming languages

#include <stdio.h>
void main(){
int LA[] = {1,3,5};
int n = 3;
int i;
printf("The original array elements are :\n");
for(i = 0; i<n; i++)
printf("LA[%d] = %d \n", i, LA[i]);
for(i = 1; i<n; i++) {
LA[i] = LA[i+1];
n = n - 1;
}
printf("The array elements after deletion :\n");
for(i = 0; i<n; i++)
printf("LA[%d] = %d \n", i, LA[i]);
}
Output
The original array elements are :
LA[0] = 1
LA[1] = 3
LA[2] = 5
The array elements after deletion :
LA[0] = 1
LA[1] = 5

Array - Search Operation

Searching an element in the array using a key; The key element sequentially compares
every value in the array to check if the key is present in the array or not.

Algorithm
Consider LA is a linear array with N elements and K is a positive integer such that
K<=N. Following is the algorithm to find an element with a value of ITEM using
sequential search.

1. Start
2. Set J = 0
3. Repeat steps 4 and 5 while J < N
4. IF LA[J] is equal ITEM THEN GOTO STEP 6
5. Set J = J +1
6. PRINT J, ITEM
7. Stop
Example
Following are the implementations of this operation in C programming languages –

#include <stdio.h>
void main(){
int LA[] = {1,3,5,7,8};
int item = 5, n = 5;
int i = 0, j = 0;
printf("The original array elements are :\n");
for(i = 0; i<n; i++) {
printf("LA[%d] = %d \n", i, LA[i]);
}
for(i = 0; i<n; i++) {
if( LA[i] == item ) {
printf("Found element %d at position %d\n", item, i+1);
}
}
}
Output
The original array elements are :
LA[0] = 1
LA[1] = 3
LA[2] = 5
LA[3] = 7
LA[4] = 8
Found element 5 at position 3

Array - Traversal Operation

This operation traverses through all the elements of an array. We use loop statements
to carry this out.

Algorithm
Following is the algorithm to traverse through all the elements present in a Linear
Array –

1 Start
2. Initialize an Array of certain size and datatype.
3. Initialize another variable ‘i’ with 0.
4. Print the ith value in the array and increment i.
5. Repeat Step 4 until the end of the array is reached.
6. End
Example
Following are the implementations of this operation in C programming languages –

#include <stdio.h>
int main(){
int LA[] = {1,3,5,7,8};
int item = 10, k = 3, n = 5;
int i = 0, j = n;
printf("The original array elements are :\n");
for(i = 0; i<n; i++) {
printf("LA[%d] = %d \n", i, LA[i]);
}
}

Output
The original array elements are :
LA[0] = 1
LA[1] = 3
LA[2] = 5
LA[3] = 7
LA[4] = 8

Array - Update Operation

Update operation refers to updating an existing element from the array at a given index.

Algorithm
Consider LA is a linear array with N elements and K is a positive integer such that
K<=N. Following is the algorithm to update an element available at the Kth position
of LA.

1. Start
2. Set LA[K-1] = ITEM
3. Stop

Example
Following are the implementations of this operation in C programming languages –

#include <stdio.h>
void main(){
int LA[] = {1,3,5,7,8};
int k = 3, n = 5, item = 10;
int i, j;
printf("The original array elements are :\n");
for(i = 0; i<n; i++) {
printf("LA[%d] = %d \n", i, LA[i]);
}
LA[k-1] = item;
printf("The array elements after updation :\n");
for(i = 0; i<n; i++) {
printf("LA[%d] = %d \n", i, LA[i]);
}
}

Output
The original array elements are :
LA[0] = 1
LA[1] = 3
LA[2] = 5
LA[3] = 7
LA[4] = 8
The array elements after updation :
LA[0] = 1
LA[1] = 3
LA[2] = 10
LA[3] = 7
LA[4] = 8

Array - Display Operation

This operation displays all the elements in the entire array using a print statement.

Algorithm
Consider LA is a linear array with N elements. Following is the algorithm to display
an array elements.

1. Start
2. Print all the elements in the Array
3. Stop

Example

Following are the implementations of this operation in C programming languages −

#include <stdio.h>
int main(){
int LA[] = {1,3,5,7,8};
int n = 5;
int i;
printf("The original array elements are :\n");
for(i = 0; i<n; i++) {
printf("LA[%d] = %d \n", i, LA[i]);
}
}

Output
The original array elements are :
LA[0] = 1
LA[1] = 3
LA[2] = 5
LA[3] = 7
LA[4] = 8
1.5 LINKED LISTS

Linked lists and arrays are similar since they both store collections of data.
Array is the most common data structure used to store collections of elements. Arrays
are convenient to declare and provide the easy syntax to access any element by its index
number. Once the array is set up, access to any element is convenient and fast.

The disadvantages of arrays are:


• The size of the array is fixed. Most often this size is specified at compile time. This

makes the programmers to allocate arrays, which seems "large enough" than required.
• Inserting new elements at the front is potentially expensive because existing

elements need to be shifted over to make room.


• Deleting an element from an array is not possible. Linked lists have their own

strengths and weaknesses, but they happen to be strong where arrays are weak.
Generally array's allocates the memory for all its elements in one block whereas
linked lists use an entirely different strategy. Linked lists allocate memory for each
element separately and only when necessary.
Linked List Concepts:
A linked list is a non-sequential collection of data items. It is a dynamic data
structure. For every data item in a linked list, there is an associated pointer that would
give the memory location of the next data item in the linked list. The data items in the
linked list are not in consecutive memory locations. They may be anywhere, but the
accessing of these data items is easier as each data item contains the address of the next
data item.
Types of Linked Lists:
Basically we can put linked lists into the following four items:
1. Single Linked List.
2. Double Linked List.
3. Circular Linked List.
A single linked list is one in which all nodes are linked together in some sequential
manner. Hence, it is also called as linear linked list.
A double linked list is one in which all nodes are linked together by multiple links
which helps in accessing both the successor node (next node) and predecessor node
(previous node) from any arbitrary node within the list. Therefore each node in a
double linked list has two link fields (pointers) to point to the left node (previous) and
the right node (next). This helps to traverse in forward direction and backward
direction.
A circular linked list is one, which has no beginning and no end. A single linked list
can be made a circular linked list by simply storing address of the very first node in
the link field of the last node.
Comparison between array and linked list:

1.6 REPRESENTATION OF A LINKED LIST IN MEMORY


There are two ways to represent a linked list in memory:
1. Static representation using array
2. Dynamic representation using free pool of storage

Static representation
In static representation of a single linked list, two arrays are maintained: one array for
data and the other for links. The static representation of the linked list in Figure 5.2 is
shown in Figure 5.3.

A single linked list with six nodes.


Static representation using arrays of the single linked list of Figure

Two parallel arrays of equal size are allocated which should be sufficient to store
the entire linked list. Neverthemless this contradicts the idea of the linked list (that is
non-contagious location of elements). But in some programming languages, for
example, ALGOL, FORTRAN, BASIC, etc. such a representation is the only
representation to manage a linked list.
Dynamic representation
 The efficient way of representing a linked list is using the free pool of storage. In this
method, there is a memory bank (which is nothing but a collection of free memory
spaces) and a memory manager (a program, in fact). During the creation of a linked list,
whenever a node is required the request is placed to the memory manager; the memory
manager will then search the memory bank for the block requested and, if found, grants
the desired block to the caller.

 Again, there is also another program called the garbage collector; it plays whenever a
node is no more in use; it returns the unused node to the memory bank.
 It may be noted that memory bank is basically a list of memory spaces which is
available to a programmer. Such a memory management is known as dynamic memory
management. The dynamic representation of linked list uses the dynamic memory
management policy.

 The mechanism of dynamic representation of single linked list is illustrated in Figures1


and 2. A list of available memory spaces is there whose pointer is stored in AVAIL.
For a request of a node, the list AVAIL is searched for the block of right size. If AVAIL
is null or if the block of desired size is not found, the memory manager will return a
message accordingly. Suppose the block is found and let it be XY.

 Then the memory manager will return the pointer of XY to the caller in a temporary
buffer, say NEW. The newly availed node XY then can be inserted at any position in
the linked list by changing the pointers of the concerned nodes. In Figure1, the node
XY is inserted at the end and change of pointers is shown by the dotted arrows. Figure
2 explains the mechanism of how a node can be returned from a linked list to the
memory bank.
Fig1. Allocation of a node from memory bank to a linked list.
Fig2: Returning a node from a linked list to memory bank.

The pointers which are required to be manipulated while returning a node are
shown with dotted arrows. Note that such allocations or deallocations are carried out
by changing the pointers only.

1.7 Single Linked List:

 A linked list allocates space for each element separately in its own block of memory called
a "node". The list gets an overall structure by using pointers to connect all its nodes together
like the links in a chain.
 Each node contains two fields; a "data" field to store whatever element, and a "next" field
which is a pointer used to link to the next node. Each node is allocated in the heap using
malloc(), so the node memory continues to exist until it is explicitly de-allocated using
free(). The front of the list is a pointer to the “start” node.
A single linked list is shown in figure

 The beginning of the linked list is stored in a "start" pointer which points to the first node.
The first node contains a pointer to the second node. The second node contains a pointer to
the third node, ... and so on. The last node in the list has its next field set to NULL to mark
the end of the list. Code can access any node in the list by starting at the start and following
the next pointers.
 The start pointer is an ordinary local pointer variable, so it is drawn separately on the left
top to show that it is in the stack. The list nodes are drawn on the right to show that they are
allocated in the heap

Implementation of Single Linked List:


Before writing the code to build the above list, we need to create a start node, used to create
and access other nodes in the linked list. The following structure definition will do (see
figure):
• Creating a structure with one data item and a next pointer, which will be pointing to next
node of the list. This is called as self-referential structure.
• Initialise the start pointer to be NULL.

1.8 Operations in a single linked list:


• Creation.
• Insertion.
• Deletion.
• Traversing.
Creating a node for Single Linked List:
Creating a singly linked list starts with creating a node. Sufficient memory has to be
allocated for creating a node. The information is stored in the memory, allocated by using
the malloc() function. The function getnode(), is used for creating a node, after allocating
memory for the structure of type node, the information for the item (i.e., data) has to be read
from the user, set next field to NULL and finally returns the address of the node. The
following figure illustrates the creation of a node for single linkedlist

Creating a Singly Linked List with ‘n’ number of nodes:


The following steps are to be followed to create ‘n’ number of nodes:
• Get the new node using getnode(). newnode = getnode();

• If the list is empty, assign new node as start. start = newnode;

• If the list is not empty, follow the steps given below:

• The next field of the new node is made to point the first node (i.e. start node)
in the list by assigning the address of the first node.
• The start pointer is made to point the new node by assigning the address of the

new node.
• Repeat the above steps ‘n’ times.

The following figure shows 4 items in a single linked list stored at different locations in
memory. The function createlist(), is used to create ‘n’ number of nodes:

Insertion of a Node:
One of the most primitive operations that can be done in a singly linked list is the
insertion of a node. Memory is to be allocated for the new node (in a similar way that is
done while creating a list) before reading the data. The new node will contain empty data
field and empty next field. The data field ofthe new node is then stored with the information
read from the user. The next field of the new node is assigned to NULL. The new node can
then be inserted at three different places namely:
1.Inserting a node at the beginning.
2.Inserting a node at the end.
3.Inserting a node at intermediate position.
Inserting a node at the beginning:
The following steps are to be followed to insert a new node at the beginning of the list:
Get the new node using getnode(). newnode = getnode();
If the list is empty then start = newnode.
If the list is not empty, follow the steps given below:
newnode -> next = start; start = newnode;

The following figure shows inserting a node into the single linked list at the beginning.

Inserting a node at the end:


The following steps are followed to insert a new node at the end of the list:
Get the new node using getnode() newnode = getnode();
If the list is empty then start = newnode.
If the list is not empty follow the steps given below: temp = start;
while(temp -> next != NULL) temp = temp -> next;
temp -> next = newnode;
Figure shows inserting a node into the single linked list at the end.
The function insert_at_end(), is used for inserting a node at the end.
Inserting a node at intermediate position:
 The following steps are followed, to insert a new node in an intermediate position
in the list:

 Get the new node using getnode(). newnode = getnode();


 Ensure that the specified position is in between first node and last node. If not,
specified position is invalid. This is done by countnode() function.

 Store the starting address (which is in start pointer) in temp and prev pointers.
Then traverse the temp pointer upto the specified position followed by prev
pointer.

 After reaching the specified position, follow the steps given below: prev -> next
= newnode;
newnode -> next = temp;

 Let the intermediate position be 3.


Figure shows inserting a node into the single linked list at a specified intermediate
position other than beginning and end.

The function insert_at_mid(), is used for inserting a node in the intermediate position.
Deletion of a node:
Another primitive operation that can be done in a singly linked list is the deletion of
a node. Memory is to be released for the node to be deleted. A node can be deleted from the
list from three different places namely.
1. Deleting a node at the beginning.
2. Deleting a node at the end.
3. Deleting a node at intermediate position.
Deleting a node at the beginning:
The following steps are followed, to delete a node at the beginning of the list:
If list is empty then display ‘Empty List’ message.
If the list is not empty, follow the steps given below: temp = start;
start = start -> next; free(temp);
Figure shows deleting a node at the beginning of a single linked list.

The function delete_at_beg(), is used for deleting the first node in the list .
Deleting a node at the end:
The following steps are followed to delete a node at the end of the list:
If list is empty then display ‘Empty List’ message.
If the list is not empty, follow the steps given below:
temp = prev = start;
while(temp -> next != NULL)
{
prev=temp;
temp = temp -> next;
}
prev -> next = NULL; free(temp);
Figure shows deleting a node at the end of a single linked list.

The function delete_at_last(), is used for deleting the last node in the list.
Deleting a node at Intermediate position:
The following steps are followed, to delete a node from an intermediate position in the list
(List must contain more than two node).
If list is empty then display ‘Empty List’ message
If the list is not empty, follow the steps given below.
if(pos > 1 && pos < nodectr)
{
temp = prev = start; ctr=1; while(ctr<pos)
{
prev=temp; temp=temp->next; ctr++;
}
prev -> next = temp -> next; free(temp);
printf("\n node deleted..");
}
Figure shows deleting a node at a specified intermediate position other than beginning and

end from a single linked list.


The function delete_at_mid(), is used for deleting the intermediate node in the list.
Traversal and displaying a list (Left to Right):
To display the information, you have to traverse (move) a linked list, node by node from
the first node, until the end of the list is reached. Traversing a list involves the following
steps:
4. Assign the address of start pointer to a temp pointer.
5. Display the information from the data field of each node.
The function traverse() is used for traversing and displaying the information stored in the
list from left to right.
1.8.1 Operations on Singly Linked List

1. Create
2. Insertion
 Inserting At Beginning of the list
 Inserting At End of the list
 Inserting At Specific location in the list

3. Deletion
 Deleting from Beginning of the list
 Deleting from End of the list
 Deleting a Specific Node

4. Display

Create First Node


Step 1 -Include all the header files which are used in the program.
Step 2 - Declare all the user defined functions.
Step 3 - Define a Node structure with two members data and next
Step 4- Define a Node pointer 'head' and set it to NULL
Step 5- Implement the main method by displaying operations menu and make
suitable function calls in the main method to perform user selected operation.
Case 3: Delete from specific location.

Display Node in Linked List

1.9 Merging two lists:


Given two sorted singly linked list, we need to merge these two sorted
linked lists into one without creating any additional node i.e in O(1) space
complexity. For example, below figure shows out two input sorted linked lists
are merged into one linked list.
 First, figure out which node will be the head of the resulting list. It can be easily
found by comparing head nodes of both lists, whichever is smaller is the head
of resultant list. Now, there are n-1 nodes in one list (from list from which head
node was taken) and m nodes in another. Task is now reduced to merge these
two remaining linked lists. Once we merge these two lists, next of head node
will point to head of resultant linked list.
 Second, at each node figure out which list to advance. Store the smaller node
and then point its next to the resultant linked list which is returned by merge two
linked list after removing the smaller node.
 It can be implemented using recursion; same processing (merging) has to be
done on n-1 and m nodes again. Base case for recursion will be when one of the
linked list has been completely traversed and reached till NULL. Then we just
have to attach all remaining nodes in other linked list in resultant linked list.
For example if there are two lists as follows
3->6->7->9->NULL and
1->2->5->8->NULL
 In this case while comparing 3 and 1, head node will be 1 So result = Node 1 This
will be head of resultant list after merge linked lists. We are left with following
linked lists to be merged.
2->5->8->NULL and
3->6->7->9->NULL
 Now, again 2 and 3 are compared and result will be 2. Now linked lists to be
merged are
5->8->NULL and 3->6->7->9->NULL
 At this point 3 and 5 are compared and 3 is stored as result. Remaining linked
lists are
5->8->NULL and 6->7->9->NULL
 With same manner when NULL node is encountered, recursion start unwinding
and at every function return result which we stored will be returned and the next
of previous invocation’s result node.
 In the code we are storing a pointer result (node which is smaller when heads
are compared), and next of that result node will be returned value of next
invocation of merge function.

1.9.1Merging two sorted list Algorithm:

Here is another more complex function to combine two lists; this one
merges nodes from two sorted lists, preserving their order:
Algorithm
Nodemerge( Node p, Node q ) { if ( p == null)
return q;
else if ( q == null) return p;
else if (p.item < q.item) { p.next
= merge( p.next, q ); return p;
}
else {
q.next = merge( p, q.next ); return q;

}
}
EXAMPLE

Merging is the process of combining two sorted lists into a single sorted list.

1.10Reverse A Singly Linked List:


Let’s assume that we are going to start reversing the linked list starting
from the very first node – the head node. What it basically comes down to is
changing pointers from one node to the next so that the entire linked list becomes
reversed. There is definitely a process – an algorithm – that we will want to
follow in order to do that:
Algorithm
1. The head node’s next pointer should be set to NULL since the
head will become the tail. This is an exception for the head node, and can be
done outside the while loop. But, before we do this we will need a temp variable
to point to the 2nd node (the node after the head node), because the only way to
reference the 2nd node is through the head node’s next pointer.
2. The 2nd node (the node after the head node) should have it’s own
next pointer changed to point to the head node. This will reverse the order of the
nodes. But, remember that the 2nd node’s next pointer will at first be pointing to
the 3rd node. This means that before we change the 2nd node’s next pointer, we
have to save a reference to the 3rd node otherwise we will have no way of
referencing the 3rd node. So, we simply store a reference to the 3rd node in a
variable before we change the 2nd node’s next pointer.
3. The 3rd node then becomes the “first” node in the while loop and
we repeat the process of changing pointers described in step 2.

4. Continue step 3 until we come across a node that has a next pointer
set to NULL. When we do come across a NULL next pointer we just set the head
node to point to the node that has the NULL next pointer. This node was
previously the tail node, but is now the head node because we are reversing the
linked list.
Algorithm ReverseLinkedlist(struct node **head)
{
struct node *p, *q, *r;
p = q = r = *head; // assign value of head to variable p,q and rp = p->next->next;
// Making p to point third node in the list
q = q->next; // Making q to point second node in the list
r->next = NULL; // Assign pointer field of first node is NULL
q->next = r; // making next value of second node is node first while (p !=
NULL) // as long as p is not NULL
{
r = q; // assign q to r
q = p; // assign p to q
p = p->next; // making p to point the next node in the listq->next = r; //
Making q to point node r
}
*head = q;
}

1.11 Advantages of singly linked lists:


Linked lists have many advantages. Some of the very important advantages are:
1. Linked lists are dynamic data structures. i.e., they can grow or shrink
during the execution of a program.
2. Linked lists have efficient memory utilization. Here, memory is not
preallocated. Memory is allocated whenever it is required and it is de-allocated
(removed) when it is no longer needed.
3. Insertion and Deletions are easier and efficient. Linked lists provide
flexibility in inserting a data item at a specified position and deletion of the data
item from the given position.
4. Many complex applications can be easily carried out with linked lists.
Disadvantages of singly linked lists:
1. It consumes more space because every node requires a additional
pointer to store address of the next node.
2. Searching a particular element in list is difficult and also time
consuming.

1.12 Double Linked List:

A double linked list is a two-way list in which all nodes will have two
links. This helps in accessing both successor node and predecessor node from
the given node position. It provides bi-directional traversing. Each node contains
three fields:
• Left link.
• Data.
• Right link.
The left link points to the predecessor node and the right link points to the
successor node. The data field
stores the required data. Many applications require searching forward and
backward thru nodes of a list. For example searching for a name in a telephone
directory would need forward and backward scanning thru a region of the whole
list.

The basic operations in a double linked list are:


• Creation.
• Insertion.
• Deletion.
• Traversing.
A double linked list is shown in figure

The beginning of the double linked list is stored in a "start" pointer which points
to the first node. The first node’s left link and last node’s right link is set to
NULL.
The following code gives the structure definition:

Creating a node for Double Linked List:


Creating a double linked list starts with creating a node. Sufficient
memory has to be allocated for creating a node. The information is stored in the
memory, allocated by using the malloc() function. The function getnode(), is
used for creating a node, after allocating memory for the structure of type node,
the information for the item (i.e., data) has to be read from the user and set left
field to NULL and right field also set to NULL

Creating a Double Linked List with ‘n’ number of nodes:


The following steps are to be followed to create ‘n’ number of nodes:
• Get the new node using getnode(). newnode =getnode();

• If the list is empty then start = newnode.

• If the list is not empty, follow the steps given below:

• The left field of the new node is made to point the previous node.

• The previous nodes right field must be assigned with address of the new node.

• Repeat the above steps ‘n’ times.

The function createlist(), is used to create ‘n’ number of nodes:


The following figure shows 3 items in a double linked list stored at different

locations.

Inserting a node at the beginning:


The following steps are to be followed to insert a new node at the beginning of
the list:
• Get the new node using getnode(). newnode=getnode();

• If the list is empty then start = newnode.

• If the list is not empty, follow the steps given below:

newnode -> right = start; start -> left = newnode; start = newnode;
The function dbl_insert_beg(), is used for inserting a node at the beginning.
Figure shows inserting a node into the double linked list at the beginning.
Inserting a node at the end:
The following steps are followed to insert a new node at the end of the list:
• Get the new node using getnode() newnode=getnode();

• If the list is empty then start = newnode.

• If the list is not empty follow the steps given below: temp = start;

while(temp -> right != NULL)


temp = temp -> right; temp -> right = newnode; newnode -> left = temp;
The function dbl_insert_end(), is used for inserting a node at the end. Figure
shows inserting a node into the double linked list at the end.

Inserting a node at an intermediate position:


The following steps are followed, to insert a new node in an intermediate
position in the list:
• Get the new node using getnode(). newnode=getnode();

• Ensure that the specified position is in between first node and last node. If
not, specified position is invalid. This is done by countnode() function.
• Store the starting address (which is in start pointer) in temp and prev pointers.

Then traverse the temp pointer upto the specified position followed by prev
pointer.
• After reaching the specified position, follow the steps given below: newnode -

> left = temp;


newnode -> right = temp -> right; temp -> right -> left = newnode; temp ->
right = newnode;
The function dbl_insert_mid(), is used for inserting a node in the intermediate
position. Figure shows inserting a node into the double linked list at a specified
intermediate position other than beginning and end.

Deleting a node at the beginning:


The following steps are followed, to delete a node at the beginning of the list:
• If list is empty then display ‘Empty List’ message.

• If the list is not empty, follow the steps given below: temp = start;

start = start -> right; start -> left = NULL; free(temp);


The function dbl_delete_beg(), is used for deleting the first node in the list.
Figure shows deleting a node at the beginning of a double linked list.

Deleting a node at the end:


The following steps are followed to delete a node at the end of the list:
• If list is empty then display ‘Empty List’ message
• If the list is not empty, follow the steps given below:
temp = start;
while(temp -> right != NULL)
{
temp = temp -> right;
}
temp -> left -> right = NULL; free(temp);
The function dbl_delete_last(), is used for deleting the last node in the list.
Figure shows deleting a node at the end of a double linked list.

Deleting a node at Intermediate position:


The following steps are followed, to delete a node from an intermediate
position in the list (List must contain more than two nodes).
• If list is empty then display ‘Empty List’ message.
• If the list is not empty, follow the steps given below:
• Get the position of the node to delete.
• Ensure that the specified position is in between first node and last node. If not,
specified position is invalid.
• Then perform the following steps: if(pos > 1 && pos < nodectr)
{
temp=start; i=1;
while(i<pos)
{
temp =temp -> right; i++;
}
temp -> right -> left = temp -> left; temp -> left -> right = temp -> right;
free(temp);
printf("\n node deleted..");
}
The function delete_at_mid(), is used for deleting the intermediate node in the
list. Figure shows deleting a node at a specified intermediate position other
than beginning and end from a double linked list.

Traversal and displaying a list (Left to Right):


To display the information, you have to traverse the list, node by node from the
first node, until the end of the list is reached. The function traverse_left_right()
is used for traversing and displaying the information stored in the list from left
to right.
The following steps are followed, to traverse a list from left to right:
• If list is empty then display ‘Empty List’ message.

• If the list is not empty, follow the steps given below:


temp = start; while(temp != NULL)
{
print temp-> data; temp = temp -> right;
}
Traversal and displaying a list (Right to Left):
To display the information from right to left, you have to traverse the list, node
by node from the first node, until the end of the list is reached. The function
traverse_right_left() is used for traversing and displaying the information stored
in the list from right to left. The following steps are followed, to traverse a list
from right to left:
• If list is empty then display ‘Empty List’ message.

• If the list is not empty, follow the steps given below:


temp = start;
while(temp -> right != NULL) temp = temp -> right; while(temp != NULL)
{
print temp -> data; temp = temp -> left;
}

Counting the Number of Nodes:


The following code will count the number of nodes exist in the list (using
recursion).

1.13 Circular Single Linked List:

 It is just a single linked list in which the link field of the last node points
back to the address of the first node. A circular linked list has no beginning
and no end. It is necessary to establish a special pointer called start pointer
always pointing to the first node of the list.
 Circular linked lists are frequently used instead of ordinary linked list
because many operations are much easier to implement. In circular linked
list no null pointers are used, hence all pointers contain valid address. A
circular single linked list is shown in figure
The basic operations in a circular single linked list are:
• Creation.
• Insertion.
• Deletion.
• Traversing.
Creating a circular single Linked List with ‘n’ number of nodes:
The following steps are to be followed to create ‘n’ number of nodes:
• Get the new node using getnode(). newnode = getnode();

• If the list is empty, assign new node as start. start = newnode;

• If the list is not empty, follow the steps given below:

temp = start;
while(temp -> next != NULL) temp = temp -> next;
temp -> next = newnode;
Repeat the above steps ‘n’ times.
newnode -> next = start;
The function createlist(), is used to create ‘n’ number of nodes:

Inserting a node at the beginning:


The following steps are to be followed to insert a new node at the beginning of
the circular list:
• Get the new node using getnode(). newnode = getnode();

• If the list is empty, assign new node as start.

start = newnode; newnode -> next = start;


• If the list is not empty, follow the steps given below:

last = start;
while(last -> next != start) last= last -> next;
newnode -> next = start; start = newnode;
last -> next = start;
The function cll_insert_beg(), is used for inserting a node at the beginning.

Figure shows inserting a node into the circular single linked list at the
beginning.

Inserting a node at the end:


The following steps are followed to insert a new node at the end of the list:
• Get the new node using getnode(). newnode = getnode();

• If the list is empty, assign new node as start.

start = newnode;
newnode -> next = start;
• If the list is not empty follow the steps given below:

temp = start;
while(temp -> next != start) temp = temp -> next;
temp -> next = newnode; newnode -> next = start;
The function cll_insert_end(), is used for inserting a node at the end. Figure
shows inserting a node into the circular single linked list at the end.
Deleting a node at the beginning:

The following steps are followed, to delete a node at the beginning of the list:
• If the list is empty, display a message ‘Empty List’.

• If the list is not empty, follow the steps given below:

last = temp = start;


while(last -> next != start) last= last -> next;
start = start -> next; last -> next = start;
• After deleting the node, if the list is empty then start = NULL. The function
cll_delete_beg(), is used for deleting the first node in the list. Figure shows
deleting a node at the beginning of a circular single linked list.

Deleting a node at the end:


The following steps are followed to delete a node at the end of the list:
• If the list is empty, display a message ‘Empty List’.
• If the list is not empty, follow the steps given below:
temp = start; prev = start;
while(temp -> next != start)
{
prev=temp;
temp = temp -> next;
}
prev -> next = start;
• After deleting the node, if the list is empty then start = NULL.
The function cll_delete_last(), is used for deleting the last node in the

list.Figure shows deleting a node at the end of a circular single linked list.

Traversing a circular single linked list from left to right:


The following steps are followed, to traverse a list from left to right:
• If list is empty then display ‘Empty List’ message.
• If the list is not empty, follow the steps given below:
temp = start; do
{
printf("%d", temp -> data); temp = temp -> next;
} while(temp != start);

You might also like