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

05-DS-Linked List-2024

linked list DSA in C.

Uploaded by

meaditya031
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)
14 views58 pages

05-DS-Linked List-2024

linked list DSA in C.

Uploaded by

meaditya031
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

Linked List

Alok Kumar Jagadev


Linked List
n Linked List is a commonly used linear data structure
n Consists of group of nodes in a sequence
n Each node holds data (info) and the address of the next node forming a
chain like structure
n head: pointer to the first node
n The last node points to NULL

head

10 20 20
Linked List

n Linked lists
n Abstract data type (ADT)
n Basic operations of linked lists
n Insert, find, delete, print, etc.
n Variations of linked lists
n Single linked lists
n Double linked lists
n Circular linked lists
Array versus Linked Lists

• Arrays are suitable for:


– Inserting/deleting an element at the end
– Randomly accessing any element
– Searching the list for a particular value

• Linked lists are suitable for:


– Inserting an element
– Deleting an element
– Applications where sequential access is required
– In situations where the number of elements cannot be predicted beforehand
Types of Lists

n Depending on the way in which the links are used to maintain adjacency,
several different types of linked lists are possible.
n Linear single-linked list (or simply linear list)

head

10 20 30
Single-linked lists vs. 1D-arrays
ID-array Single-linked list

Fixed size: Resizing is expensive Dynamic size

Insertions and Deletions are inefficient: Insertions and Deletions are efficient: No
Elements are usually shifted shifting

Random access i.e., efficient indexing No random access


 Not suitable for operations requiring
accessing elements by index such as
sorting
No memory waste if the array is full or Extra storage needed for references;
almost full; otherwise may result in much however uses exactly as much memory as it
memory waste. needs
Access is faster because of greater locality Access is slower because of low locality of
of references [Reason: Elements in references [Reason: Elements not in
contiguous memory locations] contiguous memory locations]
Circular Linked List

n Circular linked list


n The pointer from the last element in the list points back to the first element.

head

10 20 30
Double Linked List

n Double linked list


n Pointers exist between adjacent nodes in both directions.
n The list can be traversed either forward or backward.
n Usually two pointers are maintained to keep track of the list, head and tail.

head tail

10 20 30
Why Linked List?
n Arrays can be used to store linear data of similar types, but arrays have
the following limitations.
n size of the arrays is fixed
n upper limit on the number of elements must know in advance.
n Allocated memory is for the total array irrespective of the usage.

n Inserting a new element in an array of elements is expensive


n the room has to be created for the new elements and
n to create room existing elements have to be shifted.
Basic Operations on a List

n Creating a list
n Traversing the list
n Inserting an item in the list
n Deleting an item from the list
n Concatenating two lists into one
List is an Abstract Data Type
• What is an abstract data type?
– data type defined by the user
– Typically more complex than simple data types like int, float, etc.

• Why abstract?
– Because details of the implementation are hidden.
– When some operations on the list are performed, just the functions are called.
– Details of how the list is implemented or how the insert function is written is
no longer required.
Conceptual Idea

Insert
List
implementation
Delete
and the
related functions
Traverse
Structure of a Node
n Declare Node structure
n data: int-type data in this example
n next: a pointer to the next node in the list

struct Node {
int data; // data
struct Node* next; // pointer to next node
};
Create a List
void createList() {
int k, n;
struct Node *p, *head;
printf ("Number of nodes: ");
scanf ("%d", &n);
for (k=0; k<n; k++) {
if (k == 0) {
head = (struct Node *) malloc(sizeof(struct Node));
p = head;
}
else {
p->next = (struct Node *) malloc(sizeof(struct Node));
p = p->next;
}
scanf ("%d", &p->data);
}
p->next = NULL;
}
Traversing the List

n Once the linked list has been constructed and head points to the first node
of the list,
n Follow the pointers
n Display the contents of the nodes as they are traversed
n Stop when the next pointer points to NULL
Traversing the List
void display () {
int count = 1;
struct Node *p;
if(head == NULL) {
printf(“\nEmpty List...”);
return;
}
p = head;
while (p != NULL) {
printf ("\nNode: %d: %d", count, p->data);
count++;
p = p->next;
}
printf ("\n");
}
Inserting a Node in a List
Inserting a Node in a List
• Insert at beginning of the list:
– Only one next pointer needs to be modified.
• head is made to point to the new node.
• New node points to the previously first node.

