428 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
			
		
		
	
	
			428 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
| ---
 | |
| title: Data Structure Linked List
 | |
| ---
 | |
| Just like a garland is made with flowers, a linked list is made up of nodes. We call every flower on this particular garland to be a node. And each of the node points to the next node in this list as well as it has data (here it is type of flower).
 | |
| 
 | |
| ## Types
 | |
| 
 | |
| 1.  Singly Linked List
 | |
| 
 | |
| Singly linked lists contain nodes which have a `data` field as well as a `next` field, which points to the next node in the sequence. Operations that can be performed on singly linked lists are insertion, deletion and traversal.
 | |
| 
 | |
| `
 | |
| 
 | |
|     Singly Link List
 | |
| 
 | |
| * * *
 | |
| 
 | |
|        head
 | |
|         |
 | |
|         |
 | |
|       +-----+--+      +-----+--+      +-----+------+
 | |
|       |  1  |o----->  |  2  |o----->  |  3  | NULL |
 | |
|       +-----+--+      +-----+--+      +-----+------+
 | |
| 
 | |
| `
 | |
| 
 | |
| Application
 | |
| 
 | |
| Internal implementation of CPython, the frames and evaluated variables are kept on a stack.
 | |
| 
 | |
| For this we need to iterate only forward aur get the head, therefore singly linked-list is used.
 | |
| 
 | |
| 1.  Doubly Linked List
 | |
| 
 | |
| Doubly linked lists contain node which have `data` field, `next` field and another link field `prev` pointing to the previous node in the sequence.
 | |
| 
 | |
| `
 | |
| 
 | |
| Doubly Linked List
 | |
| 
 | |
| * * *
 | |
| 
 | |
|               head
 | |
|                |
 | |
|                |
 | |
|       +------+-----+--+    +--+-----+--+       +-----+------+
 | |
|       |      |     |o------>  |     |o------>  |     |      |
 | |
|       | NULL |  1  |          |  2  |          |  3  | NULL |
 | |
|       |      |     |  <------o|     |  <------o|     |      |
 | |
|       +------+-----+--+    +--+-----+--+       +-----+------+
 | |
| 
 | |
| `
 | |
| 
 | |
| Application
 | |
| 
 | |
| The browser cache which allows you to hit the BACK and FORWARD button. Here we need to maintain a doubly linked list, with `URLs` as data field, to allow access in both direction. To go to previous URL we will use `prev` field and to go to next page we will use `next` field.
 | |
| 
 | |
| 1.  Circular Linked List
 | |
| 
 | |
| Circular linked lists is a singly linked list in which last node, `next` field points to first node in the sequence.
 | |
| 
 | |
| `
 | |
| 
 | |
| Circular Linked List
 | |
| 
 | |
| * * *
 | |
| 
 | |
|          head
 | |
|           |
 | |
|           |
 | |
|         +-----+--+      +-----+--+      +-----+--+
 | |
| 
 | |
| --> | 1 |o-----> | 2 |o-----> | 3 |o----  
 | |
| | +-----+--+ +-----+--+ +-----+--+ |  
 | |
| | |
 | |
| 
 | |
| * * *
 | |
| 
 | |
| `
 | |
| 
 | |
| **Application**
 | |
| 
 | |
| Timesharing problem solved by the operating system.
 | |
| 
 | |
| In a timesharing environment, the operating system must maintain a list of present users and must alternately allow each user to use a small portion of CPU time, one user at a time. The operating system will pick a user, let him/her use a small amount of CPU time and then move on to the next user.
 | |
| 
 | |
| For this application, there should be no NULL pointers unless there is absolutely no one requesting CPU time, i.e list is empty.
 | |
| 
 | |
| ## Basic Operations
 | |
| 
 | |
| 1.  Insertion
 | |
| 
 | |
| To add a new element to the list.
 | |
| 
 | |
| `
 | |
| 
 | |
| Insertion at the beginning
 | |
| 
 | |
| * * *
 | |
| 
 | |
| *   Create a new node with given data.
 | |
| *   Point new node's `next` to old `head`.
 | |
| *   Point `head` to this new node.
 | |
| 
 | |
| Insertion in the middle/end
 | |
| 
 | |
| * * *
 | |
| 
 | |
| Insertion after node X.
 | |
| 
 | |
| *   Create a new node with given data.
 | |
| *   Point new node's `next` to old X's `next`.
 | |
| *   Point X's `next` to this new node.  
 | |
|     `
 | |
| 
 | |
| **Time Complexity: O(1)**
 | |
| 
 | |
| 1.  Deletion
 | |
| 
 | |
| To delete existing element from the list.
 | |
| 
 | |
