Project 1 - Creation of user defined data type to implement the user interfaces for working with ‘Set’ (Mathematical Set theory) using Linked List
AIM:
To create user defined data type to implement the user interfaces for working with 'Set' (Mathematical Set Theory).
Objective:
- Using c programming implementation of interface for mathematical set theory
- Using linked list method give two list of data as a input to get the output as union and intersection for given list of data.
Theory:
Mathematicall set theory
Set theory is a branch of mathematics that deal with the properties of well defined collection of objects, which may or may not be of a mathematical nature, such as numbers or functions.
Union of Sets
It is denoted as A`cup`B, list the elements in set A and set B or the elements in both set A and set B. For example, {1,3}`cup`{1,4} = {1,3,4}.
Intersection of sets
It is denoted as A`cap`B, list the elements which are common in set A and set B. For example, {1,2}`cap`{2,4} = {2}.
Linked List
Linked list is a linear data structure, the elements are linked using pointers. They includes a series of connected nodes. here each stores the data and the address of the next node. A linked list is represented by pointer to the first node of the linked list. The first node is called the head. If linked list is empty, then the value of the head poins to null.
Each node in a list consist of at least two parts:
- A data type (We can store integer, strings or any type of data).
- Pointer (or reference) to the next node (connects one node to another) or an address of another node.

Inserting a node
A node can be inserted in 3 ways.
- At the front of linked list.
- At the given node.
- At the end of linked list.
1. At the front of linked list
The new node is always added before the head of the given linked list. And newly added node becomes the new head of the linked list. For example if the given linked list is 10->15->20 ->25 and we add an item 5 at the front, then the linked list becomes 5->10->15->20->25.let us call the function that adds at the front of the list is push(). The push() must receive a pointer to the head pointer, because push must change the head pointer to point to the new node.

Program:
/* Given a reference (pointer to pointer) to the head of a list and an int, inserts a new node on the front of the list. */void push(struct Node** head_ref, int new_data){ /* 1. allocate node */ struct Node* new_node = (struct Node*) malloc(sizeof(struct Node)); /* 2. put in the data */ new_node->data = new_data; /* 3. Make next of new node as head */ new_node->next = (*head_ref); /* 4. move the head to point to the new node */ (*head_ref) = new_node;}We have pointer to the head and we can directly attach a node and change the pointer. So the time complexity of inserting a node at head position is 0(1) as it does a constant amount of work.
2. At the given node
We have given pointer to node and the new node is inserted after the given node.