• Insert at end of the list:


– Two next pointers need to be modified.
• Last node points to the new node.
• New node points to NULL.

• When a node is added in the middle (at any position)


– Two next pointers need to be modified.
• Previous node now points to the new node.
• New node points to the next node.
Inserting at Begining
Inserting at Begining
void insertAtBegining() {
struct Node* newNode = (struct Node*) malloc(sizeof(struct Node));
printf("\nEnter the new data: ");
scanf("%d", &newNode->data);
newNode->next = head;
head = newNode;
}
Inserting at End
Inserting at End
void insertAtEnd() {
struct Node* last;
struct Node* newNode = (struct Node*) malloc(sizeof(struct Node));
printf("\nEnter the new data: ");
scanf("%d", &newNode->data);
newNode->next = NULL;
last = head;
if (head == NULL) {
head = newNode;
return;
}
while (last->next != NULL)
last = last->next;
last->next = newNode;
}
Inserting After a Node
Inserting After a Node
void insertAfter() {
struct Node , *prev, *newNode;
prev=head;
while(prev->next != NULL && prev->data != val)
prev = prev->next;
if (prev->data == val) {
newNode =(struct Node*) malloc(sizeof(struct Node));
printf("\nEnter the new data: ");
scanf("%d", &newNode->data);
newNode->next = prev->next;
prev->next = newNode;
}
else
printf( "Value %d is not in list\n", val);
}
Insert a node at a specific position
void insertAtPos() {
i = 1;
int pos, i, nodes=0;
curr = head;
struct Node *newNode, *prev;
while(i<pos) {
struct Node* curr=head;
i++;
while(curr != NULL){
prev = curr;
nodes++;
curr = curr->next;
curr=curr->next; }
}
printf("\nEnter the position: ");
newNode->next = prev->next;
scanf("%d", &pos);
prev->next = newNode;
if(pos < 1 || pos > nodes) {
}
printf("Invalid Input...");
return; }
newNode =(struct Node*) malloc(sizeof(struct Node));
printf("\nEnter the new data: ");
scanf("%d", &newNode->data);
newNode->next=NULL;
if(pos==1) {
newNode->next=head;
head=newNode;
}
Deleting a Node in a List
Deleting a Node in the List
To delete a node from linked list, need to do following steps:
n Find previous node of the node to be deleted
n Change the next of previous node
n Free memory for the node to be deleted
Deleting a Node at Beginning
Deleting a Node at Beginning
void deleteAtBeginning() {
struct Node* temp = head;
if (temp == NULL) {
printf(\nEmpty list...");
return;
}
printf(\nValue of the deleted node = %d", temp->data);
head = head->next;
free(temp);
}
Deleting a Node at End
Deleting a Node at End
void deleteAtEnd() { while (temp->next != NULL ) {
struct Node* temp = head; prev = temp;
struct Node* prev; temp = temp->next;
if (temp == NULL) { }
printf(\nEmpty list..."); printf(\nValue of the deleted node = %d",
return; temp->data);
} prev->next = temp->next;
if (temp->next == NULL) { free(temp);
printf(\nList contains only node, its }
value = %d", temp->data);
head = NULL;
free(temp);
return;
}
Deleting a Node at any Position
Deleting a Node at any Position
void deleteAtAnyPosition(int key) { while ( temp && temp->data != key) {
struct Node* temp = head, *prev; prev = temp;
if (temp == NULL ) { temp = temp->next;
printf("\nEmpty List..."); }
return; if (temp == NULL) {
} printf("\nSearched value does not exist
if (temp != NULL && temp->data == key) { in the list...");
printf(\nValue of the deleted node = %d", return;
temp->data); }
head = temp->next; printf(\nValue of the deleted node = %d",
free(temp); temp->data);
return; prev->next = temp->next;
} free(temp);
}
Detect the loop in a single linked list
int detectLoop() {
struct Node *slowp = head, *fastp = head;
if (head == NULL || head->next == NULL) {
printf(\nEmpty list or list contains one node...");
return 0;
}
while (slowp && fastp && fastp->next) {
slowp = slowp->next;
fastp = fastp->next->next;
if (slowp == fastp)
return 1;
}
return 0;
}
Reverse a single linked list
void reverse() {
struct Node* prev = NULL, *ptr;
struct Node* curr = head;
if(head == NULL) {
printf("\nEmpty List ...");
return;
}
while (curr != NULL) {
ptr = curr->next;
curr->next = prev;
prev = curr;
curr = ptr;
}
head = prev;
}
Double Linked List
A Double Linked List contains an extra pointer, typically called previous pointer,
together with next pointer and data which are there in single linked list.

Node of a double linked list


struct Node {
int data;
struct Node* next; // Pointer to next node
struct Node* prev; // Pointer to previous node
};
Double Linked List
Following are advantages/disadvantages of DLL over single linked list.
Advantages:
1) A DLL can be traversed in both forward and backward directions.
2) The delete operation in DLL is more efficient if pointer to the node to be deleted is
given.
3) Quickly insert a new node before a given node.
4) In single linked list, to delete a node, pointer to the previous node is needed. To get
this previous node, sometimes the list is traversed. In DLL, can get the previous node
using previous pointer.

Disadvantages:
1) Every node of DLL requires extra space for an previous pointer.
2) All operations require an extra pointer previous to be maintained.
§ For example, in insertion, need to modify previous pointers together with next
pointers.
Inserting at Beginning in a DLL
Inserting at Beginning in a DLL
void insertAtBegining() {
struct Node* newNode = (struct Node*) malloc(sizeof(struct Node));
printf("\nEnter the new data: ");
scanf("%d", &newNode->data);
newNode->next = head;
new_node->prev = NULL;
if (head != NULL)
head->prev = newNode;
head = newNode;
}
Inserting at End in a DLL
Inserting at End in a DLL
void insertAtEnd() {
struct Node* last = head
struct Node* newNode = (struct Node*) malloc(sizeof(struct Node));
printf("\nEnter the new data: ");
scanf("%d", &newNode->data);
newNode->next = NULL;
if (head == NULL) {
newNode->prev = NULL;
head = newNode;
return; }
while (last->next != NULL)
last = last->next;
last->next = newNode;
newNode->prev = last;
return; }
Inserting at Any Position in a DLL
Inserting at Any Position in a DLL
void insertAtAnyPosition() { if(curr->next == NULL) { insertAtEnd();
int i = 1, pos; return;}
struct Node* newNode, *curr; if(curr != NULL) {
curr = head; newNode = (struct Node*)
if(head == NULL) { malloc(sizeof(struct Node));
printf("\nEmpty list..."); printf("\nEnter the new data: ");
return; scanf("%d", &newNode->data);
} newNode->next = curr->next;
printf("\nEnter the position at which it will newNode->prev = curr;
be inserted: "); if(curr->next != NULL) curr->next->prev
scanf("%d", &pos); = newNode;
if(pos == 1) {insertAtBeginning(); return;} curr->next = newNode;
while(i< pos-1 && curr!=NULL) { }
curr = curr->next; else printf("Invalid position...\n"); }
i++; }
Delete node from the beginning of a
double linked list
Delete node from the beginning of a
double linked list
void deleteATBeginning() {
struct Node *temp;
if(head == NULL) {
printf("Empty List, Delete is not possible...\n");
return;
}
temp = head;
head = head->next;
if(head != NULL) head->prev = NULL;
free(temp);
}
Delete node from the end of a double
linked list
Delete node from the end of a double
linked list
void deleteAtEnd() {
struct Node *temp;
if(head == NULL) {
printf("Empty List, Delete is not possible...\n");
return;
}
temp = head;

while(temp->next != NULL) temp=temp->next;


if(temp->prev != NULL) temp->prev->next = NULL;
else head = NULL;
free(temp);
}
Delete node from a position of a
double linked list
Delete node from a position of a double
linked list else {
temp->prev->next = temp->next;
void deleteAtPosition(int pos) { temp->next->prev = temp->prev;
struct Node *temp; free(temp);
int i; }
if(head == NULL) { }
printf("Empty List, Delete is not possible...\n");
return;
}
if(pos == 1) deleteAtBeginning();
temp = head;
i=1;
while(i<pos && temp!=NULL) {
i++;
temp=temp->next;
}
if(temp==NULL) printf("Invalid Position...\n");
else if(temp->next == NULL) deleteAtEnd();
Delete all the even nodes from a double
linked list
void deleteEvenNodes() { // if node to be deleted is NOT the first node
struct Node* temp = head; if (temp->prev != NULL)
struct Node* nxt; temp->prev->next = temp->next;
if(head==NULL) { free(temp);
printf("Empty List, Invalid deletion...\n"); }
return; temp = nxt;
} }
while (temp != NULL) { }
nxt = temp->next;
if (temp->data % 2 == 0) {
// If node to be deleted is head node
if (head == temp)
head = temp->next;
// if node to be deleted is NOT the last node
if (temp->next != NULL)
temp->next->prev = temp->prev;
Circular Single Linked List
Why Circular?
n In a single linked list, for accessing any node of a linked list, always traverse from
the first node.
n If reached at any node in the middle of the list, then it is not possible to access
nodes that precede the given node.
n This problem can be solved by slightly altering the structure of single linked list.
n In a single linked list, next part of the last node is NULL
n If this link points to the first node then it can reach preceding nodes.
Circular Single Linked List
Insertion:
n A node can be added in three ways:
n Insertion in an empty list
n Insertion at the beginning of the list
n Insertion at the end of the list
n Insertion in between the nodes
Insertion in an empty List
void insertToEmptyList() {
if (head != NULL)
return;
struct Node *curr = (struct Node*)malloc(sizeof(struct Node));
printf("\nEnter the data: ");
scanf("%d", &curr->data);
curr -> next = curr;
head = last = curr;
}
Insertion at the beginning
void insertAtBeginning() {
if (last == NULL) {
insertToEmptyList();
return;
}
struct Node *curr = (struct Node *)malloc(sizeof(struct Node));
printf("\nEnter the data: ");
scanf("%d", &curr->data);
curr -> next = last -> next;
last -> next = curr;
head = curr;
}
Insert at End
void insertAtEnd() {
void insertAtEnd() {
struct Node *curr;
struct Node *newNode = (struct Node*)
struct Node *newNode = (struct Node*)
malloc(sizeof(struct Node));
malloc(sizeof(struct Node));
printf("\nEnter the data: ");
printf("\nEnter the data: ");
scanf("%d", &newNode->data);
scanf("%d", &newNode->data);
if (last == NULL) {
if (head == NULL) {
newNode -> next = newNode;
newNode->next = newNode;
head = last = newNode;
head = newNode;
}
}
newNode -> next = last -> next;
curr = head;
last -> next = newNode;
while(curr->next != head)
last = newNode;
curr = curr->Next;
}
newNode->next = curr->next;
curr->next = newNode; }
Header Linked List
n A header node is a special node that is found at the beginning of the list.
n A list that contains this type of node, is called the header-linked list.
n This type of list is useful when information other than each node value is needed.
n For example, suppose there is an application in which the number of nodes in a list
is often calculated.
n Usually, a list is always traversed to find the length of the list.
n However, if the current length is maintained in an additional header node that
information can be easily obtained.
Create a Header Linked List
void createHeaderList() {
struct node *newNode, *curr;
newNode = (struct Node*) malloc(sizeof(struct Node));
sacnf("%d", &newNode->data);
newNode->next = NULL;
if (start == NULL) {
start = (struct Node*) malloc(sizeof(struct Node));
start->next = newNode;
}
else {
curr = start->next;
while (curr->next != NULL)
curr = curr->next;
curr->next = newNode;
}
}
Display a Header Linked List
void display() {
struct Node* curr;
curr = start->next;
while (curr != NULL) {
printf("%d ", curr->data);
curr = curr->next;
}
}

You might also like