| `
 | |
| 
 | |
| Deletion at the beginning
 | |
| 
 | |
| * * *
 | |
| 
 | |
| *   Get the node pointed by `head` as Temp.
 | |
| *   Point `head` to Temp's `next`.
 | |
| *   Free memory used by Temp node.
 | |
| 
 | |
| Deletion in the middle/end
 | |
| 
 | |
| * * *
 | |
| 
 | |
| Deletion after node X.
 | |
| 
 | |
| *   Get the node pointed by `X` as Temp.
 | |
| *   Point X's `next` to Temp's `next`.
 | |
| *   Free memory used by Temp node.  
 | |
|     `
 | |
| 
 | |
| **Time Complexity: O(1)**
 | |
| 
 | |
| 1.  Traversing
 | |
| 
 | |
| To travel across the list.
 | |
| 
 | |
| `
 | |
| 
 | |
| Traversal
 | |
| 
 | |
| * * *
 | |
| 
 | |
| *   Get the node pointed by `head` as Current.
 | |
| *   Check if Current is not null and display it.
 | |
| *   Point Current to Current's `next` and move to above step.  
 | |
|     `
 | |
| 
 | |
| **Time Complexity: O(n) // Here n is size of link-list**
 | |
| 
 | |
| ## Implementation
 | |
| 
 | |
| ### C++ implementation of singly linked list
 | |
| 
 | |
|     // Header files
 | |
|     #include <iostream>
 | |
| 
 | |
|     struct node
 | |
|     {
 | |
|         int data;
 | |
|         struct node *next;
 | |
|     };
 | |
| 
 | |
|     // Head pointer always points to first element of the linked list
 | |
|     struct node *head = NULL;
 | |
| 
 | |
| #### Printing data in each node  
 | |
| 
 | |
|     // Display the list
 | |
|     void printList()
 | |
|     {
 | |
|         struct node *ptr = head;
 | |
| 
 | |
|         // Start from the beginning
 | |
|     while(ptr != NULL)
 | |
|     {
 | |
|         std::cout << ptr->data << " ";
 | |
|         ptr = ptr->next;
 | |
|     }
 | |
| 
 | |
|     std::cout << std::endl;
 | |
|     }
 | |
| 
 | |
| #### Insertion at the beginning  
 | |
| 
 | |
|     // Insert link at the beginning
 | |
|     void insertFirst(int data)
 | |
|     {
 | |
|         // Create a new node
 | |
|         struct node *new_node = new struct node;
 | |
| 
 | |
|         new_node->data = data;
 | |
| 
 | |
|     // Point it to old head
 | |
|     new_node->next = head;
 | |
| 
 | |
|     // Point head to new node
 | |
|     head = new_node;
 | |
| 
 | |
|     std::cout << "Inserted successfully" << std::endl;
 | |
|     }
 | |
| 
 | |
| #### Deletion at the beginning  
 | |
| 
 | |
|     // Delete first item
 | |
|     void deleteFirst()
 | |
|     {
 | |
|         // Save reference to head
 | |
|         struct node *temp = head;
 | |
| 
 | |
|         // Point head to head's next
 | |
|     head = head->next;
 | |
| 
 | |
|     // Free memory used by temp
 | |
|     temp = NULL:
 | |
|     delete temp;
 | |
| 
 | |
|     std::cout << "Deleted successfully" << std::endl;
 | |
|     }
 | |
| 
 | |
| #### Size  
 | |
| 
 | |
|     // Find no. of nodes in link list
 | |
|     void size()
 | |
|     {
 | |
|         int length = 0;
 | |
|         struct node *current;
 | |
| 
 | |
|         for(current = head; current != NULL; current = current->next)
 | |
|     {
 | |
|         length++;
 | |
|     }
 | |
| 
 | |
|     std::cout << "Size of Linked List is " << length << std::endl;
 | |
|     }
 | |
| 
 | |
| #### Searching  
 | |
| 
 | |
|     // Find node with given data
 | |
