Unit 2 New-1-34
Unit 2 New-1-34
Arrays Overview
One memory block is allocated for the entire array to hold the elements of the array. The array elements
can be accessed in constant time by using the index of the particular element as the subscript.
Why Constant Time for Accessing Array Elements?
To access an array element, the address of an element is computed as an offset from the base address of
the array and one multiplication is needed to compute what is supposed to be added to the base address to
get the memory address of the element. First the size of an element of that data type is calculated and then
it is multiplied with the index of the element to get the value to be added to the base address.
This process takes one multiplication and one addition. Since these two operations take constant time, we
can say the array access can be performed in constant time.
Advantages of Arrays
Disadvantage of Array
First Disadvantage of Arrays:
Preallocates all needed memory up front and wastes memory space for indices in the array that are empty.
Fixed size: The size of the array is static (specify the array size before using it).
Although the dynamic allocation of storage is a great advantage, the overhead with storing and retrieving data
can make a big difference. Sometimes linked lists are hard to manipulate.
If the last item is deleted, the last but one must then have its pointer changed to hold a NULL reference.
This requires that the list is traversed to find the last but one link, and its pointer set to a NULL reference.
Finally, linked lists waste memory in terms of extra reference points.
The ListLength() function takes a linked list as input and counts the number of nodes in the list.
The function given below can be used for printing the list data with extra print function.
Time Complexity: O(n), for scanning the list of size n.
Space Complexity: O(1), for creating a temporary variable.
Let us write the code for all three cases. We must update the first element pointer in the calling
function, not just in the called function.
For this reason we need to send a double pointer. The following code inserts a node in the singly linked
list.
Code for Inserting a Node
Note: We can implement the three variations of the insert operation separately.
Time Complexity: O(n), since, in the worst case, we may need to insert the node at the end of the list.
Space Complexity: O(1), for creating one temporary variable.
Singly Linked List Deletion
Similar to insertion, here we also have three cases.
• Deleting the first node
• Deleting the last node
• Deleting an intermediate node.
Now, move the head nodes pointer to the next node and dispose of the temporary node.
The advantage of a doubly linked list (also called two – way linked list) is that given a node in the list, we can
navigate in both directions.
A node in a singly linked list cannot be removed unless we have the pointer to its predecessor.
But in a doubly linked list, we can delete a node even if we don’t have the previous node’s address (since each
node has a left pointer pointing to the previous node and can move backward).
Disadvantages
The primary disadvantages of doubly linked lists are:
Each node requires an extra pointer, requiring more space.
The insertion or deletion of a node takes a bit longer (more pointer operations).
Update head node’s left pointer to point to the new node and make new node as head.
I Step
II Step
Position node right pointer points to the new node
The next node of position node left pointer points to new node.
Now, let us write the code for all of these three cases.
Update the first element pointer in the calling function, not just in the called function.
For this reason we need to send a double pointer.
The following code inserts a node in the doubly linked list
Code
Doubly Linked List Deletion
Similar to singly linked list deletion, here we have three cases:
• Deleting the first node
• Deleting the last node
• Deleting an intermediate node
Update the next pointer of previous node to the tail node with NULL.
Dispose the tail node.
Deleting an Intermediate Node in Doubly Linked List
In this case, the node to be removed is always located between two nodes, and the head and tail links are
not updated. The removal can be done in two steps:
Similar to the previous case, maintain the previous node while also traversing the list. Upon
locating the node to be deleted, change the previous node’s next pointer to the next node of the node to
be deleted.
In singly linked lists and doubly linked lists, the end of lists are indicated with NULL value.
Circular linked lists do not have ends.
In circular linked lists, each node has a successor.
In singly linked lists, there is no node with NULL pointer in a circularly linked list.
Declaration of node
The following is a type declaration for a circular linked list of integers:
In a circular linked list, we access the elements using the head node (similar to head node in singly linked
list and doubly linked lists).
The circular list is accessible through the node marked head.
To count the nodes, the list has to be traversed from the node marked head, with the help of a dummy
node current, and stop the counting when current reaches the starting node head.
If the list is empty, head will be NULL, and in that case set count = 0.
Otherwise, set the current pointer to the first node, and keep on counting till the current pointer
reaches the starting node.
Update the next pointer of the new node with the head node and also traverse the list to the tail. That
means in a circular list we should stop at the node whose next node is head.
Update the next pointer of the previous node to point to the new node and we get the list as shown below.
Update the next pointer of the new node with the head node and also traverse the list until the tail. That
means in a circular list we should stop at the node which is its previous node in the list.
Update the previous head node in the list to point to the new node.
Update the next pointer of tail node’s previous node to point to head.
Dispose of the tail node.
Find the tail node of the linked list by traversing the list. Tail node is the previous node to the head node which
we want to delete.
Create a temporary node which will point to the head. Also, update the tail nodes next pointer to point to next
node of head (as shown below).
Now, move the head pointer to next node. Create a temporary node which will point to head. Also, update the
tail nodes next pointer to point to next node of head (as shown below).