Professional Documents
Culture Documents
Syllabus
1 Data elements are arranged in a linear order Data elements are attached in hierarchically
where each and every elements are attached manner.
to its previous and next adjacent.
2 Single level is involved. Multiple levels are involved.
3 Its implementation is easy Its implementation is complex
4 Data elements can be traversed in a single run Data elements can’t be traversed in a single run
only. only.
5 Memory is not utilized in an efficient way. Memory is utilized in an efficient way.
6 Examples are: array, stack, queue, linked list, Examples are: trees and graphs.
etc.
7 Applications of linear data structures are Applications of non-linear data structures are in
mainly in application software development. Artificial Intelligence and image processing.
8 Time complexity often increases with increase in Time complexity often remain with increase in size.
size.
Linear Data Structure-Array
• By bracket notation
• A is Linear Array
• 1, 2, 3, 4 are index values
• 1000 is bases address(starting address of the array) in bytes
• 10, 100, 20, 500, 600 are elements of the array
Operations on arrays
• Array traversal
• Insertion
• Deletion
• Sorting
• Searching
Array Traversal -Eg
#include <stdio.h>
main()
{
int Array[] = {1,3,5,7,8};
int item = 10, k = 3, n = 5;
Output:
int i = 0, j = n;
The original array elements are :
printf("The original array elements are :\n"); Array[0] = 1
for(i = 0; i<n; i++) Array[1] = 3
{ Array[2] = 5
printf("Array[%d] = %d \n", i, Array[i]); Array[3] = 7
Array[4] = 8
}
}
Insertion
• Insertion refers to addition of element to the array
• A new element can be added at the beginning, end, or any given index
of array.
• Inserting an element at the end of the array can be easily done
provided memory space allocated is large enough to accommodate the
element.
• Inserting an element in the middle of the array is somewhat difficult
• Half of the element is must be moved downward to new locations
to accommodate the new element to keep the order of other
elements.
Insertion…
#include <stdio.h>
main()
{
int LA[] = {1,3,5,7,8};
int item = 10, k = 3, n = 5;
OUTPUT:
int i = 0, j = n;
printf("The original array elements are :\n"); The original array elements are :
LA[0] = 1
for(i = 0; i<n; i++) LA[1] = 3
printf("LA[%d] = %d \n", i, LA[i]); LA[2] = 5
LA[3] = 7
n = n + 1; LA[4] = 8
while( j >= k) The array elements after insertion :
LA[0] = 1
{ LA[j+1] = LA[j]; j = j - 1; } LA[1] = 3
LA[k] = item; LA[2] = 5
LA[3] = 10
printf("The array elements after insertion :\n"); LA[4] = 7
LA[5] = 8
for(i = 0; i<n; i++)
printf("LA[%d] = %d \n", i, LA[i]); }
Insertion…
Deletion
Algorithm
1.Start
2.Set j=0
3.Repeat steps 4 and 5 while J<N
4.If LA[J] is equal to item then goto step 6
5.Set J=J+1
6.Print J, item
7.Stop
Searching…
#include <stdio.h>
void main()
{
int LA[] = {1,3,5,7,8};
int item = 5, n = 5;
int i = 0, j = 0;
Output:
printf("The original array elements are :\n");
for(i = 0; i<n; i++)
The original array elements are
printf("LA[%d] = %d \n", i, LA[i]); LA[0] = 1
while( j < n) LA[1] = 3
{ LA[2] = 5
if( LA[j] == item ) LA[3] = 7
break; LA[4] = 8
j = j + 1;
Found element 5 at position 3
}
printf("Found element %d at position %d\n", item, j+1);
}
Applications of arrays
Applications
Arrays are widely used to implement mathematical vectors, matrices, and other
kinds of rectangular tables.
Many databases include one-dimensional arrays whose elements are records.
Arrays are also used to implement other data structures such as strings, stacks,
queues, heaps, and hash tables.
Arrays can be used for sorting elements in ascending or descending order
Multidimensional Arrays
Example
• The 2d array can be used to represent a sparse matrix in which there are three
rows named as:
• Row: It is an index of a row where a non-zero element is located.
• Column: It is an index of the column where a non-zero element is located.
• Value: The value of the non-zero ele
• Representing a sparse matrix by a 2D array leads to wastage of lots of memory
as zeroes in the matrix are of no use in most of the cases.
• So, instead of storing zeroes with non-zero elements, we only store non-zero
elements. T
• This means storing non-zero elements with triples- (Row, Column, value).
Sparse Matrix…
56
Introduction
• Linked List is a linear data structure.
• A list can be defined as an ordered collection
• A node contains two fields i.e. data stored at that
particular address and the pointer which contains
the address of the next node in the memory.
• The last node of the list contains pointer to the null.
57
• A linked list can change during execution.
• Successive elements are connected by pointers.
• Last element points to NULL.
• It can grow or shrink in size during execution of a program.
• It can be made just as long as required.
• It does not waste memory space.
58
Basic operations of Linked List
• Creation- Creates a linked list
• Insertion − Adds an element to the list.
• Deletion − Deletes an element to the list.
• Display − Displays the complete list.
• Search − Searches an element using the given key.
• Delete − Deletes an element using the given key.
59
Creating a Linked List
60
• To start with, we have to create a node (the first node), and make
head point to it.
• struct node
• {
• int data;
• struct node *next;
• };
• struct node *head, *ptr;
• ptr = (struct node *)malloc(sizeof(struct node *));
head
roll next
name
age
61
Contd.
• If there are n number of nodes in the initial linked list:
• Allocate n records, one by one.
• Read in the fields of the records.
• Modify the links of the records so that the chain is formed.
head
A B C
62
Inserting a Node in a List
63
• The insertion into a singly linked list can be
performed at different positions. Based on the
position of the new node being inserted, the insertion
is categorized into the following categories.
64
Illustration: Insertion
A B C
Item to be
tmp X inserted
A B C
curr
X
65
Pseudo-code for insertion
typedef struct nd {
struct item data;
struct nd * next;
} node;
tmp=(node *) malloc(sizeof(node));
tmp->next=curr->next;
curr->next=tmp;
}
66
Contd.
• When a node is added at the beginning,
– Only one next pointer needs to be modified.
• head is made to point to the new node.
• New node points to the previously first element.
• When a node is added at the end,
– Two next pointers need to be modified.
• Last node now points to the new node.
• New node points to NULL.
• When a node is added in the middle,
– Two next pointers need to be modified.
• Previous node now points to the new node.
• New node points to the next node.
67
Deleting a node from the
list
68
The Deletion of a node from a singly linked list can be performed
at different positions. Based on the position of the node being
deleted, the operation is categorized into the following
categories.
69
Illustration: Deletion
Item to be deleted
A B C
tmp
curr
A B C
70
Pseudo-code for deletion
typedef struct nd {
struct item data;
struct nd * next;
} node;
71
Application of Linked List
72
Applications of linked list in computer
science
• Implementation of stacks and queues
• Implementation of graphs : Adjacency list representation of graphs is
most popular which is uses linked list to store adjacent vertices.
• Dynamic memory allocation : We use linked list of free blocks.
• Maintaining directory of names
• Performing arithmetic operations on long integers
• Manipulation of polynomials by storing constants in the node of
linked list
• representing sparse matrices
73
Applications of linked list in real world
• Image viewer – Previous and next images are linked, hence can be
accessed by next and previous button.
• Previous and next page in web browser – We can access previous and
next url searched in web browser by pressing back and next button
since, they are linked as linked list.
• Music Player – Songs in music player are linked to previous and next
song. you can play songs either from starting or ending of the list.
74
Stack Implementations: Using Array and Linked List
75
Stack: Linked List Structure
PUSH OPERATION
top
76
Stack: Linked List Structure
POP
OPERATION
top
77
Basic Idea
• We would:
• Declare an array of fixed size (which determines the
maximum size of the stack).
• Keep a variable which always points to the “top” of the
stack.
• Contains the array index of the “top” element.
78
Basic Idea
• In the linked list implementation, we would:
• Maintain the stack as a linked list.
• A pointer variable top points to the start of the list.
• The first element of the linked list is considered as the stack top.
79
Declaration
struct lifo
{
int value;
struct lifo *next;
};
typedef struct lifo
stack;
stack *top;
80
Stack Creation
void create (stack **top)
{
*top = NULL;
81
Pushing an element into the stack
void push (stack **top, int element)
{
stack *new;
new = (stack *) malloc(sizeof(stack));
if (new == NULL)
{
printf (“\n Stack is full”);
exit(-1);
}
new->value = element;
new->next = *top;
*top = new;
}
ARRAY
82
Popping an element
int pop (stack **top)
from the stack
{
int t;
stack *p;
if (*top == NULL)
{
printf (“\n Stack is empty”);
exit(-1);
}
else
{
t = (*top)->value;
p = *top;
*top = (*top)->next;
free (p);
return t;
}
} ARRAY
83
Polynomial Arithmetic using Linked List
84
• A polynomial p(x) is the expression in variable x which
is in the form (axn + bxn-1 + …. + jx+ k), where a, b, c
…., k fall in the category of real numbers and 'n' is non
negative integer, which is called the degree of
polynomial.
• A polynomial can be thought of as an ordered list of
non zero terms. Each non zero term is a two-tuple
which holds two pieces of information:
• The exponent part
• The coefficient part
85
Adding two polynomials using Linked List
Given two polynomial numbers represented by a linked list.
Write a function that add these lists means add the coefficients
who have same variable powers.
86
Cursor Based Implementation
Methodology
Motivation
• Some programming languages doesn’t support pointers.
• But we need linked list representation to store data.
• Solution:
• Cursor implementation – Linked list implementation using arrays.
What is Cursor List?
• A CursorList is an array version of a Linked List.
• It is an array of list nodes but instead of each node containing a
pointer to the next item in the linked list, each node element in the
array contains the index for the next node element.
Methodology
• Convert a linked list based implementation to an array based
implementation.
• Instead of pointers, array index could be used to keep track of node.
• Convert the node structures (collection of data and next pointer) to a
global array of structures.
• Need to find a way to perform dynamic memory allocation performed
using malloc and free functions.
Methodology: 1. Cursor Representation Model
Slot Element Next Cursor Model:
0 header 1
• Global array of structures
1 - 2 • Each structure has two members
2 - 3 1. Element
3 - 4 2. Next
• Figure 2.7.1 has 11 array of structures.
4 - 5
5 - 6
Initial configuration of cursor:
6 - 7
7 - 8 • It contains empty list with 0 as header.
8 - 9
• 0 1 2 3 4 5 6 7 8 9 10
9 - 10
10 - 0 • Node 10 is the last node of the list with next pointer to ‘ 0 ’.
CursorAlloc() CursorFree()
Position CursorAlloc( void ) void CursorFree( Position P)
{ {
Position P;
CursorSpace[P].Next=CursorSpace[0].Next;
CursorSpace[0].Next = P;
P = CursorSpace[0].Next;
CursorSpace[0].Next = CursorSpace[P].Next; }
return P;
}
Initializing Cursor Space
• Cursor_space[list] =0;
Cursor implementation of linked lists - Example
TmpCell = CursorAlloc( )
if( TmpCell ==0 )
fatal_error("Out of space!!!");
CursorSpace[TmpCell].Element = x;
CursorSpace[TmpCell]. Next = CursorSpace[P]. Next;
CursorSpace[P]. Next =TmpCell;
}
Find Routine
/* Return Position of X in L; 0 if not found */
/* Uses a header node */
P = CursorSpace[L].Next;
while( P && CursorSpace[P].Element != x )
P = CursorSpace[P].Next;
return P;
}
Deletion Routine
/* Delete first occurrence of x from a list */
/* Assume use of a header node */
P = FindPrevious( x, L );
• A circular linked list can be a singly circular linked list or doubly circular
linked list.
Advantages of Circular Linked Lists
• Any node can be a starting point.
• We just need to stop when the first visited node is visited again.
• Insertion
• Deletion
• Display
temp=head;
temp->next = new;
new -> next = head;
Insertion in a Circular Linked List
Step 4 - If it is Not Empty then, define a Node pointer 'temp' and initialize with 'head‘
Step 5 - Keep moving the 'temp' to its next node until it reaches to the last node
(until 'temp → next == head').
Step 6 - Set 'newNode → next =head', 'head = newNode' and 'temp → next = head'.
Inserting At the End of the list
• Steps to insert a new node at end of the circular linked list.
Step 3 - If it is Empty then, set head = newNode and newNode → next = head
Step 4 - If it is Not Empty then, define a node pointer temp and initialize
with head
Step 5 - Keep moving the temp to its next node until it reaches to the last node in
the list (until temp → next == head)
Step 3 - If it is Empty then, set head = newNode and newNode → next = head.
Step 4 - If it is Not Empty then, define a node pointer temp and initialize
with head
Step 5 - Keep moving the temp to its next node until it reaches to the node after which
we want to insert the newNode (until temp1 → data is equal to location, here
location is the node value after which we want to insert the newNode).
Inserting At Specific location in the list (After a Node)
Step 6 - Every time check whether temp is reached to the last node or not. If it is reached
to last node then display 'Given node is not found in the list!!!
Step 7 - If temp is reached to the exact node after which we want to insert the newNode
then check whether it is last node (temp → next == head).
Step 8 - If temp is last node then set temp → next = newNode and
Step 9 - If temp is not last node then set newNode → next = temp → next
Insertion at middle:
n1->next = new;
new->next = n2;
n2->next = head;
Insertion at last:
n2->next=new;
new->next = head;
Circular Linked List
Deletion Operation
• In a circular linked list, the deletion operation can be performed in three
ways those are as follows.
Step 2 - If it is Empty then, display 'List is Empty!!! Deletion is not possible' and
terminate the function
Step 3 - If it is Not Empty then, define two Node pointers 'temp1' and 'temp2' and
initialize both 'temp1' and 'temp2' with head
Step 4 - Check whether list is having only one node (temp1 → next == head)
Step 5 - If it is TRUE then set head = NULL and delete temp1 (Setting Empty list
conditions)
Step 6 - If it is FALSE move the temp1 until it reaches to the last node.
(until temp1 → next == head )
Step 7 - Then set head = temp2 → next, temp1 → next = head and delete temp2
DELETING FROM END OF THE LIST
• The following steps to delete a node from end of the circular linked list.
Step 2 - If it is Empty then, display 'List is Empty!!! Deletion is not possible' and
terminate the function.
Step 3 - If it is Not Empty then, define two Node pointers 'temp1' and 'temp2' and
initialize 'temp1' with head
Step 4 - Check whether list has only one Node (temp1 → next == head)
Step 5 - If it is TRUE. Then, set head = NULL and delete temp1. And terminate from the
function. (Setting Empty list condition)
Step 6 - If it is FALSE. Then, set 'temp2 = temp1 ' and move temp1 to its next node.
Repeat the same until temp1 reaches to the last node in the list. (until temp1 →
next == head)
• First position.
• Last Position.
• At any given position i.
Deleting the last node of the Circular Linked List
Deleting nodes at given index in the Circular
linked list
Array versus Linked Lists
• Linked lists are more complex to code and manage than arrays, but they
have some distinct advantages.
• There are n people standing in a circle waiting to be executed. The counting out begins at
some point in the circle and proceeds around the circle in a fixed direction. In each step, a
certain number of people are skipped and the next person is executed. The elimination
proceeds around the circle (which is becoming smaller and smaller as the executed people
are removed), until only the last person remains, who is given freedom. Given the total
number of persons n and a number m which indicates that m-1 persons are skipped and m-th
person is killed in circle. The task is to choose the place in the initial circle so that you are the
last one remaining and so survive.
Example
Josephus Problem - Snippet
int josephus(int m, node *head)
{ f->next=head->next;
node *f; //sequence in which nodes getting deleted
int c=1;
while(head->next!=head) printf("%d->",head->data);
{ head=f->next;
c=1; }
while(c!=m) printf("\n");
{ printf("Winner is:%d\n",head->data);
f=head; return;
head=head->next; }
c++;
}
Exercise
• Write a C program to implement the following operations using
Circular Linked List
• Insertion in all the positions like start , middle and end
• Deletion in all the positions like start , middle and end
• Display
Quiz
1. Find the concept which is right for the below condition.“Any node can be a starting point.
We can traverse the whole list by starting from any point. We just need to stop when the
first visited node is visited again”.
• Circular Linked List
• Singly Linked List
• Stack
• Queue
2. What is the right statement (condition) to check the last node in the circular linked list.
(Assume temp is initialized as temp=head)
• temp->next=NULL
• temp->next=head
• temp=NULL
• temp=head
Quiz
3. Find the code used to count the nodes in the circular linked list.
Doubly Linked List
Doubly Linked list - Motivation
• Doubly linked lists are useful for playing video and sound files with “rewind” and
“instant replay”
• They are also useful for other linked data which require “rewind” and “fast
forward” of the data
Doubly Linked Lists
• Doubly linked lists
• Each node points to not only successor but the
predecessor
• There are two NULL: at the first and last nodes in the list
• Advantage: given a node, it is easy to visit its predecessor.
Convenient to traverse lists backwards
NULL 13 6 12 NULL
Address of
previous node
Last
Head
Doubly-linked lists
head NUL
a b c
L
last
7
Address of
temp previous node
Head Last
Insertion at end • Time Complexity – O(n)
13 6 12
Last
Head
Insertion at a given position
Struct node *insertAtPostion(Struct node *head, int data, int item)
{
Struct node *temp, *P; P= P->next;
temp=(Struct node*)malloc(Sizeof(struct node)); }
temp->info=data; Printf(“%d
item); not present in the list \n \n”,
P=head; return head;
While(P!=NULL) }
{ • Time Complexity –O(n)
If(P->info==item)
{
temp->previous=P;
Temp->next=P->next;
If(P->next->previous=temp);
P->next=temp;
Return head;
}
Head 13 6 12 NULL
NULL
temp Last
Deleting a node from the list
Struct node *delete(Struct node *head, int data) Else
{ {
Struct node *temp; printf(“Element %d not found \n”, data);
If(head==NULL) return head;
{ }
printf(“List is empty”); }
return head;
}
If(head->next==NULL)
Time Complexity – O(1)
{
If(head->info==data)
{
temp=head;
head=NULL;
free(temp);
return head;
} temp
Head 13 NULL
NULL
Deletion of first node
Struct node *delete(Struct node *head, int data)
{
Struct node *temp;
If(head==NULL)
{ • Time Complexity – O(1)
printf(“List is empty”);
return head;
}
If(head->info==data)
{
temp=head;
head=head->next;
head->previous=NULL;
free(temp);
return head;
}
Deletion of a node in the middle
temp=head->next;
While(temp->next!=NULL)
{
If(temp->info==data)
{
temp->previous->next=temp->next;
temp->next->previous=temp->previous;
free(temp);
return head;
}
temp=temp->next;
}
13 6 12 8
NULL
Deletion of a node at end
int deleteFromEnd()
{
struct node *temp;
temp = last;
if(temp->previous==NULL)
{
free(temp);
head=NULL;
last=NULL;
return 0;
}
printf("\nData deleted from list is %d \n",last->data);
last=temp->previous;
last->next=NULL;
free(temp);
return 0;
}
13 6 12
8
NULL
Searching a node
int searchList(struct Node* head, int search) if(temp->info == search)
{ {
struct Node *temp = head; count++;
int count=0,flag=0,value; flag = 1;
if(temp == NULL) }
return -1; if(flag == 1)
else { printf(“%d Search node is found \n”);
while(temp->next != head) else
{ printf(“%d Search node is found \n”);
count++; }
if(temp->info == search) }
{
flag = 1;
count--;
break;
}
temp = temp->next;
}
Advantages and Disadvantages of Doubly Linked List
• Advantages:
1. We can traverse in both directions i.e. from starting to end and as well as from end to
starting.
2. It is easy to reverse the linked list.
3. If we are at a node, then we can go to any node. But in linear linked list, it is not
possible to reach the previous node.
Disadvantages:
1. It requires more space per space per node because one extra field is required for pointer
to previous node.
2. Insertion and deletion take more time than linear linked list because more pointer
operations are required than linear linked list.
Review Questions
1) How do you calculate the pointer difference in a memory efficient double linked list?
a) head xor tail b) pointer to previous node xor pointer to next node
c) pointer to next node - pointer to previous node
d) pointer to previous node - pointer to next node