0% found this document useful (0 votes)
38 views

Advanced Algorithms & Data Structures: Lecturer: Karimzhan Nurlan Berlibekuly

The document provides information about linked lists and their implementation. It discusses single linked lists and double linked lists. It defines key concepts like nodes, data types, and basic linked list operations. It provides examples of implementing a simple linked list in C/C++ with three nodes, and includes code to traverse and insert nodes into the linked list.

Uploaded by

Naski Kuafni
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
38 views

Advanced Algorithms & Data Structures: Lecturer: Karimzhan Nurlan Berlibekuly

The document provides information about linked lists and their implementation. It discusses single linked lists and double linked lists. It defines key concepts like nodes, data types, and basic linked list operations. It provides examples of implementing a simple linked list in C/C++ with three nodes, and includes code to traverse and insert nodes into the linked list.

Uploaded by

Naski Kuafni
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
You are on page 1/ 47

ADVANCED

ALGORITHMS &
DATA STRUCTURES
Lecture-04
Data Structures
Single Linked List
Double Linked List

Lecturer: Karimzhan Nurlan Berlibekuly


[email protected]
Data Structures
Basic Concepts of Data Structure
Data Structure is a way of collecting and organizing
data in such a way that we can perform operations
on these data in an effective way.

Data Structures is about rendering data elements in


terms of some relationship, for better organization
and storage.

For example, we have data player's name "Hitesh"


and age 26. Here "Hitesh" is of String data type and
26 is of integer data type.
Basic Concepts of Data Structure
We can organize this data as a record
like Player record. Now we can collect and store
player's records in a file or database as a data
structure. For example: "Gayle" 30, "Sachin" 31,
"Parth" 33

In simple language, Data Structures are structures


programmed to store ordered data, so that various
operations can be performed on it easily.
Data Definition
Data Definition defines a particular data with following
characteristics.
• Atomic − Definition should define a single concept
• Traceable − Definition should be be able to be
mapped to some data element.
• Accurate − Definition should be unambiguous.
• Clear and Concise − Definition should be
understandable.
Data Object
Data Object represents an object having a data.
Data Type
Data type is way to classify various types of data such
as integer, string etc. which determines the values that
can be used with the corresponding type of data, the
type of operations that can be performed on the
corresponding type of data. Data type of two types −
• Built-in Data Type
• Derived Data Type
Built-in Data Type
Those data types for which a language has built-in
support are known as Built-in Data types. For example,
most of the languages provides following built-in data
types.
• Integers
• Boolean (true, false)
• Floating (Decimal numbers)
• Character and Strings
Derived Data Type
Those data types which are implementation
independent as they can be implemented in one or
other way are known as derived data types. These
data types are normally built by combination of
primary or built-in data types and associated
operations on them. For example −
• List
• Array
• Stack
• Queue
Basic Operations
The data in the data structures are processed by certain
operations. The particular data structure chosen largely
depends on the frequency of the operation that needs
to be performed on the data structure.
• Traversing
• Searching
• Insertion
• Deletion
• Sorting
• Merging
Linked List
Like arrays, Linked List is a linear data structure.
Unlike arrays, linked list elements are not stored at a
contiguous location; the elements are linked using
pointers.
Why Linked List?
Arrays can be used to store linear data of similar types,
but arrays have the following limitations.
1) The size of the arrays is fixed: So we must know the
upper limit on the number of elements in advance. Also,
generally, the allocated memory is equal to the upper
limit irrespective of the usage.
2) Inserting a new element in an array of elements is
expensive because the room has to be created for the
new elements and to create room existing elements
have to be shifted.
Why Linked List?
For example, in a system, if we maintain a sorted list of
IDs in an array id[].
id[] = [1000, 1010, 1050, 2000, 2040].
And if we want to insert a new ID 1005, then to maintain
the sorted order, we have to move all the elements after
1000 (excluding 1000).

Deletion is also expensive with arrays until unless some


special techniques are used. For example, to delete 1010
in id[], everything after 1010 has to be moved.
Linked List vs Array
Linked List vs Array

Advantages over arrays


