Module 3
Module 3
A circular linked list is a list in which the nodes are connected in a sequence,
where the last node always points to the head (first) node of the linked list.
Generally, the last node in a singly or doubly linked list contains NULL,
which means the end of the list. However, the circular linked lists do not
have any end as the last node always points to the first node of the linked list
which makes it circular.
We must be cautious when navigating circular linked lists to avoid endlessly
exploring the list. It should be noted that, unlike normally linked lists,
circularly linked lists do not have any nodes with a NULL pointer, every
node has a next node in a linear sequence.
struct node{
<data__type> data;
struct node* next;
};
Syntax:
struct node{
<data__type> data;
struct node* next;
struct node* prev;
};
while(current->next != *head){
current = current->next;
}
current->next = temp;
temp->next = *head;
*head = temp;
return;
}
return 0;
}
Output:
List: 10 20 30 40 50 60
C Program
#include<stdio.h>
#include<stdlib.h>
// creating a structure for the circular singly linked list
struct node
{
int data;
struct node *next;
};
// if the list is empty, we assign the new node to the head pointer
if(*head == NULL){
*head = temp;
temp->next = *head;
return;
}
while(current->next != *head){
current = current->next;
}
current->next = temp;
temp->next = *head;
}
int main(){
return 0;
}
Output:
List: 10 20 30 40 50
Similar to the first C program, we have created a structure for the
circular singly linked list. We have created
an insertNodeAtEnd() function to insert new nodes at the end of the
list. It takes two arguments, first the address of the head pointer and
second the data for the new node. We can view the entire list using
the viewList() function.
C Program:
#include<stdio.h>
#include<stdlib.h>
while(current->next != *head){
current = current->next;
}
current->next = temp;
temp->next = *head;
return;
}
// code to insert a new node after a specific value node in the list
void insertAfterSpecificNode(struct node** head, int data, int value){
struct node* temp, *newNode;
// adding the newNode b/w the "value" data node and next node.
newNode->next = temp->next;
temp->next = newNode;
return;
}
int main(){
viewList(&head);
return 0;
}
Output:
List: 3 6 9 12 18 21
List: 3 6 9 12 15 18 21
A skip list SS has a few important properties that are referenced in its
analysis. It has a height of h which is the number of linked lists in it. It
has a number of distinct elements, n. And it has a probability p, which is
usually 12.21.
The highest element (one that appears in the most lists) will appear in
log1p(n)logp1(n) lists, on average. This, if we use p=12p=21, there are
log2(n)log2(n) lists. This is the average value of h. Another way of saying
"Every element in a linked list is in the linked list below it" is "Every
element in level Si+1Si+1 exists in level Si."
Each element in the skip list has four pointers. It points to the node to its
left, its right, its top, and its bottom. These quad-nodes will allow us to
efficiently search through the skip list.
In a doubly linked list, you store two pointers per node: prev and next. In an
XOR linked list, you store one 'pointer' per node, which is the XOR of prev and
next (or if one of them is absent, just the other (the same as XORing with 0)).
The reason why you can still traverse an XOR linked list in both directions
relies on the properties of XOR and the redundancy of information inherent in a
double linked list.
XOR List; Pro’s and Con’s
While an XOR linked list has the advantage of smaller memory usage, it
has disadvantages — it will confuse the compiler, debugging and static
analysis tools as your XOR of two pointers will not be correctly
recognized by a pointer by anything except your code.
It also slows down pointer access to have to do the XOR operation to
recover the true pointer first.
It also can't be used in managed code — XOR obfuscated pointers won't
be recognized by the garbage collector.
DYNAMIC ARRAYS
• A dynamic array is an array whose size can be changed during runtime.
Unlike static arrays, which have a fixed size that is determined at
compile time, dynamic arrays can be resized as needed. It allows for more
flexibility and better memory management, as the size of the array can be
adjusted to fit the amount of data being stored.
• Dynamic arrays are implemented using pointers and memory allocation
functions. In C, the most commonly used memory allocation functions
are malloc(), calloc(), and realloc(). These functions allow for the
allocation and deallocation of memory during runtime, which is necessary
for creating and manipulating dynamic arrays.
Output:
012345
MULTI-DIMENSIONAL ARRAY
C allows arrays of three or more dimensions. The exact limit is
determined by the compiler. The general form of a multi-dimensional
array is
type array_name[s1][s2][s3]....[sm];
where si is the size of the ith dimension. Some example are:
int survey[3][5][12];
float table[5][4][5][3];
survey is a three-dimensional array declared to contain 180 integer type
elements. Similarly table is a 4D array containing 300 elements of
floating point type.
The array survey may represent a survey data of rainfall during the last 3
years from January to December in 5 cities.
If the 1st index denotes year, 2nd city and the 3rd month, then the element
survey[2][3][10]
denotes the rainfall in the month of October during the second year in
city-3.
3D array representation
4. Create a function to merge two sorted linked lists into a single sorted linked
list without using extra space.
5. Implement a circular buffer using an array. Include functions for enqueue,
dequeue, and checking if the buffer is full or empty.
6. Write a function to find the intersection point of two singly linked lists.
7. Implement a sparse matrix using a linked list of linked lists. Include functions
for matrix addition and multiplication.
8. Create a function to rotate a linked list to the right by k nodes.
9. Implement a memory-efficient doubly linked list using XOR of addresses
(XOR linked list).
10. Write a function to flatten a multilevel doubly linked list.
11. Implement a function to perform in-place merge sort on a singly linked list.
12. Create a self-organizing list that moves frequently accessed elements to the
front (using move-to-front heuristic).
13. Implement a function to rearrange a linked list in such a way that all even
position nodes are before odd position nodes.
14. Write a function to clone a linked list with random pointers.
15. Implement a persistent data structure for a singly linked list that allows
access to previous versions after modifications.