1.
C Program to Implement Singly Linked List:
#include <stdio.h>
#include <stdlib.h>
struct Node {
int data;
struct Node* next;
};
struct Node* head = NULL;
// Function to create a new node
struct Node* createNode(int data) {
struct Node* newNode = (struct Node*)malloc(sizeof(struct Node));
if (newNode == NULL) {
printf("Memory allocation failed!\n");
exit(1);
}
newNode->data = data;
newNode->next = NULL;
return newNode;
}
// Function to insert at the beginning
void insertAtBeginning(int data) {
struct Node* newNode = createNode(data);
newNode->next = head;
head = newNode;
}
// Function to insert at the end
void insertAtEnd(int data) {
struct Node* newNode = createNode(data);
if (head == NULL) {
head = newNode;
} else {
struct Node* temp = head;
while (temp->next != NULL) {
temp = temp->next;
}
temp->next = newNode;
}
}
// Function to insert at a given position
void insertAtPosition(int data, int position) {
if (position == 0) {
insertAtBeginning(data);
} else {
struct Node* newNode = createNode(data);
struct Node* temp = head;
for (int i = 0; i < position - 1 && temp != NULL; i++) {
temp = temp->next;
}
if (temp == NULL) {
printf("Invalid position!\n");
} else {
newNode->next = temp->next;
temp->next = newNode;
}
}
}
// Function to delete from the beginning
void deleteFromBeginning() {
if (head == NULL) {
printf("List is empty!\n");
} else {
struct Node* temp = head;
head = head->next;
free(temp);
}
}
// Function to delete from the end
void deleteFromEnd() {
if (head == NULL) {
printf("List is empty!\n");
} else if (head->next == NULL) {
free(head);
head = NULL;
} else {
struct Node* temp = head;
while (temp->next->next != NULL) {
temp = temp->next;
}
free(temp->next);
temp->next = NULL;
}
}
// Function to delete from a given position
void deleteFromPosition(int position) {
if (head == NULL) {
printf("List is empty!\n");
} else if (position == 0) {
deleteFromBeginning();
} else {
struct Node* temp = head;
for (int i = 0; i < position - 1 && temp != NULL; i++) {
temp = temp->next;
}
if (temp == NULL || temp->next == NULL) {
printf("Invalid position!\n");
} else {
struct Node* toDelete = temp->next;
temp->next = toDelete->next;
free(toDelete);
}
}
}
// Function to search for an element
int search(int data) {
struct Node* temp = head;
int position = 0;
while (temp != NULL) {
if (temp->data == data) {
return position;
}
temp = temp->next;
position++;
}
return -1; // Element not found
}
// Function to display the linked list
void display() {
struct Node* temp = head;
printf("List: ");
while (temp != NULL) {
printf("%d ", temp->data);
temp = temp->next;
}
printf("\n");
}
int main() {
// Example usage:
insertAtEnd(10);
insertAtBeginning(20);
insertAtPosition(30, 1);
insertAtEnd(40);
display();
deleteFromBeginning();
deleteFromEnd();
deleteFromPosition(1);
display();
printf("Position of 30: %d\n", search(30));
return 0;
}
2. Difference Between Linear and Non-linear Data Structures:
● Linear:
○ Elements are arranged in a sequence.
○ Access to elements is sequential (e.g., arrays, linked lists, stacks, queues).
● Non-linear:
○ Elements are not arranged in a sequence.
○ Access to elements is not sequential (e.g., trees, graphs).
● Static:
○ Fixed size at compile time.
○ Memory allocation is done during compilation.
○ Examples: Arrays.
● Non-static:
○ Size can change dynamically during runtime.
○ Memory allocation is done during runtime.
○ Examples: Linked lists.
3. Advantages, Applications, and Disadvantages of Linked Lists:
● Advantages:
○ Dynamic size: Can grow or shrink as needed.
○ Efficient insertions and deletions (especially at the beginning).
○ Can be used to implement other data structures like stacks, queues, and
graphs.
● Applications:
○ Implementing dynamic memory allocation.
○ Representing data with variable-length records.
○ Implementing symbol tables in compilers.
○ Implementing file systems.
● Disadvantages:
○ Random access is not efficient.
○ Extra memory is required for pointers.
4. Different Types of Linked Lists:
● Singly Linked List: Each node points to the next node.
● Doubly Linked List: Each node points to both the next and previous nodes.
● Circular Linked List: The last node points back to the first node.
● Circular Doubly Linked List: A combination of circular and doubly linked lists.
5. C Program to Reverse a Linked List:
#include <stdio.h>
#include <stdlib.h>
struct Node {
int data;
struct Node* next;
};
struct Node* head = NULL;
// Function to reverse the linked list
void reverseList() {
struct Node* prev = NULL;
struct Node* current = head;
struct Node* next;
while (current != NULL) {
next = current->next;
current->next = prev;
prev = current;
current = next;
}
head = prev;
}
// ... (other functions from the previous code) ...
int main() {
// ... (same as in the previous code) ...
reverseList();
display();
return 0;
}
6. Comparison Between Linked List and Linear Array:
Feature Linked List Array
Memory Allocation Dynamic Static
Insertion/Deletion Efficient at beginning/end, Inefficient at beginning/end,
less efficient in the middle efficient in the middle
Random Access Inefficient Efficient
Memory Usage More memory overhead due Less memory overhead
to pointers
● When to use Linked List:
○ When frequent insertions and deletions are required.
○ When the size of the data structure is not known in advance.
○ When random access is not critical.
● When to use Array:
○ When random access is frequent.
○ When memory usage is a concern.
○ When the size of the data structure is known in advance.