1) Dynamic size
2) Ease of insertion/deletion
Linked List
Drawbacks:
1) Random access is not allowed. We have to access
elements sequentially starting from the first node. So we
cannot do binary search with linked lists efficiently with
its default implementation. Read about it here.
2) Extra memory space for a pointer is required with
each element of the list.
3) Not cache friendly. Since array elements are
contiguous locations, there is locality of reference which
is not there in case of linked lists.
Linked List. Representation:
A linked list is represented by a pointer to the first node
of the linked list. The first node is called the head. If the
linked list is empty, then the value of the head is NULL.
Each node in a list consists of at least two parts:
1) data
2) Pointer (Or Reference) to the next node
In C, we can represent a node using structures. Below is
an example of a linked list node with integer data.
In Java or C#, LinkedList can be represented as a class
and a Node as a separate class. The LinkedList class
contains a reference of Node class type.
Linked List. Representation:

class Node {
public:
int data;
Node* next;
};
Linked List. Representation:
First Simple Linked List in C Let us create a simple linked list with 3 nodes.
#include <bits/stdc++.h>
using namespace std; // allocate 3 nodes in the heap
head = new Node();
class Node { second = new Node();
public: third = new Node();
int data;
Node* next; head->data = 1; // assign data in first node
}; head->next = second; // Link first node
with
// Program to create a simple linked
// list with 3 nodes second->data = 2;
int main() second->next = third;
{
Node* head = NULL; third->data = 3; // assign data to third
Node* second = NULL; node
Node* third = NULL; third->next = NULL;

return 0;
}
Linked List. Representation:
First Simple Linked List in C Let us create a simple linked list with 3 nodes.

/* data has been assigned to the data part of the third


block (block pointed by third). And next pointer
of the third block is made NULL to indicate
that the linked list is terminated here.

We have the linked list ready.

head
|
|
+---+---+ +---+---+ +----+------+
| 1 | o----->| 2 | o-----> | 3 | NULL |
+---+---+ +---+---+ +----+------+

Note that only the head is sufficient to represent


the whole list. We can traverse the complete
list by following the next pointers. */
Linked List Traversal // Driver code
int main()
{
// A simple C++ program Node* head = NULL;
//for traversal of a linked list Node* second = NULL;
#include <bits/stdc++.h> Node* third = NULL;
using namespace std;
// allocate 3 nodes in the heap
head = new Node();
class Node { second = new Node();
public: third = new Node();
int data;
Node* next; head->data = 1; // assign data in first node
}; head->next = second; // Link first node with
second
// This function prints contents of linked list
second->data = 2; // assign data to second node
// starting from the given node second->next = third;
void printList(Node* n)
{ third->data = 3; // assign data to third node
while (n != NULL) { third->next = NULL;
cout << n->data << " ";
n = n->next; printList(head);
}
return 0;
}
}
Linked List. Insert Node
Add a node at the front
Linked List. Insert Node
/* This function is in LinkedList class. Inserts a Add a node at the front
new Node at front of the list. This method is
defined inside LinkedList class shown above
*/
public void push(int new_data)
{
/* 1 & 2: Allocate the Node &
Put in the data*/
Node new_node = new Node(new_data);

/* 3. Make next of new Node as head */


new_node.next = head;

/* 4. Move the head to point to new Node */


head = new_node;
}
Linked List. Insert Node
Add a node after a given node
Linked List. Insert Node
Add a node after a given node