|     void find(int data){
 | |
| 
 | |
|         // Start from the head
 | |
|     struct node* current = head;
 | |
| 
 | |
|     // If list is empty
 | |
|     if(head == NULL)
 | |
|     {
 | |
|         std::cout << "List is empty" << std::endl;
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     // Traverse through list
 | |
|     while(current->data != data){
 | |
| 
 | |
|         // If it is last node
 | |
|         if(current->next == NULL){
 | |
|             std::cout << "Not Found" << std::endl;
 | |
|             return;
 | |
|         }
 | |
|         else{
 | |
|             // Go to next node
 | |
|             current = current->next;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     // If data found
 | |
|     std::cout << "Found" << std::endl;
 | |
|     }
 | |
| 
 | |
| #### Deletion after a node  
 | |
| 
 | |
|     // Delete a node with given data
 | |
|     void del(int data){
 | |
| 
 | |
|         // Start from the first node
 | |
|     struct node* current = head;
 | |
|     struct node* previous = NULL;
 | |
| 
 | |
|     // If list is empty
 | |
|     if(head == NULL){
 | |
|         std::cout << "List is empty" << std::endl;
 | |
|         return ;
 | |
|     }
 | |
| 
 | |
|     // Navigate through list
 | |
|     while(current->data != data){
 | |
| 
 | |
|         // If it is last node
 | |
|         if(current->next == NULL){
 | |
|             std::cout << "Element not found" << std::endl;
 | |
|             return ;
 | |
|         }
 | |
|         else {
 | |
|             // Store reference to current node
 | |
|             previous = current;
 | |
|             // Move to next node
 | |
|             current = current->next;
 | |
|         }
 | |
| 
 | |
|     }
 | |
| 
 | |
|     // Found a match, update the node
 | |
|     if(current == head) {
 | |
|         // Change head to point to next node
 | |
|         head = head->next;
 | |
|     }
 | |
|     else {
 | |
|         // Skip the current node
 | |
|         previous->next = current->next;
 | |
|     }
 | |
| 
 | |
|     // Free space used by deleted node
 | |
|     current = NULL;
 | |
|     delete current;
 | |
|     std::cout << "Deleted succesfully" << std::endl;
 | |
|     }
 | |
| 
 | |
|  <a href='https://repl.it/CXVt/1' target='_blank' rel='nofollow'>Run Code</a>
 | |
| 
 | |
| ### Python Implementation of Singly Linked List  
 | |
| 
 | |
|     class Node(object):
 | |
|         # Constructor
 | |
|         def __init__(self, data=None, next=None):
 | |
|             self.data = data
 | |
|             self.next = next
 | |
| 
 | |
|         # Function to get data
 | |
|     def get_data(self):
 | |
|         return self.data
 | |
| 
 | |
|     # Function to get next node
 | |
|     def get_next(self):
 | |
|         return self.next
 | |
| 
 | |
|     # Function to set next field
 | |
|     def set_next(self, new_next):
 | |
|         self.next = new_next
 | |
|     class LinkedList(object):
 | |
|         def __init__(self, head=None):
 | |
|             self.head = head
 | |
| 
 | |
| #### Insertion  
 | |
| 
 | |
|         # Function to insert data
 | |
|     def insert(self, data):
 | |
|         # new_node is a object of class Node
 | |
|         new_node = Node(data)
 | |
|         new_node.set_next(self.head)
 | |
|         self.head = new_node
 | |
|         print("Node with data " + str(data) + " is created succesfully")
 | |
| 
 | |
| #### Size  
 | |
| 
 | |
|         # Function to get size
 | |
|     def size(self):
 | |
|         current = self.head
 | |
|         count = 0
 | |
|         while current:
 | |
|             count += 1
 | |
|             current = current.get_next()
 | |
|         print("Size of link list is " + str(count))
 | |
| 
 | |
| #### Searching  
 | |
| 
 | |
|         # Function to search a data
 | |
|     def search(self, data):
 | |
|         current = self.head
 | |
|         found = False
 | |
|         while current and found is False:
 | |
|             if current.get_data() == data:
 | |
|                 found = True
 | |
|             else:
 | |
|                 current = current.get_next()
 | |
|         if current is None:
 | |
|             print("Node with data " + str(data) + " is not present")
 | |
|         else:
 | |
|             print("Node with data " + str(data) + " is found")
 | |
| 
 | |
| #### Deletion after a node  
 | |
| 
 | |
|         # Function to delete a node with data
 | |
|     def delete(self, data):
 | |
|         current = self.head
 | |
|         previous = None
 | |
|         found = False
 | |
|         while current and found is False:
 | |
|             if current.get_data() == data:
 | |
|                 found = True
 | |
|             else:
 | |
|                 previous = current
 | |
|                 current = current.get_next()
 | |
|         if current is None:
 | |
|             print("Node with data " + str(data) + " is not in list")
 | |
|         elif previous is None:
 | |
|             self.head = current.get_next()
 | |
|             print("Node with data " + str(data) + " is deleted successfully")
 | |
|         else:
 | |
|             previous.set_next(current.get_next())
 | |
|             print("Node with data " + str(data) + " is deleted successfully")
 | |
| 
 | |
|  <a href='https://repl.it/CVq3/2' target='_blank' rel='nofollow'>Run Code</a>
 | |
| 
 | |
| **Advantages**
 | |
| 
 | |
| 1.  Linked lists are a dynamic data structure, which can grow and shrink, allocating and deallocating memory while the program is running.
 | |
| 2.  Insertion and deletion of node are easily implemented in a linked list at any position.
 | |
| 
 | |
| **Disadvantages**
 | |
| 
 | |
| 1.  They use more memory than arrays because of the memory used by their pointers (`next` and `prev`).
 | |
| 2.  Random access is not possible in linked list. We have to access nodes sequentially.
 | |
| 3.  It's more complex than array. If a language supports array bound check automatically, Arrays would serve you better.
 | |
| 
 | |
| #### Note
 | |
| 
 | |
| We have to use free() in C and delete in C++ to free the space used by deleted node, whereas, in Python and Java free space is collected automatically by garbage collector. |