DSA Unit2
DSA Unit2
• Nonlinear DS
• Data elements are not arranged sequentially or linearly
• Single level is not involved. Therefore, we can’t traverse all the elements in single run
only.
• Not easy to implement in comparison to linear data structure. It utilizes computer
memory efficiently in comparison to a linear data structure.
• Examples are Trees and Graphs
Linear Vs Nonlinear Data Structures
S.No Linear Nonlinear
1 Data elements are arranged in a linear Data elements are attached in hierarchically
order where each and every elements are manner.
attached 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 Data elements can’t be traversed in a single run
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 Examples are: trees and graphs.
list, etc.
7 Applications of linear data structures are Applications of non-linear data structures are in
mainly in application software Artificial Intelligence and image processing.
development.
8 Time complexity often increases with increase Time complexity often remain with increase in size.
in 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 loactions
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
LA[2] = 5
printf("LA[%d] = %d \n", i, LA[i]); LA[3] = 7
n = n + 1; LA[4] = 8
The array elements after insertion :
while( j >= k) LA[0] = 1
{ LA[j+1] = LA[j]; j = j - 1; } LA[1] = 3
LA[2] = 5
LA[k] = item; LA[3] = 10
LA[4] = 7
printf("The array elements after insertion :\n"); 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"); The original array elements are
for(i = 0; i<n; i++) LA[0] = 1
printf("LA[%d] = %d \n", i, LA[i]); LA[1] = 3
while( j < n) LA[2] = 5
{ LA[3] = 7
if( LA[j] == item )
LA[4] = 8
break;
Found element 5 at position 3
j = j + 1;
}
printf("Found element %d at position %d\n", item, j+1);
}
Applications of arrays
Applications
● Arrays are used to Store List of values ● Arrays are used to implement Sorting Algorithms
In c programming language, single dimensional arrays are
We use single dimensional arrays to implement sorting
used to store list of values of same datatype. In other algorihtms like ...
words, single dimensional arrays are used to store a row
a. Insertion Sort
of values. In single dimensional array data is stored in
linear form. b. Bubble Sort
● Arrays are used to Perform Matrix Operations c. Selection Sort
We use two dimensional arrays to create matrix. We can d. Quick Sort
perform various operations on matrices using two e. Merge Sort, etc.,
dimensional arrays. ● Arrays are used to implement Datastructures
● Arrays are used to implement Search Algorithms We use single dimensional arrays to implement
We use single dimensional arrays to implement search datastructures like...
algorihtms like ... f. Stack Using Arrays
1. Linear Search
g. Queue Using Arrays
2. Binary Search
● Arrays are also used to implement CPU Scheduling
Algorithms
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…
105
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.
106
• 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.
107
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.
108
Creating a Linked List
109
• 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
110
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
111
Inserting a Node in a List
112
• 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.
113
Illustration: Insertion
A B C
Item to be
tmp X inserted
A B C
curr
X
114
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;
}
115
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.
116
Deleting a node from the
list
117
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.
118
Illustration: Deletion
Item to be deleted
A B C
tmp
curr
A B C
119
Pseudo-code for deletion
typedef struct nd {
struct item data;
struct nd * next;
} node;
120
Application of Linked List
121
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
122
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.
123
Stack Implementations: Using Array and Linked List
124
Stack: Linked List Structure
PUSH OPERATION
top
125
Stack: Linked List Structure
POP OPERATION
top
126
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.
128
Declaration
struct lifo
{
int value;
struct lifo *next;
};
typedef struct lifo
stack;
stack *top;
129
Stack Creation
void create (stack **top)
{
*top = NULL;
130
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
131
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
132
Polynomial Arithmetic using Linked List
133
• 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
134
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.
135
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()
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 5 - Keep moving the temp to its next node until it reaches to the last node in
the list (until temp → next == 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).
newNode → next = head
and temp → next = newNode.
Circular Linked List
Insertion (ROUTINE)
Insertion at first:
new->next = head
head =new;
temp->next= head;
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 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 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
int c=1; deleted
while(head->next!=head)
{ printf("%d->",head->data);
c=1;
head=f->next;
while(c!=m)
}
{
f=head;
printf("\n");
head=head->next; printf("Winner is:%d\n",head->data);
c++; return;
} }
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 contains
• a value,
• a link to its successor (if any), and
• a link to its 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 6 12 NULL
13
Address of
previous node
Head
Operations - Doubly Linked List
• Create a Node
• Insertion at beginning of a list
• Insertion at end of the list
• Insertion after a given position
• Delete a node from beginning
• Delete a node from end
• Delete a node from any location
Creating a Node
struct node
{
struct node *previous; • info: the user's data
int info;
struct node *next; • next, previous: the address of
}
void display(struct node *head) the next and previous node in
{ the list
struct node *P; .info .next
If (head==NULL) .back
{
printf(List is empty \n”); previous info next
return;
}
P=head;
printf(“List is: \t”);
while(P!=NULL)
{ printf(“%d”, P->info);
P=P->next;
}
}
Insertion at Beginning • Time Complexity –O(1)
Last
Head
Insertion after a given item
struct node *insertAfterItem(Struct node *head, int data, int item)
{
P= P->next;
struct node *temp, *P;
}
temp=(Struct node*)malloc(sizeof(struct node));
temp->info=data;
printf(“%d not present in the list \n \n”, item);
P=head; return head;
while(P!=NULL) }
{ • Time Complexity –O(n)
If(P->info==item)
{
temp->previous=P;
temp->next=P->next;
P->next->previous==temp;
P->next=temp;
return head;
}
Head 13 6 12 NULL
NULL
P
temp Last
Deletion
Find the node to delete
Adjust the pointers
Delete the node(freeing the memory space allotted to the node) by calling free()
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
struct node *deleteItemNode(Struct node *head, int data)
{
temp=head;
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 = head;
while(temp->next!=NULL)
temp=temp->next;
printf("\nData deleted from list is %d \n",temp->data);
temp->previous->next=NULL;
free(temp);
return 0;
}
13 6 12
8
NULL
Searching a node
int searchList(struct Node* head, int search)
{
struct Node *temp = head;
int flag=0,value;
if(temp == NULL)
return -1;
else {
while(temp->next != NULL)
{
if(temp->info == search)
{
flag = 1;
break;
}
temp = temp->next;
}
if(flag == 1)
printf(“%d Search node is found \n”);
else
printf(“%d Search node is not found \n”);
}
}
Advantages and Dis advantages of Doubl y L inked Li st
• 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