/* This function is in LinkedList class.


/* 2. Allocate the Node &
Inserts a new node after the given
3. Put in the data*/
prev_node. This method is
Node new_node = new Node(new_data);
defined inside LinkedList class shown above
*/
/* 4. Make next of new Node as next of
public void insertAfter(Node prev_node, int
prev_node */
new_data)
new_node.next = prev_node.next;
{
/* 1. Check if the given Node is null */
/* 5. make next of prev_node as new_node
if (prev_node == null)
*/
{
prev_node.next = new_node;
System.out.println("The given previous
}
node cannot be null");
return;
}
Linked List. Insert Node
Add a node at the end
Linked List. Insert NodeAdd a node at the end
/* Appends a new node at the end. This
method is
defined inside LinkedList class shown above /* 4. This new node is going to be the last
*/ node, so
public void append(int new_data) make next of it as null */
{ new_node.next = null;
/* 1. Allocate the Node &
2. Put in the data /* 5. Else traverse till the last node */
3. Set next as null */ Node last = head;
Node new_node = new Node(new_data); while (last.next != null)
last = last.next;
/* 4. If the Linked List is empty, then make
the /* 6. Change the next of last node */
new node as head */ last.next = new_node;
if (head == null) return;
{ }
head = new Node(new_data);
return;
}
Linked List. Deleting a node
Linked List. Deleting a node
/* Given a reference (pointer to pointer) to the // Search for the key to be deleted, keep
head of a list track of the
and a key, deletes the first occurrence of key // previous node as we need to change
in linked list */ 'prev->next'
void deleteNode(struct Node **head_ref, int while (temp != NULL && temp->data != key)
key) {
{ prev = temp;
// Store head node temp = temp->next;
struct Node* temp = *head_ref, *prev; }

// If head node itself holds the key to be // If key was not present in linked list
deleted if (temp == NULL) return;
if (temp != NULL && temp->data == key)
{ // Unlink the node from linked list
*head_ref = temp->next; // Changed prev->next = temp->next;
head
free(temp); // free old head free(temp); // Free memory
return; }
}
Double Linked List
A Doubly Linked List (DLL) contains an extra pointer, typically
called previous pointer, together with next pointer and data
which are there in singly linked list.
Double Linked List
// Class for Doubly Linked List
public class DLL {
Node head; // head of list

/* Doubly Linked list Node*/


class Node {
int data;
Node prev;
Node next;

// Constructor to create a new node


// next and prev is by default initialized as null
Node(int d) { data = d; }
}
}
Double Linked List
Advantages over singly linked list
1) A DLL can be traversed in both forward and backward direction.
2) The delete operation in DLL is more efficient if pointer to the node to be
deleted is given.
3) We can quickly insert a new node before a given node.
In singly 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, we can get the
previous node using previous pointer.

Disadvantages over singly linked list


1) Every node of DLL Require extra space for an previous pointer. It is possible to
implement DLL with single pointer though (See this and this).
2) All operations require an extra pointer previous to be maintained. For
example, in insertion, we need to modify previous pointers together with next
pointers. For example in following functions for insertions at different positions,
we need 1 or 2 extra steps to set previous pointer.
Double Linked List
Insertion
A node can be added in four ways
1) At the front of the DLL
2) After a given node.
3) At the end of the DLL
4) Before a given node.
Double Linked List
1) Add a node at the front: (A 5 steps process)
The new node is always added before the head of the given Linked List. And newly
added node becomes the new head of DLL. For example if the given Linked List is
10152025 and we add an item 5 at the front, then the Linked List becomes
510152025. 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 (See this)
Double Linked
List // Adding a node at the front of the list
public void push(int new_data)
{
/* 1. allocate node
* 2. put in the data */
Node new_Node = new Node(new_data);

/* 3. Make next of new node as head and


previous as NULL */
new_Node.next = head;
new_Node.prev = null;

/* 4. change prev of head node to new node


*/
if (head != null)
head.prev = new_Node;

/* 5. move the head to point to the new


node */
head = new_Node;
}
Double Linked List
2) Add a node after a given node.: (A 7 steps process)
We are given pointer to a node as prev_node, and the new
node is inserted after the given node.
Double Linked List
/* Given a node as prev_node, insert a new /* 4. Make next of new node as next of
node after the given node */ prev_node */
public void InsertAfter(Node prev_Node, int new_node.next = prev_Node.next;
new_data)
{ /* 5. Make the next of prev_node as
new_node */
/*1. check if the given prev_node is NULL */ prev_Node.next = new_node;
if (prev_Node == null) {
System.out.println("The given previous /* 6. Make prev_node as previous of
node cannot be NULL "); new_node */
return; new_node.prev = prev_Node;
}
/* 7. Change previous of new_node's next
/* 2. allocate node node */
* 3. put in the data */ if (new_node.next != null)
Node new_node = new Node(new_data); new_node.next.prev = new_node;
}
Double Linked List/* 4. If the Linked List is empty, then make the
new
* node as head */
// Add a node at the end of the list
if (head == null) {
void append(int new_data)
new_node.prev = null;
{
head = new_node;
/* 1. allocate node
return;
* 2. put in the data */
}
Node new_node = new Node(new_data);
/* 5. Else traverse till the last node */
Node last = head; /* used in step 5*/
while (last.next != null)
last = last.next;
/* 3. This new node is going to be the last
node, so
/* 6. Change the next of last node */
* make next of it as NULL*/
last.next = new_node;
new_node.next = null;
/* 7. Make last node as previous of new
node */
new_node.prev = last;
}
Double Linked List
4) Add a node before a given node:
Steps
Let the pointer to this given node be next_node and the data of the new node to be added
as new_data.
1. Check if the next_node is NULL or not. If it’s NULL, return from the function because any
new node can not be added before a NULL
2. Allocate memory for the new node, let it be called new_node
3. Set new_node->data = new_data
4. Set the previous pointer of this new_node as the previous node of the next_node,
new_node->prev = next_node->prev
5. Set the previous pointer of the next_node as the new_node, next_node->prev =
new_node
6. Set the next pointer of this new_node as the next_node, new_node->next = next_node;
7. If the previous node of the new_node is not NULL, then set the next pointer of this
previous node as new_node, new_node->prev->next = new_node
8. Else, if the prev of new_node is NULL, it will be the new head node. So, make
(*head_ref) = new_node.
Double Linked List
4) Add a node before a given node:
Double Linked List – Delete
Node

