module2_array&LL
module2_array&LL
An array is a collection of elements of the same data type, stored in contiguous memory
locations. Arrays allow you to store multiple values of the same type in a single variable, and
you can access the elements using an index. The index of an array starts at 0 and goes up to
(n-1) for an array of size n.
Initialization of Arrays
Key Points
• Fixed size: Once an array is declared with a specific size, its size cannot be changed.
• Indexing: Array elements are accessed using indices starting from 0.
• Homogeneous elements: All array elements must be the same type.
• Memory layout: Arrays are stored in contiguous blocks of memory.
Single-Dimension Array:
Example in C:
int arr[5] = {10, 20, 30, 40, 50}; // A single-dimension array of size 5
1
o arr[0] = 10
o arr[1] = 20
o arr[2]=30
o …….
• Use cases: Single-dimension arrays are used when the data can be represented in a
simple linear form, such as a list of integers, names, or marks.
Multi-Dimensional Array:
A multi-dimensional array is an array of arrays. The most commonly used form is the two-
dimensional array, but arrays can have higher dimensions (3D, 4D, etc.). Multi-dimensional
arrays are stored in row-major or column-major order depending on the programming
language.
2D Array Example:
A two-dimensional array can be thought of as a matrix, where each element is accessed using
two indices.
Example in C:
int matrix[3][4] = {
{1, 2, 3, 4},
{5, 6, 7, 8},
{9, 10, 11, 12}
};
• Accessing elements: Each element is accessed using two indices, one for the row and
one for the column.
o matrix[0][0] = 1
o matrix[1][2] = 7
o ……
• Use cases: Multi-dimensional arrays are useful for representing data that has multiple
dimensions, such as:
o A 2D grid (e.g., a chessboard)
o Matrices for mathematical operations
o Tables with rows and columns
Differences
2
Aspect Single-Dimension Array Multi-Dimensional Array
Structure Linear (a list of elements) Matrix-like (array of arrays)
Indexing Single index (e.g., arr[i]) Multiple indices (e.g., arr[i][j])
Memory Stored contiguously in Stored either in row-major or column-major
Layout memory order
Linear data structures (e.g.,
Use cases Tables, matrices, multi-dimensional data
list)
Example:
Assume arr starts at memory address 1000, and each integer takes 4 bytes. The memory
layout would look like:
Here, each element is 4 bytes apart, as the integer data type occupies 4 bytes. The memory
address of an element can be calculated as:
In this case:
3
Address of arr[2]=1000+(2-0)×4=1008
• Row-major order
• Column-major order
In row-major order (used in languages like C/C++), the array is stored row by row in
contiguous memory locations.
Example:
int matrix[3][4] = {
{1, 2, 3, 4},
{5, 6, 7, 8},
{9, 10, 11, 12}
};
Assuming the starting address is 2000, and each integer takes 4 bytes, the memory layout
would look like this (row-major order):
• The elements of the first row are stored first, followed by the elements of the second
row, and so on.
4
Address of matrix[i][j]=Base Address+[((i-Lr)×number of columns)+j]×Size of Element
Address of matrix[1][2]=2000+[((1-0)×4)+2]×4=2024
In column-major order (used in languages like Fortran), the array is stored column by column
in contiguous memory locations.
c
Copy code
int matrix[3][4] = {
{1, 2, 3, 4},
{5, 6, 7, 8},
{9, 10, 11, 12}
};
5
For matrix[1][2], this would be:
Address of matrix[1][2]=2000+[((2-0)×3)+1]×4=2028
• Single-dimension arrays are stored in contiguous memory, and each element can be
accessed using a single index.
• Multi-dimensional arrays can be stored either in row-major or column-major order,
with elements accessed using multiple indices.
Array Operations
1. Traversal
Traversal involves visiting each element of the array exactly once, usually to display or
process the elements.
Example in C:
• Output: 10 20 30 40 50
2. Insertion
Insertion adds a new element at a specified position in the array. If inserting in the middle of
an array, the elements from that position onward need to be shifted to the right.
6
• Resulting Array: {10, 20, 25, 30, 40, 50}
3. Deletion
Deletion removes an element from a specific position in the array. After deletion, the
elements to the right of the deleted element need to be shifted to the left to fill the gap.
4. Searching
Searching involves finding the position of a given element in an array. There are two main
types of searching:
• Linear Search: Search for the element by checking each element one by one.
• Binary Search: If the array is sorted, use binary search to find the element more
efficiently.
Search Example:
5. Sorting
Sorting is the process of rearranging the elements of the array in a specific order, typically
either ascending or descending. There are several sorting algorithms:
• Bubble Sort: Compare adjacent elements and swap them if they are in the wrong
order.
• Selection Sort: Select the smallest (or largest) element and place it in its correct
position.
• Merge Sort, Quick Sort: More efficient algorithms that follow the divide-and-
conquer strategy.
Sort Example:
7
int arr[] = {50, 20, 40, 10, 30};
int n = sizeof(arr) / sizeof(arr[0]);
for (int i = 0; i < n - 1; i++) {
for (int j = 0; j < n - i - 1; j++) {
if (arr[j] > arr[j + 1]) {
int temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
}
6. Merging
Merging involves combining two sorted arrays into a single sorted array.
Example:
7. Reversing
Example:
8
int arr[] = {10, 20, 30, 40, 50};
int n = sizeof(arr) / sizeof(arr[0]);
for (int i = 0; i < n / 2; i++) {
int temp = arr[i];
arr[i] = arr[n - i - 1];
arr[n - i - 1] = temp;
}
8. Updating
9. Copying
Copying one array into another array involves transferring all elements from one array to
another.
Example:
Parallel arrays (or structure of arrays) refer to a data structure where multiple arrays are
used in parallel, with each array holding a different type of data, but corresponding elements
at the same index across all arrays are logically related. Essentially, parallel arrays store
different attributes of the same entity in different arrays.
9
In this example:
So for index 0:
• names[0] = "Alice"
• ages[0] = 20
• grades[0] = 'A'
The values across the arrays at the same index (i) represent different attributes of the same
student.
Advantages:
1. Separation of Data Types: Parallel arrays make it easy to handle different data types
for different attributes of the same entity.
2. Direct Access: Each array stores one type of data, so you can easily access or process
just one aspect of the entity (e.g., names or ages) without affecting the other data.
3. Memory Efficiency: When using low-level languages like C, parallel arrays can be
more memory-efficient than using an array of structures because of more control over
memory alignment and layout.
Disadvantages:
1. Indexing Complexity: You must always ensure that you use the same index across
all arrays to refer to the same entity. If this indexing is not synchronized, it can lead to
logical errors.
2. Lack of Encapsulation: Parallel arrays do not bundle the data for a single entity
together, making it harder to conceptually treat the data as a single object. In object-
oriented programming, a class or structure would be more natural.
Sparse Matrix
A sparse matrix is a matrix in which most of the elements are zero. Sparse matrices are often
encountered in scientific computing, machine learning, graph theory, and other areas where
large datasets are common, but only a small subset of the data is significant (non-zero). Due
to the large number of zero elements, sparse matrices can be efficiently represented and
processed using specialized storage techniques.
10
• Most elements are zero: Typically, a matrix is considered sparse if more than half of
its elements are zero.
• Efficient storage: Rather than storing all elements (including the zeros), sparse
matrices use techniques to store only the non-zero elements, leading to significant
memory savings.
Copy code
|0 0 0 0 5|
|0 8 0 0 0|
|0 0 0 0 0|
|2 0 0 0 0|
In this 4x5 matrix, only three elements are non-zero. Storing all the zero elements would be
inefficient, especially if the matrix size is large.
To efficiently represent sparse matrices, the following methods are often used:
The COO format stores the non-zero elements and their corresponding row and column
indices.
• Values: [5, 8, 2]
• Row indices: [0, 1, 3]
• Column indices: [4, 1, 0]
11
Linked List
Linked list is a linear collection of data elements called nodes. It can be considered as a series
of nodes, with each node storing data as well as the address of the next node.
Linked lists contain a pointer variable HEAD that stores the address of the first node. Also,
we store NULL in the address part of the last node because it has no next node connected to
it.
Arrays store elements in contiguous memory locations. The size of the array is fixed and
cannot be changed at runtime. We must know the number of elements in advance. Normally
the allocated memory is equal to the upper limit of the array and In practice, however, the
highest limit is rarely attained.
12
In a linked list nodes can exist at non-contiguous addresses. This permits the linked list’s size
to be changed at runtime.
Array elements can be accessed directly with its index. But in the case of a linked list,
random access is not possible. To access any element, all previous items must be traversed.
Inserting and deleting elements in an array is expensive because we have to shift the elements
to preserve the order. Ease of insertion and deletion is a notable advantage of linked lists at
the cost of extra space required for storing the address pointers.
Data can be only stored in contiguous memory Data can exist at non-contiguous
locations. addresses.
Size is fixed and cannot be altered at runtime. Size can be changed at runtime.
A linked list is a series of nodes in which the address of the first node is stored in a pointer
called HEAD. Each of the nodes in the linked list consists of two parts:
• A data item.
• An address that points to another node.
struct node
int data;
};
Each struct node contains a data item as well as a pointer to another struct node. The
following example creates a basic Linked List with three items and displays its elements.
#include <stdio.h>
13
#include <stdlib.h>
struct node
int data;
};
int main()
one->data = 1;
two->data = 2;
three->data = 3;
one->next = two;
14
// Connect second node
two->next = three;
three->next = NULL;
head = one;
current = head;
while(current != NULL)
current = current->next;
return 0;
Output
123
15
• To implement other data structures such as Queues, Stacks, Trees, Graphs, etc.
• Used for dynamic memory allocation.
• For manipulating polynomials, representing sparse matrice, etc.
• In undo functionality of softwares.
• Previous and next page navigation on web browsers.
Like any other data structure, we can perform insertion, deletion and traversal operations in a
linked list. In the next tutorial, let’s learn Algorithms for insertion, deletion and traversal
operations in a linked list.
A doubly linked list or two way linked list is a type of linked list that contains a pointer to
the next node as well as the previous node in the sequence.
16
struct node *one = NULL;
struct node *two = NULL;
struct node *three = NULL;
struct node *current = NULL;
// Allocate memory for the nodes
one = (struct node*) malloc(sizeof(struct node));
two = (struct node*) malloc(sizeof(struct node));
three = (struct node*) malloc(sizeof(struct node));
// Assign data to nodes
one->data = 1;
two->data = 2;
three->data = 3;
// Connect first node
// with the second node
one->next = two;
// Connect second node
// with the third node
two->next = three;
// make next pointer of
//third node to NULL
//indicates last node
three->next = NULL;
//connect previous nodes
one->prev = NULL;
two->prev = one;
three->prev = two;
// Save address of first node in head
head = one;
current = head;
// print the linked list values forward
while(current != NULL)
{
printf("%d ", current->data);
current = current->next;
}
return 0;
}
Now we’ve made a doubly-linked list with three nodes.
Output
123
17
Circular Linked List
A circular linked list is a type of linked list in which the last node is also connected to the first
node to form a circle. Thus a circular linked list has no end.
18
one->data = 1;
two->data = 2;
three->data = 3;
// Connect first node
// with the second node
one->next = two;
// Connect second node
// with the third node
two->next = three;
// Connect second node
// with the third node
three->next = one;
// Save address of first node in head
head = one;
current = head;
// print the linked list values
while(current != NULL)
{
printf("%d ", current->data);
current = current->next;
}
return 0;
}
Now we’ve made a circular linked list with three nodes.
19
• Allocate memory for new node and initialize its DATA part to 24.
• Add the new node as the first node of the list by pointing the NEXT part of the new
node to HEAD.
• Make HEAD to point to the first node of the list.
• Make HEAD point to the new node.
Algorithm: InsertAtBeginning
Step 1: IF AVAIL = NULL
Write OVERFLOW
Go to Step 11
[END OF IF]
Step 2: SET NEW_NODE = AVAIL
Step 3: SET AVAIL = AVAIL NEXT
Step 4: SET NEW_NODE -> DATA = VAL
Step 5: SET PTR = HEAD
Step 6: Repeat Step 7 while PTR -> NEXT != HEAD
Step 7: PTR = PTR -> NEXT
[END OF LOOP]
Step 8: SET NEW_NODE -> NEXT = HEAD
Step 9: SET PTR -> NEXT = NEW_NODE
Step 10: SET HEAD = NEW_NODE
Step 11: EXIT
Note that the first step of the algorithm checks if there is enough memory available to create a
new node. The second, and third steps allocate memory for the new node.
Insert at the end of the list
Suppose we want to add a new node with data 24 as the last node of the following circular
linked list. The following changes have to be made in the linked list.
20
• Allocate memory for the new node and initialize data.
• Traverse to the end of the list.
• Point the NEXT part of the last node to the newly created node.
• Make the value of next part of last node to HEAD.
Algorithm: InsertAtLast
Step 1: IF AVAIL = NULL
Write OVERFLOW
Go to Step 1
[END OF IF]
Step 2: SET NEW_NODE = AVAIL
Step 3: SET AVAIL = AVAIL -> NEXT
Step 4: SET NEW_NODE -> DATA = VAL
Step 5: SET NEW_NODE -> NEXT = HEAD
Step 6: SET PTR = HEAD
Step 7: Repeat Step 8 while PTR -> NEXT != HEAD
Step 8: SET PTR = PTR -> NEXT
[END OF LOOP]
Step 9: SET PTR -> NEXT = NEW_NODE
Step 1 : EXIT
Deleting a Node from a Circular Linked List
Let’s look at how a node is removed from a circular linked list in the following scenarios.
• The first node is deleted.
• The last node is deleted.
The remaining cases are the same as those described for a singly linked list.
Deleting first node from a list
The following changes have to be made to the linked list if we want to remove the first node
having data 24.
21
• Check if the linked list is empty or not. Exit if the list is empty.
• Make HEAD points to the second node.
• Traverse to the end of the list and point the next part of last node to second node.
• Free the first node from memory.
Algorithm: DeleteFirst
Step 1: IF HEAD = NULL
Write UNDERFLOW
Go to Step 8
[END OF IF]
Step 2: SET PTR = HEAD
Step 3: Repeat Step 4 while PTR -> NEXT != HEAD
Step 4: SET PTR = PTR -> NEXT
[END OF LOOP]
Step 5: SET PTR -> NEXT = HEAD -> NEXT
Step 6: FREE HEAD
Step 7: SET HEAD = PTR -> NEXT
Step 8: EXIT
Deleting last node from the list
Suppose we want to delete the last node from the circular linked list. The following changes
will be done in the list.
22
• Traverse to the end of the list.
• Change value of next pointer of second last node to HEAD.
• Free last node from memory.
Algorithm: DeleteFirst
Step 1: IF HEAD = NULL
Write UNDERFLOW
Go to Step 8
[END OF IF]
Step 2: SET PTR = HEAD
Step 3: Repeat Steps 4 and 5 while PTR NEXT != HEAD
Step 4: SET PREPTR = PTR
Step 5: SET PTR = PTR -> NEXT
[END OF LOOP]
Step 6: SET PREPTR -> NEXT = HEAD
Step 7: FREE PTR
Step 8: EXIT
23