Program
/* Given a node prev_node, insert a new node after the givenprev_node */void insertAfter(struct Node* prev_node, int new_data){ /*1. check if the given prev_node is NULL */ if (prev_node == NULL) { printf("the given previous node cannot be NULL"); return; } /* 2. allocate new node */ struct Node* new_node = (struct Node*)malloc(sizeof(struct Node)); /* 3. put in the data */ new_node->data = new_data; /* 4. Make next of new node as next of prev_node */ new_node->next = prev_node->next; /* 5. move the next of prev_node as new_node */ prev_node->next = new_node;}Time complexity of insert after () is 0(n). As it depends on n where n is the size of the linked list.
3. Add node at the end.
The node is always added after the last node of the given linked list. For example if the given linked list is 5->10->15->20->25 and we add an item 30 at the end, then the linked list becomes 5->10->15->20->25->30.Since the linked list is typically represented by the head of it, we have to traverse the list till the end and change the next to the last node to a new node. 
Program
/* Given a reference (pointer to pointer) to the head of a list and an int, appends a new node at the end */void append(struct Node** head_ref, int new_data){ /* 1. allocate node */ struct Node* new_node = (struct Node*) malloc(sizeof(struct Node)); struct Node *last = *head_ref; /* used in step 5*/ /* 2. put in the data */ new_node->data = new_data; /* 3. This new node is going to be the last node, so make next of it as NULL*/ new_node->next = NULL; /* 4. If the Linked List is empty, then make the new node as head */ if (*head_ref == NULL) { *head_ref = new_node; return; } /* 5. Else traverse till the last node */ while (last->next != NULL) last = last->next; /* 6. Change the next of last node */ last->next = new_node; return; }Singly Linked list: It is the most basic linked list in which traversal is unidirectional i.e. from head node to the last node. Doubly Linked list: In this linked list traversal can be done in both ways and hence it requires an extra pointer. Circular Linked list: This linked list is unidirectional but in this list, the last node points to the first i.e. the head node and hence it becomes circular in nature. Circular doubly Linked list: The circular doubly linked list is a combination of the doubly linked list and the circular linked list. It means that this linked list is bidirectional and contains two pointers and the last pointer points to the first pointer.
Linked list are commonly used for:
- Linked list are mostly used because of their effective insertion and deletion.
- Insertion and deletion in the linked list are very effective and take less time complexity as compared to the array data strucure.
- This data structure is simple and can be also used to implement a stack, queues and other abstract data structures
Application of Linked lists:
- Linked lists are used to implement stacks and queues.
- It is used for the various representations of trees and graphs.
- It is used in dynamic memory allocation.
- It is used for representing sparse matrices.
- It is used for manipulation of polynomials.
- It is also used for performing arithmatic operations on long integers.
- It is used for finding paths in networks.
Applications of Linked list in the real world:
- The list of song in music player are linked to the previous and next songs.
- In a web browser, previous and next web page URLs are linked through the previous and next buttons.
- In image viewer, the previous and next images are linked with the help of previous and next buttons.
- Switching between two applications is carried out by using "alt+tab" in windows and "cmd+tab" in mac book. It requires the functionality of circular linked list.
- In mobile phones, we save the conacts of the people. the newly entered contact details will be placed at the correct alphabetical order. This can be achieved by linked list to set contact at correct alphabetical position.
- The modification that we are made in the documents are actually created as nodes in doubly linked list. We can can simply use the undo option by pressing Ctrl+Z to modify the contents. It is done by the functionality of linked list.
Advantages
- Insertion and deletion in linked lists are very efficient.
- Linked list can be expanded in constant time.
- For implementation of stacks and queues and for representation of trees and graphs.
- Linked lists are used for dynamic memory allocation which means effective memory utilization hence no memory wastage.
Disadvantages
- Use of pointers is more in linked lists hence complex and requires more memory.
- searching an element is costly and requires 0(n) time complexity.
- Traversing is more time consuming and reverse traversing is not possible in singly linked lists.
- Random access is not possible due to dynamic memory allocation.
From above method we are going to use inserting node at the front linked list./* Program to find union and inyersection using linked list */
#include <stdio.h>
#include <stdlib.h>
// A structure of linked list node
struct node
{
int data;
struct node *next;
} *LLOne, *LLTwo, *unionLL, *intersectionLL;
void initialize()
{
LLOne = LLTwo = NULL;
}
//Given a Inserts a node in front of a singly linked list.
void insert(struct node **head, int num)
{
// Create a new Linked List node
struct node* newNode = (struct node*) malloc(sizeof(struct node));
newNode->data = num;
// Next pointer of new node will point to head node of linked list
newNode->next = *head;
//make new node as new head of linked list
*head = newNode;
}
// Searches an element in Linked List by linearly traversing from head to tail
int search(struct node *head, int num)
{
while (head != NULL)
{
if (head->data == num)
{
return 1;
}
head = head->next;
}
return 0;
}
//Returns the union of two given linked list
struct node* findunion(struct node *LLOne, struct node *LLTwo)
{
unionLL = NULL;
// Add all nodes of first Linked List to unionLL
struct node *temp = LLOne;
while(temp != NULL)
{
insert(&unionLL, temp->data);
temp = temp->next;
}
// Insert those nodes of LLTwo which is not present in LLOne
while(LLTwo != NULL)
{
if(!search(LLOne, LLTwo->data))
{
insert(&unionLL, LLTwo->data);
}
LLTwo = LLTwo->next;
}
return unionLL;
}
//Returns the Linked List which contains common nodes of two given linked list
struct node* intersection(struct node *LLOne, struct node *LLTwo)
{
intersectionLL = NULL;
//Search every element of LLOne in LLTwo, If found then add it to intersection List
while(LLOne != NULL)
{
if(search(LLTwo, LLOne->data))
{
insert(&intersectionLL, LLOne->data);
}
LLOne = LLOne->next;
}
return intersectionLL;
}
//Prints a linked list from head node till tail node
void printLinkedList(struct node *nodePtr)
{
while (nodePtr != NULL)
{
printf("%d", nodePtr->data);
nodePtr = nodePtr->next;
if(nodePtr != NULL)
printf("-->");
}
}
int main()
{
int i, LLOneCount, LLTwoCount, temp;
initialize();
//Creating First linked List
printf("Enter number of nodes in first Linked List\n");
fflush(stdout);
scanf("%d", &LLOneCount);
printf("Enter %d integers\n", LLOneCount);
for(i=0; i<LLOneCount; i++)
{
scanf("%d", &temp);
insert(&LLOne, temp);
}
printLinkedList(LLOne);
printf("\nEnter number of nodes in second Linked List\n");
fflush(stdout);
scanf("%d", &LLTwoCount);
printf("Enter %d integers\n", LLTwoCount);
for(i=0; i<LLTwoCount; i++)
{
scanf("%d", &temp);
insert(&LLTwo, temp);
}
printLinkedList(LLTwo);
//printing Union of two given linked list
findunion(LLOne, LLTwo);
intersection(LLOne, LLTwo);
printf("\nUnion Linked List\n");
printLinkedList(unionLL);
printf("\nIntersection Linked List\n");
printLinkedList(intersectionLL);
return 0;
}
Output:

Conclusion:
1.In this way we have successfully implemented Linked list method for user defined data for working with det theory.
2. using linked list method we find out union and intersection of data which we took it from user.
3. Also dicussed application and real time application of linked list method.