After deletion of head node


Double Linked List – Delete
Node

After deletion of middle node


Double Linked List – Delete
Node

After deletion of last node


Double Linked List – Delete
Node
Algorithm
Let the node to be deleted is del.
1) If node to be deleted is head node,
then change the head pointer to next
current head.
2) Set next of previous to del, if
previous to del exists.
3) Set prev of next to del, if next
to del exists.
Double Linked List – Delete Node
// C++ program to delete a node from /* Function to delete a node in a Doubly Linked List.
head_ref --> pointer to head node pointer.
// Doubly Linked List del --> pointer to node to be deleted. */
#include <bits/stdc++.h> void deleteNode(Node** head_ref, Node* del)
using namespace std; {
/* base case */
if (*head_ref == NULL || del == NULL)
/* a node of the doubly linked list */ return;
class Node
{ /* If node to be deleted is head node */
if (*head_ref == del)
public: *head_ref = del->next;
int data;
Node* next; /* Change next only if node to be
Node* prev; deleted is NOT the last node */
if (del->next != NULL)
}; del->next->prev = del->prev;

/* Change prev only if node to be


deleted is NOT the first node */
if (del->prev != NULL)
del->prev->next = del->next;

/* Finally, free the memory occupied by del*/


free(del);
return;
}
Double Linked List – Delete Node
/* UTILITY FUNCTIONS */
/* Function to insert a node at the
beginning of the Doubly Linked List */
void push(Node** head_ref, int new_data)
{
/* allocate node */
Node* new_node = new Node();

/* put in the data */


new_node->data = new_data;

/* since we are adding at the beginning,


prev is always NULL */
new_node->prev = NULL;

/* link the old list off the new node */


new_node->next = (*head_ref);

/* change prev of head node to new node */


if ((*head_ref) != NULL)
(*head_ref)->prev = new_node;

/* move the head to point to the new node */


(*head_ref) = new_node;
}
Double Linked List – Delete Node
/* Function to print nodes in a given doubly linked cout << "Original Linked list ";
list printList(head);
This function is same as printList() of singly linked lsit
*/
/* delete nodes from the doubly linked list
void printList(Node* node)
{ */
while (node != NULL) deleteNode(&head, head); /*delete first
{ node*/
cout << node->data << " "; deleteNode(&head, head->next); /*delete
node = node->next; middle node*/
} deleteNode(&head, head->next); /*delete
} last node*/
/* Driver code*/
int main() /* Modified linked list will be NULL<-8-
{ >NULL */
/* Start with the empty list */ cout << "\nModified Linked list ";
Node* head = NULL; printList(head);

/* Let us create the doubly linked list 10<->8<->4<- return 0;


>2 */ }
push(&head, 2);
push(&head, 4);
push(&head, 8); // This code is contributed by rathbhupendra
push(&head, 10);

You might also like