Data Structure
Mr Zahi Al Chami
Chap 4: Simple Linked List
Introduction
Like arrays, a linked list is a linear data structure to store
data of similar type where each element is a separate
object (called nodes).
Unlike arrays, linked list elements are not stored at a
contiguous location; the elements are linked using
pointers.
Introduction
We have three types of linked list:
Simple Linked list ( singly) : Traversed in one direction
Doubly Linked List: Traversed in both directions
Circular Linked List
Why Linked List ?
An array is always of a fixed size; it does not grow as more
elements are required.
The programmer must remember the location in the array of
each value.
When using an array, many operations may be applied such
as accessing element at certain point, remove or add element.
However, these different actions have costs in terms of time.
Why Linked List ?
The computational complexity for writing (replacing a
value) and accessing an array is O(1).
Inserting or removing from an array can come in three
different forms:
inserting/removing at the beginning.
inserting/removing at the end.
inserting/removing at the middle.
Why Linked List ?
In order to add an element to the beginning of an array, we must shift every
other element after it to a higher index.
Time taken will be proportional to the size of the list or Big O(n), n being
the size of the list.
Adding to the end of the array is a lot simpler in terms of speed. It involves
adding the element to the next highest index of the array.
This means that it is constant time and Big O(1) if the array is not already
full.
The third case of insertion would be adding to a position between the
beginning and end of the array which would be Big O(n).
Why Linked List ?
Arrays can be used to store linear data of similar types, but arrays
have the following limitations:
The size of the arrays is fixed
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.
Advantages of the linked list:
Dynamic size
Ease of insertion / deletion
Drawbacks:
Random access is not allowed
Extra memory space for a pointer is required with each element of the list
Simple Linked List Representation
A linked list is represented by a pointer to the first node of
the linked list and it ends by a NULL pointer.
The first node is called the head. The list can only be
traversed in one direction.
Each node in a list consists of at least two parts:
Data
Pointer (Or Reference) to the next node
Simple Linked List Declaration
You only need to create the pointer which will point to the
first element of the linked list (Head), and no end is
therefore to be specified.
We proceed as follows to declare a node:
struct NODE {
int data; // can be any type
NODE *next; // a pointer to point to the next node
};
Simple Linked List Manipulation
The main operations to perform in a simple linked list are:
Initialization
Display
Insertion
Suppression
Modification
Search
Other operations: test if a linked list is empty, return the
number of nodes, etc.
Simple Linked List: Initialization
To create a linked list, we need to initialize its first
element, which represents its head.
To do so, we proceed as follows:
NODE *initialize(){
return NULL;
}
Display a Simple Linked List
void Display ( NODE *head){
NODE *cur;
cur=head;
while(cur!=NULL){
cout<<cur->data << “ “;
cur=cur->next;
}
}
Insert At Head
To insert a new node, we need to:
Create the node using the dynamic allocation
Initialize the node
Insert the node in the list by adjusting the links
In the case of the insertion at head, we need to adjust the
pointer to the beginning of the list.
Insert At Head
NODE *insertAtHead( NODE *head, int val){
NODE *tmp; // create a new NODE
tmp=new NODE; // declare the new NODE
tmp->data=val;
tmp->next=head; // insert the new NODE
return tmp;
}
Insert At Tail
Insert At Tail
NODE *InsertAtQueue (NODE *head, int val){ To check if a list is empty:
NODE *tmp, *cur; bool isEmpty(NODE *head){
tmp=new NODE;
tmp->data=val; return (head==NULL);
tmp->next=null; }
if( isEmpty(head))
return tmp;
cur=head;
while(cur->next!=NULL)
cur-=cur->next;
cur->next=tmp;
return head;
}
Insert at a given position
Insert at a given position between 2 nodes
NODE *InsertAtPosition (NODE *head, int val, int position){
NODE *tmp,*cur;
tmp=new NODE;
tmp->data=val;
cur=head;
int i=0;
while(i < position && cur->next!=NULL){
cur=cur->next;
i++;
}
tmp->next=cur->next;
cur->next=tmp;
return head;
}
Delete From Head
Delete From Head
NODE *DeleteFromHead ( NODE *head){
NODE *cur=head->next;
delete head;
head=cur;
return head;
}
What if the list is empty ?
Delete From Tail
Delete From Tail
NODE *DeleteFromTail ( NODE *head){
NODE *cur, *prev;
cur=head->next;
prev=head;
while(cur->next!=null){
cur=cur->next;
prev=prev->next;
}
delete cur;
prev->next=null;
return head;
}
Delete From a specific Position
Delete an entire List
To delete a list, you should remove each node.
Exercises
Write a function to check if an element exists in a List.
Write a function that will return the number of elements in a
linked list.
Write a function that concatenates two simple linked list
Write a procedure that deletes the node which has the lowest
value
Write a procedure that will reverse a linked list.
We need to reverse the list by changing links between nodes.
Exercises
Write a function that finds the highest value in a linked list.
Write a function that takes a simple list as argument and
copies its elements into a second list but in the reverse order
Write a recursive procedure that displays the elements of a
simple list.
Write a recursive function that counts the number of
elements of a simple list
Exercises
Write a procedure that swaps two nodes. This procedure
takes as input the two positions and a list.
Step 1
Step 2
Step 3
Doubly Linked List
Introduction
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.
The List is not only defined by its head, but also by its
tail.
List and Node Definition
We define a node and a list as follows:
Struct NODE { Struct LIST {
NODE *next; NODE *head;
NODE *prev; NODE *tail;
int data; };
};
List Initialization
As we mentioned before, a doubly linked list is defined by
its head and tail.
To initialize a list, we proceed as follows:
Void Initialize ( LIST *L){
L->head=NULL;
L->tail=NULL;
}
Display the elements of a List
To display the elements from the head to the tail, we then write:
Void Head2Tail (List *L){
To check if a list is empty
NODE *cur=L->head;
bool isEmpty (LIST *L){
if (isEmpty (L)){
cout<<“List is empty”; return (L->head==NULL);
return; }
}
while (cur!=NULL){
cout<<cur->data<<“ “;
cur=cur->next;
}
}
How to display the elements from tail to head ?
Search a node containing a specific value
NODE *search (LIST *L, int val) {
NODE *cur=L->head;
if (isEmpty (L)){
cout<<“Empty”;
return NULL;
}
while (cur!=NULL){
if(cur->data==val)
return cur;
cur=cur->next;
}
return NULL;
}
Write a function that returns the last occurrence.
Write a function that returns the total nodes containing the given value
Insert at Head
Insert at Head
Void InsertAtHead (LIST *L, int val) {
NODE *tmp=new NODE;
tmp->next=NULL;
tmp->prev=NULL;
tmp->data=val;
ff( isEmpty(L)) {
L->head=tmp;
L->tail=tmp;
return;
}
tmp->next=L->head;
L->head->prev=tmp;
L->head=tmp;
}
Insert at Tail
Insert at Tail
Void InsertAtTail (LIST *L, int val) {
NODE *tmp=new NODE;
tmp->next=NULL;
tmp->prev=NULL;
tmp->data=val;
if (isEmpty(L)){
L->head=tmp;
L->tail=tmp;
return;
}
L->tail->next=tmp;
tmp->prev=L->tail;
L->tail=tmp;
}
Insert at specific position (Between 2 nodes)
Insert at specific position (Between 2 nodes)
Void InsertAtPosition (LIST *L, int val, int position) {
NODE *tmp=new NODE;
tmp->data=val;
NODE *cur=L->head;
int i=0;
while ( i< position && cur!=NULL){
cur=cur->next;
i++;
}
if (cur->next!=NULL){
tmp->next=cur->next;
tmp->prev=cur;
cur->next->prev=tmp;
cur->next=tmp;
}
}
Delete From Head
Delete From Head
Void DeleteHead (LIST *L) {
if (isEmpty (L)) {
cout<<“ Error , list is empty”;
return;
}
NODE *cur;
cur=L->head->next;
delete L->head;
L->head=cur;
L->head->prev=NULL;
}
Delete from Tail
Delete From Tail
Void deleteFromTail ( LIST *L) {
if (isEmpty (L)){
cout<< “error, list is empty”;
return;
}
NODE *cur;
cur=L->tail->prev;
delete L->tail;
L->tail=cur;
L->tail->next=NULL;
}
Delete Between 2 nodes
Delete Between 2 nodes
Void DeleteBetween ( LIST *L, int pos) {
NODE *cur;
if (isEmpty(L)){
cout<<“List is Empty”;
return;
}
cur=L->head;
int i=0;
while ( i<pos && cur!=NULL){
cur=cur->next;
i++;
}
if ( cur->next!=NULL ){
cur->prev->next=cur->next;
cur->next->prev=cur->prev;
delete cur;
}
Exercise
Write a function to delete a node that has a specific value.
This value should be passed as parameter.
Note that the value can be at one of the three possibilities below
:
At the head of the list
At the tail of the list
At the middle
Exercise