BScII CompSci DataStrcture Notes
BScII CompSci DataStrcture Notes
1
INTRODUCTION TO DATA
STRUCTURES
Unit Structure :
1.0 Objectives
1.1 Data and Information
1.2 Data Structure
1.3 Classification of Data Structure- Primitive Data types, Abstract
Data types, Data type VS File organization
1.4 Operation on Data Structure
1.5 Importance of Algorithm Analysis
1.6 Complexity of an Algorithm- Asymptotic Analysis and
Notations, Big O Notation, Big Omega Notation, Big Theta
Notation, Rate of Growth and Big O Notation
1.7 Summary
1.8 References
1.9 Questions
1.0 OBJECTIVES
2
1.2 Program- A implementation of algorithm in some programming
language.
1.3 Data Structure- Organization of data needed to solve the program
1.4 for eg Write a program to print 10 numbers
Algorithm would be
Step 1 Take a range of values in a variable A, nothing but an Array
Data Structure
Step 1 Assign a Value to an Array A Such as A[1,2,3,4,5,6,7,8,9,10]
Step 2 Apply loop to print values of Array
Program
# include<stdio.h>
#include<conio.h>
Void main
{
int a[10],i;
for(i=0;i<10;i++)
{
Printf(“The value of is “,i);
}
}
Data structure – here array is one type of data structure used here
1.7 To study Data structure in basic terms covers the following points
Amount of memory require to store
Amount of time require to process
Representation of data in memory
Operations performed on that data
3
1.3 CLASSIFICATION OF DATA STRUCTURE-
PRIMITIVE DATA TYPES, ABSTRACT DATA
TYPES, DATA TYPE VS FILE ORGANIZATION
4
4.4 Example of non-primitive data types are Array, List and Files
etc.
4.5 A Non-primitive data type is further divided in to Linear and
Non-Linear data structure
1 Array- An array is a fixed size sequenced collection of elements
of the same data type.
2 List- An ordered set containing variable number of elements of
the same data type .
3 File- A file is a collection of logically related information. It can
be viewed as a large list of records consisting of various fields.
5 Linear Data Structures
5.1 A data structure is said to be linear, if its elements are
connected in linear fashion by means of logically or in sequence
memory locations.
5.2 There are two ways to represent a linear data structure in
memory,
1 Static Memory Allocation
2 Dynamic Memory Allocation
5.3 The possible operations on the linear data structure are-
Traversal, insertion, Deletion, Searching, Sorting and Merging.
5.4 Examples of Linear Data Strictures are Stack and Queue
5.4.1 Stack- It is a data structure in which insertion and deletion
operation are performed a one end only. The insertion operation is
referred to as “PUSH” and deletion operation is referred to as
“POP” operation. Stack is also called as Last in First Out(LIFO)
data structure.
5.4.2 Queue- The data structure which permits the insertion at one
end and deletion at another end known as queue. End at which
deletion is occurs is known as FRONT end and another end at
which insertion occurs as REAR end. It is also called as First in
First Out (FIFO) structure.
6 Non Linear data Structures
6.1 These are those data structure in which data items are not
arranged in a sequence.
6.2 Examples of Non-Linear Data Structure are Tree and Graph.
6.3 Tree- A tree can be defined as finite set of data items(nodes) in
which data items are arranged in branches and sub branches
according to requirement. It represent the hierarchical relationship
between various elements. Tree consist of nodes connected by
edge, the node represented by circle and edge lives connecting to
circle.
6.4 Graph- Graph is a collection of nodes(information) and
connecting edges(logical relation) between nodes. A tree can be
viewed as restricted graph. Graph have many types like un-directed
5
graph, directed graph, mixed graph, multi graph, simple graph, null
graph, weighted graph.
7 Table 3 Shows difference between Linear and Non Linear Data
Structure
Fig 2 ADT
8.4 for eg Stack ADT
1 In Stack ADT implementation instead of data being stored in
each node, the pointer to data is stored.
2 The program allocates memory for the data and address is passed
to the stack ADT.
6
Fig 3 Stack as ADT
3 The head node and the data nodes are encapsulated in the ADT.
The calling function can only see the pointer to the stack.
4 The stack head structure also contains a pointer to top and
count of number of entries currently in stack. As Push(),
pop(),peek(),size(),isempty(),isfull() is already implemented in
STACK ADT, only programmer has to use this function for
implementing program on stack
9 Data Type V/s File Organization- Data type is A particular kind of
data item, as defined by the values it can take, the programming
language used or the operations that can be performed on it,
whereas File organization means how data type values are arranged
or organized in file.
7
In above pseudocode, all students are not passed, only that students
are selected which are above 60. So this is selection operation.
1.4 Updation- It updates or modifies the data in the data structure
1.5 Searching-It finds the presence of desired data item in the list
of data items, it may also find the locations of all elements that
satisfy certain conditions.
1.6 Sorting- It is a process of combining the data items of two
different sorted list in to a single list.
1.7 Merging- It is a process of combining the data items of two
different sorted list in to a single sorted list.
1.8 Splitting- It is a process of partitioning single list to multiple
list.
1.9 Traversal- It is a process of visiting each and every node of a
list in systematic manner.
1 Algorithm
1.1 An essential aspect to data structures is algorithms.
1.2 Data Structures are implemented using algorithms.
1.3 An algorithm is a procedure that you can write as a C function or
program, or any other language.
1.4 An algorithm states explicitly how the data will be manipulated.
2 Algorithm Efficiency
2.1 Some algorithms are more efficient than others. We would prefer
to choose an efficient algorithm, so it would be nice to have
metrics for comparing algorithm efficiency.
2.2 The complexity of an algorithm is a function describing the
efficiency of the algorithm in terms of the amount of data the
algorithm must process.
2.3 Usually there are natural units for the domain and range of this
function. There are two main complexity measure of the efficiency
of an algorithm.
3 Time Complexity
3.1 It is a function describing the amount of time an algorithm takes in
terms of the amount of input to the algorithm.
3.2 Time can mean the number of memory accesses performed, the
number of comparisons between integers, the number of times
some inner loop is executed or some other natural unit related to
the amount of real time the algorithm will be.
4 Space complexity
4.1 It is a function describing the amount of memory space an
algorithm takes in terms of the amount of input to the algorithm.
4.2 We always speak of “extra” memory needed, not counting the
memory needed to store the input itself. Again we use natural but
fixed-length units to measure this.
8
4.3 We can use bytes, but it's easier to use, say, number of integers
used, number of fixed-sized structures, etc. In the end, the function
we come up with will be independent of the actual
number of bytes needed to represent the unit.
4.4 It is sometimes ignored because the space used is minimal and/or
obvious, but sometimes it becomes as important an issue as time.
5 Worst Case Analysis
5.1 In the worst case analysis, we calculate upper bound on running
time of an algorithm. We must know that causes maximum number
of operations to be executed.
5.2 For Linear search, the worst case happens when the element to be
searched is not present in the array.
5.3 When X element is not present, the search() functions compares it
with all the elements of array[] one by one. So, the worst case time
complexity of linear search would be.
6 Average Case Analysis
6.1 In average case analysis, we take all possible inputs and calculate
computing time for all of the inputs.
6.2 Add all the calculated values and divide the obtained sum by total
number of inputs.
6.3 For the linear search problem, let us assume that all cases are
uniformly distributed. So we sum all the cases and divide the sum
by(n+1).
7 Best Case Analysis
7.1 In the best case analysis, we calculate lower bound on running time
of an algorithm. We must know the causes minimum number of
operations to be executed.
7.2 In the linear search problem, the best case occurs when x is present
at the first location.
2 For example- In bubble sort, when the input array is already sorted,
the time taken by the algorithm is linear i.e the best case.
3 But, when the input array is in reverse condition, the algorithm takes
the maximum time (quadratic) to sort the elements i.e the worst case.
9
4 When the input array is neither sorted nor in reverse order, then it
takes average time. These durations are denoted using asymptotic
notations.
6 Big-O Notation(O-Notation)
6.1 Big-O notation represents the upper bound of the running time of
an algorithm. Thus, it gives the worst-case complexity of an algorithm.
6.3 For any value of n, the running time of an algorithm does not cross
the time provided by O(g(n)).
10
7.1 Omega notation represents the lower bound of the running time of
an algorithm. Thus it provides the best case complexity of an
algorithm.
11
8.3If a function f(n) lies any where in between c1g(n) and c2g(n) for
all n>=n0, then f(n) is said to be asymptotically tight bound.
12
Example: f(n) = n² ; O(n²) i.e O(f(n) Similarly this property satisfies
for both and notation.
float useless(A){
n = A.length;
if (n==1){
return A[0];
}
let A1,A2 be arrays of size n/2
for (i=0; i <= (n/2)-1; i++){
A1[i] = A[i];
A2[i] = A[n/2 + i];
}
for (i=0; i<=(n/2)-1; i++){
for (j=i+1; j<=(n/2)-1; j++){
if (A1[i] == A2[j])
A2[j] = 0;
}
}
b1 = useless(A1);
b2 = useless(A2);
return max(b1,b2);
}
Theta(n) and the second has time complexity Theta(n^2). There are 2
recursive calls of size n/2. Finally constant time (Theta(1)) is spent
combining. Hence we get the recurrence.
T(1) = Theta(1)
T(n) = 2 T(n/2) + Theta(n^2) for n >= 2
By the master method we get that T(n) = Theta(n^2). Hence this given
algorithm is a Theta(n^2) algorithm.
13
1.7 SUMMARY OF CHAPTER
1.8 REFERENCES
Textbook
1 An Introduction to Data Structure with Applications, Jean – Paul
Tremblay and Paul Sorenson Tata MacGraw Hill 2 nd 2007.
2 Schaum’s Outlines Data structure Seymour Lipschutz Tata McGraw
Hill 2 nd 2005.
Useful Links
1 Nptel Course of Data Structure-
https://nptel.ac.in/courses/106/102/106102064/
14
2
ARRAY
Unit Structure :
2.0 Objectives
2.1 Introduction
2.2 One Dimensional Array- Memory Representation, Traversing,
Insertion, Deletion, Searching, Sorting, Merging of Arrays.
2.3 Multidimensional Arrays- Memory Representation, General
Multidimensional arrays
2.4 Sparse Arrays- Sparse Matrix, Memory Representation of special
kind of matrices
2.5 Advantages and Limitations of Arrays
2.6 Summary
2.7 References
2.8 Questions
2.0 OBJECTIVES
15
There are two types of arrays
One Dimensional Arrays
Two Dimensional Arrays
2.3 The initializers are specified within braces and separated by commas
as shown in below declarations
int ex[5] = { 10, 5, 15, 20, 25} ;
char word[10] = { 'h', 'e', 'l', 'l', 'o' } ;
2.4 Example
// Program to print the element of Array
#include <stdio.h>
int main()
{
/*an array with 5 rows and 2 columns*/
int a[5][2] = {{0,0},{1,2},{2,4},{3,6},{4,8}};
int i,j;
/* Output each array elements value*/
for(i=0; i<5; i++);
{
for(j=0; j<2; j++);
{
printf("a[%d][%d]=%d",i,j,a[i][j]);
}
}
return 0;
16
}
Output
a[0][0] = 0
a[0][1] = 0
a[1][0] = 1
a[1][1] = 2
a[2][0] = 2
a[2][1] = 4
a[3][0] = 3
a[3][1] = 6
a[4][0] = 4
Note- Use online compiler GDB compiler for running this program
#include <stdio.h>
int main()
{
int i,n; //Declaration of Variable used for inputing Value and for
iteration
17
printf("Enter the size of array");
scanf("%d",&n);
int LA[n];//Declaration of array
printf("The array elements are:\n");
for(i=0;i<n;i++)
{
scanf("%d", &LA[i]);
}
4.4Update Operation
1.Update operation refers to updating an existing element from the array at
a given index.
2.Example
Consider LA is a linear array with N elements and K is a positive integer
such that K<=N.
}
printf("element not found");
}
//output
Enter size of the array : 5
Enter elements in array : 1
2
3
4
5
Enter the key : 6
element not found
scanf("%d", &n);
int number[30];
printf("Enter the numbers \n");
scanf("%d", &number[i]);
for (i = 0; i < n; ++i)
22
a = number[i];
number[i] = number[j];
number[j] = a;
}
}
printf("The numbers arranged in ascending order are given below
\n");
for (i = 0; i < n; ++i)
printf("%d\n", number[i]);
}
//output
Enter the value of N
5
Enter the numbers
5
4
3
2
1
The numbers arranged in ascending order are given below
1
2
3
4
5
24
The simplest form of the Multi Dimensionl Array is the Two
Dimensionl Array. A Multi Dimensionl Array is essence a list of One
Dimensionl Arrays.
Program
#include <stdio.h>
void printarr(int a[][]);
void printdetail(int a[][]);
void print_usingptr(int a[][]);
main()
{
int a[3][2]; \ A
for(int i = 0;i<3;i++)
for(int j=0;j<2 ;j++)
{
{
a[i]=i;
}
}
printdetail(a);
}
void printarr(int a[][])
{
for(int i = 0;i<3;i++)
for(int j=0;j<2;j++)
{
{
printf("value in array %d,a[i][j]);
}
}
}
void printdetail(int a[][])
{
for(int i = 0;i<3;i++)
for(int j=0;j<2;j++)
{
{
printf( "value in array %d and address is %8u, a[i][j],&a[i][j]);
}
}
}
void print_usingptr(int a[][])
{
int *b; \ B
b=a; \ C
for(int i = 0;i<6;i++) \ D
{
25
printf("value in array %d and address is %16lu,*b,b);
b++; // increase by 2 bytes \ E
}
}
Explanation
Statement A declares a two-dimensional array of the size 3 × 2.
The size of the array is 3 × 2, or 6.
Each array element is accessed using two subscripts.
You can use two for loops to access the array. Since i is used for
accessing a row, the outer loop prints elements row-wise, that is, for
each value of i, all the column values are printed.
You can access the element of the array by using a pointer.
Statement B assigns the base address of the array to the pointer.
The for loop at statement C increments the pointer and prints the value
that is pointed to by the pointer. The number of iterations done by the
for loop, 6, is equal to the array.
Using the output, you can verify that C is using row measure form for
storing a two dimensional array.
26
Fig 1 Array Representation of Sparse Matrix
In above example matrix, there are only 6 non-zero elements ( those are 9,
8, 4, 2, 5 & 2) and matrix size is 5 X 6. We represent this matrix as shown
in the above image. Here the first row in the right side table is filled with
values 5, 6 & 6 which indicates that it is a sparse matrix with 5 rows, 6
columns & 6 non-zero values. The second row is filled with 0, 4, & 9
which indicates the non-zero value 9 is at the 0th-row 4th column in the
Sparse matrix. In the same way, the remaining non-zero values also follow
a similar pattern.
4 Linked Representation
4.1 In linked representation, we use a linked list data structure to represent
a sparse matrix. In this linked list, we use two different nodes
namely header node and element node. Header node consists of three
fields and element node consists of five fields as shown in the image.
4.2 Consider the above same sparse matrix used in the Triplet
representation. This sparse matrix can be represented using linked
representation as shown in the below image.
27
Fig 3 Linked Representation of Sparse Matrix
1 Advantages
1.1 Arrays represent multiple data items of the same type using a single
name.
1.2 Arrays allocate memory in contiguous memory locations for all its
elements. Hence there is no chance of extra memory being allocated in
case of arrays. This avoids memory overflow or shortage of memory in
arrays.
1.3 In arrays, the elements can be accessed randomly by using the index
number.
1.4 Using arrays, other data structures like linked lists, stacks, queues,
trees, graphs etc can be implemented.
1.5 Two-dimensional arrays are used to represent matrices.
2 Disadvantages
2.1 The number of elements to be stored in an array should be known in
advance.
2.2 An array is a static structure (which means the array is of fixed size).
Once declared the size of the array cannot be modified. The memory
which is allocated to it cannot be increased or decreased.
28
2.3 Insertion and deletion are quite difficult in an array as the elements are
stored in consecutive memory locations and the shifting operation is
costly.
2.4 Allocating more memory than the requirement leads to wastage of
memory space and less allocation of memory also leads to a problem.
2.7 REFERENCES
Textbook
1 An Introduction to Data Structure with Applications, Jean – Paul
Tremblay and Paul Sorenson Tata MacGraw Hill 2 nd 2007.
2 Schaum’s Outlines Data structure Seymour Lipschutz Tata McGraw Hill
2 nd 2005.
Useful Links
1 Nptel Course of Data Structure-
https://nptel.ac.in/courses/106/102/106102064/
29
Unit II
30
For example:
Cat, Dog, Lion, Elephant
We can add more elements in the list at any place beginning, at
middle position or at end position.
31
Disadvantages of Linked List:
Memory Usage-The memory is wasted as pointers require extra
memory for storage.
No element can be accessed randomly; it has to access each node
sequentially.
Time Consuming
Heap Space Restriction
Reverse Traversing is difficult.
Data accessing is very slow.
No cache Memory Support
32
3.3 REPRESENTATION OF LINKED LIST NODE
Let's see how each node of the linked list is represented. Each node
consists:
A data element
An address of another node
We wrap both the data item and the next node reference in a struct as:
struct node
{
int data;
struct node *next;
};
typedef struct node *node; //Define node as pointer of data type struct
node
33
Doubly Linked List
The node in a doubly-linked list has two address parts; one part
stores the address of the next while the other part of the node stores
the previous node's address. The initial node in the doubly linked list has
the NULL value in the address part, which provides the address of the
previous node. Elements can be navigated forward and backward. The
representation of the doubly linked list as shown below:
It is defined by:
void *malloc (number_of_bytes)
void * is returned this pointer can be converted to any type.
35
For example: char *cp;
cp = (char *) malloc (100);
Attempts to get 100 bytes and assigns the starting address to cp. We can
also use the sizeof() function to specify the number of bytes.
For example,
int *ip;
ip = (int *) malloc (100*sizeof(int));
free() is the opposite of malloc(), which de-allocates memory. The
argument to free() is a pointer to a block of memory in the heap a pointer
which was obtained by a malloc() function.
which will be
pointing to next node of the list? This is called as self-referential structure.
Figure 3.5.1. Structure definition, singly link node and empty list
36
3.5.1. Creation of linked list.
3.5.2. Insertion of any element in the linked list.
3.5.3. Deletion any element from the linked list.
3.5.4. Traversing/Display of the linked list.
Step 3 : If the list is not empty, follow the steps given below:
37
Fig.3.5.1.2.Pictorial Representation of Creation of singly linked list
void createslist(int n)
{
int i;
node * newnode;
node *temp;
for( i = 0; i < n ; i++)
{
newnode = getnode();
if(start == NULL)
{
start = newnode;
}
else
38
{
temp = start;
while(temp -> next != NULL)
temp = temp -> next;
temp -> next = newnode;
}
}
}
newnode = getnode();
start = newnode.
39
The function insert_at_beg(), is used for inserting a node at the
beginning
void insert_at_beg()
{
node *newnode;
newnode = getnode();
if(start == NULL)
{
start = newnode;
}
else
{
newnode -> next = start;
start = newnode;
}
}
start = newnode.
temp = start;
while(temp -> next != NULL)
temp = temp -> next;
temp -> next = newnode;
Step 2: Ensure that the specified position is in between first node and last
node. If not, specified position is invalid. This is done by countnode()
function.
Step 3: Store the starting address (which is in start pointer) in temp and
temp1 pointers. Then traverse the temp pointer upto the specified position
followed by temp1pointer.
Step 4: After reaching the specified position, follow the steps given below:
temp -> next = newnode; newnode -> next = temp;
41
void insert_at_mid()
{
node *newnode, *temp1, *temp;
intpos, nodectr, ctr = 1;
newnode = getnode();
printf("\n Enter the position: ");
scanf("%d", &pos);
nodectr = countnode(start);
if(pos> 1 &&pos<nodectr)
{
temp = temp1 = start;
while(ctr<pos)
{
temp = temp1;
temp1 = temp1 -> next;
ctr++;
}
temp -> next = newnode;
newnode -> next = temp1;
}
else
{
printf("position %d is not a middle position", pos);
}
}
Step 2: If the list is not empty, follow the steps given below:
temp = start;
start = start -> next;
free(temp);
42
Fig. 3.5.3.1.Delete node from beginning position
The function delete_at_beg(), is used for deleting the first node in the list.
void delet_eat_beg()
{
node *temp;
if(start == NULL)
{
printf("\n No nodes are exist..");
return ;
}
else
{
temp = start;
start = temp -> next;
free(temp);
printf("\n Node deleted ");
}
}
43
Fig. 3.5.3.2.Delete node from end position
The function delete_at_last(), is used for deleting the last node in the list.
void delete_at_last()
{
node *temp, *temp1;
if(start == NULL)
{
printf("\n Empty List..");
return ;
}
else
{
temp = temp1=start;
while(temp -> next != NULL)
{
temp1= temp;
temp = temp -> next;
}
temp1 -> next = NULL;
free(temp);
printf("\n Node deleted ");
}
}
44
temp1 -> next = temp -> next;
free(temp);
printf("\n node deleted..");
}
Thefunctiondelete_at_mid(),isusedfordeletingtheintermediatenodeinthelist.
void delete_at_mid()
{
intctr = 1, pos, nodectr;
node *temp, *temp1;
if(start == NULL)
{
printf("\n Empty List..");
return ;
}
else
{
printf("\n Enter position of node to delete: ");
scanf("%d", &pos);
nodectr = countnode(start);
if(pos>nodectr)
{
printf("\nThis node doesnot exist");
}
if(pos> 1 &&pos<nodectr)
{
temp = temp1 = start;
while(ctr<pos)
{
temp1 = temp;
temp = temp -> next;
ctr ++;
}
temp1 -> next = temp -> next;
free(temp);
printf("\n Node deleted..");
}
else
45
46
47
return (count);
}
void createslist(int n)
{
int i;
node *newnode;
node *temp;
for(i = 0; i < n; i++)
{
newnode = getnode();
if(start == NULL)
{
start = newnode;
}
else
{
temp = start;
while(temp -> next != NULL)
temp = temp -> next;
temp -> next = newnode;
}
}
}
void traverse()
{
node *temp;
temp = start;
printf("\n The contents of List (Left to Right): \n");
if(start == NULL)
{
printf("\n Empty List");
return;
}
else
{
while(temp != NULL)
{
printf("%d-->", temp -> data);
temp = temp -> next;
}
}
printf(" NULL ");
}
void insert_at_beg()
{
node *newnode;
newnode = getnode();
if(start == NULL)
{
start = newnode;
48
}
else
{
newnode -> next = start;
start = newnode;
}
}
void insert_at_end()
{
node *newnode, *temp;
newnode = getnode();
if(start == NULL)
{
start = newnode;
}
else
{
temp = start;
while(temp -> next != NULL)
temp = temp -> next;
temp -> next = newnode;
}
}
void insert_at_mid()
{
node *newnode, *temp1, *temp;
intpos, nodectr, ctr = 1;
newnode = getnode();
printf("\n Enter the position: ");
scanf("%d", &pos);
nodectr = countnode(start);
if(pos> 1 &&pos<nodectr)
{
temp = temp1 = start;
while(ctr<pos)
{
temp = temp1;
temp1 = temp1 -> next;
ctr++;
}
temp -> next = newnode;
newnode -> next = temp1;
}
else
{
printf("position %d is not a middle position", pos);
}
}
void delete_at_beg()
49
{
node *temp;
if(start == NULL)
{
printf("\n No nodes are exist..");
return ;
}
else
{
temp = start;
start = temp -> next;
free(temp);
printf("\n Node deleted ");
}
}
void delete_at_last()
{
node *temp, *temp1;
if(start == NULL)
{
printf("\n Empty List..");
return ;
}
else
{
temp = temp1=start;
while(temp -> next != NULL)
{
temp1= temp;
temp = temp -> next;
}
temp1 -> next = NULL;
free(temp);
printf("\n Node deleted ");
}
}
void delete_at_mid()
{
intctr = 1, pos, nodectr;
node *temp, *temp1;
if(start == NULL)
{
printf("\n Empty List..");
return ;
}
else
{
printf("\n Enter position of node to delete: ");
scanf("%d", &pos);
nodectr = countnode(start);
50
if(pos>nodectr)
{
printf("\nThis node doesnot exist");
}
if(pos> 1 &&pos<nodectr)
{
temp = temp1 = start;
while(ctr<pos)
{
temp1 = temp;
temp = temp -> next;
ctr ++;
}
temp1 -> next = temp -> next;
free(temp);
printf("\n Node deleted..");
}
else
{
printf("\n Invalid position..");
getch();
}
}
}
void main(void)
{
intch, n;
clrscr();
while(1)
{
ch = menu();
switch(ch)
{
case 1:
if(start == NULL)
{
printf("\n Number of nodes you want to create: ");
scanf("%d", &n);
createslist(n);
printf("\n List created..");
}
else
printf("\n List is already created..");
break;
case 2:
insert_at_beg();
break;
case 3:
insert_at_end();
break;
51
case 4:
insert_at_mid();
break;
case 5:
delete_at_beg();
break;
case 6:
delete_at_last();
break;
case 7:
delete_at_mid();
break;
case 8:
traverse();
break;
case 9:
printf("\n No of nodes : %d ", countnode(start));
break;
case 10 :
exit(0);
}
getch();
}
}
52
The linked List is-
1->2->3
4->5->6
/* merges the two linked lists, restricting the common elements to occur
only once in the final list */
void merge ( struct node *l1, struct node *l2, struct node **newnode)
{
struct node *l3=NULL ;
/* traverse both linked lists till the end. If end of any one list is
reached loop is terminated */
while ( l1 != NULL &&l2 != NULL )
{
/* if node being added in the first node */
if ( *newnode == NULL )
{
*newnode = malloc(sizeof ( struct node ) ) ;
l3= *newnode ;
}
else
{
l3->next= malloc(sizeof ( struct node ) ) ;
l3 = l3 ->next ;
}
if ( l1 -> data <l2 -> data )
{
l3 -> data = l1 ->data ;
l1 = l1 ->next ;
}
else
{
if ( l2 -> data <l1 -> data )
{
l3 -> data = l2->data ;
l2 = l2 ->next ;
}
else
{
if ( l1 -> data == l2 -> data )
{
l3 -> data = l2 ->data ;
l1 = l1 ->next ;
53
l2 = l2->next ;
}
}
}
}
54
3.7.4 Reversing the Linked List:
void reverse()
{
Node* temp1,*temp2,*temp3;
temp1=start;
If(temp1==NULL)
{
\
getch();
}
else
{
temp2=NULL;
while(temp1!=NULL)
{
temp3=temp2;
temp2=temp1;
temp1=temp1->next;
temp2=temp2->next;
}
start=temp2;
}
\
}
List is :
12345
List is :
67
3.8 SUMMARY
The malloc() is used for allocation of anode and free()is used for de-
allocation operation.
The singly linked list has only forward pointer and no backward link is
provided. Hence the traversing of the list is possible only in one
direction.
Backward traversing is not possible.
Insertion and deletion operations are less efficient because for
inserting the element at desired position the list needs to be traversed.
Similarly traversing of the list is required for locating the element
which needs to be deleted.
https://sites.google.com/site/datastructuresite/Home-Page/books
https://www.hackerearth.com/practice/data-structures/linked-list/singly-
linked-list/tutorial/
3.10 BIBLIOGRAPHY
56
7. Jean-Paul Tremblay and Paul G. Sorenson, An Introduction to Data
Structures with Applications, Tata McGraw Hill
8. Tanenbaum, Data Structures using C & C++, PHI
9. Robert L. Kruse, Data Structures and Program Design in C, PHI
10.
57
4
LINKED LIST-II
Unit Structure :
4.0 Objectives
4.1 Introduction
4.2 Doubly Linked List
4.3 Applications of doubly linked list
4.4 Comparison between singly linked list and doubly linked list
4.5 Operations on doubly linked list
4.5.1 Creation of doubly linked list.
4.5.2 Insertion of any element in the linked list.
4.5.3 Deletion any element from the linked list.
4.5.4 Traversing/Display of the linked list.
4.6 Program on implementation of Doubly Linked List
4.7 Circular Linked List
4.8 Applications of circular linked list
4.9 Operations on doubly linked list
4.9.1 Creation of circular linked list.
4.9.2 Insertion of any element in the linked list.
4.9.3 Deletion any element from the linked list.
4.9.4 Traversing/Display of the linked list.
4.10 Program on implementation of Circular Singly Linked List
4.11 Representation of linked list using header node
4.12 Representation of Polynomial using Linked List
4.13 Representation of Sparse Matrix using Linked List
4.14 Summary
4.15 List of References
4.16 Bibliography
4.17 Unit End Exercises
4.0 OBJECTIVES
A double linked list is a two-way list in which all nodes will have
two links. This helps in accessing both successor node and predecessor
node from the given node position. It provides bi-directional traversing.
Each node contains three fields:
Prev link.
Data.
Next link.
The prev link points to the predecessor node and the next link
points to the successor node. The data field stores the required data. Many
applications require searching forward and backward through nodes of a
list. For example searching for a name in a telephone directory is popular
example.
59
structdlink list
{ Node
int data; Struct prev data next
structdlink list* next, * prev; ure:
};
typedefstructdlinklist node; Empty List: NULL
node *start = NULL;
Start=NULL
Figure 4.2 Structure definition, doubly link node and empty list
The prev part of the first node and the next part of the last node
will always contain null indicating end in each direction. There are various
operations which can be performed on doubly linked list.
The elements can be accessed using The elements can be accessed using
next link both previous link as well as next
link
It is not required extra field .Hence One filed is required to store
node takes less memory in SLL previous link .Hence node takes
more memory in DLL
Less efficient access to elements More efficient access to elements
60
4.5 OPERATIONS ON DOUBLY LINKED LIST
number of nodes:
Get the new node using getnode().
newnode =getnode();
If the list is empty then start =temp= newnode
If the list is not empty, follow the steps given below:
temp-> n e x t =newnode;
newnode->prev=temp;
61
4.5.2. Insertion of any element in the linked list.
Inserting a node in the doubly linked list, there are 3 cases-
Inserting a node at beginning position
Inserting node at last position
Inserting node at intermediate position.
Inserting a node at the beginning:
The following algorithm steps are to be followed to insert a newnode
at the beginning of the list:
Cerate the newnode using getnode().
newnode=getnode();
If the list is empty then start=newnode.
If the list is not empty, follow the steps
given below:
newnode->next= start;
start->prev=newnode;
start=newnode;
62
Fig.4.4.Shows inserting a node into the double linked list at the
beginning.
Inserting a node at the end:
The following algorithm steps are followed to insert a newnode at the
end of the list:
Figure 4.5 shows inserting a node into the double linked list at the
end.
Inserting a node at an intermediate position:
The following algorithm steps are followed, to insert a new node in an
intermediate position in thelist:
63
Check that the specified position is in between first node and last node.
If not, specified position is invalid. This is done by countnode() function.
Store the starting address (which is in start pointer) in temp and prev
pointers. Then traverse the temp pointer upto the specified position
followed by prev pointer.
After reaching the specified position, follow the steps given below:
newnode -> next= temp -> next;
newnode->prev =temp;
temp -> next ->prev = newnode;
temp->next=newnode;
Figure 4.6 shows inserting a node into the double linked list at a
specified intermediate position other than beginning and end.
64
Figure 4.7 Delete a node from beginning position
The following steps are followed to delete a node at the end of the list:
65
specified position is in between first node and last node.If
not, specified position is invalid.
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
struct dlinklist
{
structdlinklist *prev;
int data;
structdlinklist *next;
};
66
typedef struct dlinklist node;
node *start = NULL;
node* getnode()
{
node * newnode;
newnode = (node *) malloc(sizeof(node));
printf("\n Enter data: ");
scanf("%d", &newnode -> data);
newnode ->prev = NULL;
newnode -> next = NULL;
returnnewnode;
}
int countnode(node *start)
{
if(start == NULL)
return 0;
else
return 1 + countnode(start -> next);
}
int menu()
{
intch;
clrscr();
printf("\n 1.Create");
printf("\n------------------------------");
printf("\n 2. Insert a node at beginning ");
printf("\n 3. Insert a node at end");
printf("\n 4. Insert a node at middle");
printf("\n------------------------------");
printf("\n 5. Delete a node from beginning");
printf("\n 6. Delete a node from Last");
printf("\n 7. Delete a node from Middle");
printf("\n------------------------------");
printf("\n 8. Traverse the list in forward direction ");
printf("\n 9. Traverse the list from backward direction ");
printf("\n------------------------------");
printf("\n 10.Count the Number of nodes in the list");
printf("\n 11.Exit");
printf("\n\n Enter your choice: ");
scanf("%d", &ch);
returnch;
}
void createdlist(int n)
{
int i;
node *newnode;
node *temp;
for(i = 0; i < n; i++)
{
newnode = getnode();
67
if(start == NULL)
start = newnode;
else
{
temp = start;
while(temp -> next)
temp = temp -> next;
temp -> next = newnode;
newnode ->prev = temp;
}
}
}
void traverse_forward()
{
node *temp;
temp = start;
printf("\n The contents of List: ");
if(start == NULL )
printf("\n Empty List");
else
{
while(temp != NULL)
{
printf("\t %d ", temp -> data);
temp = temp -> next;
}
}
}
void traverse_backward()
{
node *temp;
temp = start;
printf("\n The contents of List: ");
if(start == NULL)
printf("\n Empty List");
else
{
while(temp -> next != NULL)
temp = temp -> next;
}
while(temp != NULL)
{
printf("\t%d", temp -> data);
temp = temp ->prev;
}
}
void dll_insert_beg()
{
node *newnode;
newnode = getnode();
68
if(start == NULL)
start = newnode;
else
{
newnode -> next = start;
start ->prev = newnode;
start = newnode;
}
}
void dll_insert_end()
{
node *newnode, *temp;
newnode = getnode();
if(start == NULL)
start = newnode;
else
{
temp = start;
while(temp -> next != NULL)
temp = temp -> next;
temp -> next = newnode;
newnode ->prev = temp;
}
}
void dll_insert_mid()
{
node *newnode,*temp;
intpos, nodectr, ctr = 1;
newnode = getnode();
printf("\n Enter the position: ");
scanf("%d", &pos);
nodectr = countnode(start);
if(pos - nodectr>= 2)
{
printf("\n Position is out of range..");
return;
}
if(pos> 1 &&pos<nodectr)
{
temp = start;
while(ctr<pos - 1)
{
temp = temp -> next;
ctr++;
}
newnode ->prev = temp;
newnode -> next = temp -> next;
temp -> next ->prev = newnode;
temp -> next = newnode;
}
69
else
printf("position %d of list is not a middle position ", pos);
}
void dll_delete_beg()
{
node *temp;
if(start == NULL)
{
printf("\n Empty list");
getch();
return ;
}
else
{
temp = start;
start = start -> next;
start ->prev = NULL;
free(temp);
}
}
void dll_delete_last()
{
node *temp;
if(start == NULL)
{
printf("\n Empty list");
getch();
return ;
}
else
{
temp = start;
while(temp -> next != NULL)
temp = temp -> next;
temp ->prev -> next = NULL;
free(temp);
temp = NULL;
}
}
void dll_delete_mid()
{
int i = 0, pos, nodectr;
node *temp;
if(start == NULL)
{
printf("\n Empty List");
getch();
return;
}
else
70
{
printf("\n Enter the position of the node to delete: ");
scanf("%d", &pos);
nodectr = countnode(start);
if(pos>nodectr)
{
printf("\nthis node does not exist");
getch();
return;
}
if(pos> 1 &&pos<nodectr)
{
temp = start;
i= 1;
while(i <pos)
{
temp = temp -> next;
i++;
}
temp -> next ->prev = temp ->prev;
temp ->prev -> next = temp -> next;
free(temp);
printf("\n node deleted..");
}
else
{
printf("\n It is not a middle position..");
getch();
}
}
}
void main(void)
{
intch, n;
clrscr();
while(1)
{
ch = menu();
switch(ch)
{
case 1 :
printf("\n Enter Number of nodes to create: ");
scanf("%d", &n);
createdlist(n);
break;
case 2 :
dll_insert_beg();
break;
case 3 :
dll_insert_end();
71
break;
case 4 :
dll_insert_mid();
break;
case 5 :
dll_delete_beg();
break;
case 6 :
dll_delete_last();
break;
case 7 :
dll_delete_mid();
break;
case 8 :
traverse_ forward ();
break;
case 9 :
traverse_backward();
break;
case 10 :
printf("\n Number of nodes: %d", countnode(start));
break;
case 11:
exit(0);
}
getch();
}
}
The linked list where the last node points the start node is called
circular linked list. A circular linked list has no beginning and no end. It is
necessary to establish a special pointer called start pointer always pointing
to the first node of the list. Hence we can move from last node to the start
node of the list very efficiently. Hence accessing of any node is much
faster than singly linked list. In circular linked list no null pointers are
used, hence all pointers contain valid address.
4.9.1.Creating
nodes:
newnode = getnode();
start = newnode;
temp = start;
while(temp -> next != NULL)
temp = temp -> next;
temp -> next = newnode;
73
Fig.4.10. Creation of circular linked list
newnode = getnode();
start = newnode;
newnode -> next = start;
temp = start;
while(temp -> next != start)
temp= temp -> next;
newnode -> next = start;
start = newnode;
temp -> next = start;
74
4.11. shows inserting a node into the circular single linked list at the
beginning.
newnode = getnode();
start = newnode;
newnode -> next = start;
temp = start;
while(temp -> next != start)
temp = temp -> next;
temp -> next = newnode;
newnode -> next = start;
The function cll_insert_end(), is used for inserting a node at the end.
Figure 4.12 shows inserting a node into the circular single linked list at the
end.
75
Inserting a node at intermediate position:
The following algorithm steps are followed, to insert a new node in an
intermediate position in the list:
Step 2: Ensure that the specified position is in between first node and last
node. If not, specified position is invalid. This is done by countnode()
function.
Step 3: Store the starting address (which is in start pointer) in temp and
prev pointers. Then traverse the temp pointer upto the specified position
followed by prev pointer.
Step 4: After reaching the specified position, follow the steps given below:
temp1 -> next = newnode;
newnode -> next = temp;
position be 3.
Figure 4.13 shows inserting a node into the double linked list at a
specified intermediate position other than beginning and end.
temp = start;
temp1 = start;
while(temp -> next != start)
{
temp1=temp;
temp = temp -> next;
}
temp1 -> next = start;
start = NULL.
The function cll_delete_last(), is used for deleting the last node in the list.
77
if(pos> 1 &&pos<nodectr)
{
temp = temp1 = start; ctr = 1;
while(ctr<pos)
{
temp1 = temp;
temp = temp -> next;
ctr++;
}
temp1 -> next = temp -> next;
free(temp);
printf("\n node deleted..");
}
# include <stdio.h>
# include <conio.h>
# include <stdlib.h>
struct cslinklist
{
78
int data;
struct cslinklist *next;
};
typedef struct cslinklist node;
node *start = NULL;
int nodectr;
node* getnode()
{
node * newnode;
newnode = (node *) malloc(sizeof(node));
printf("\n Enter data: ");
scanf("%d", &newnode -> data);
newnode -> next = NULL;
returnnewnode;
}
int menu()
{
intch;
clrscr();
printf("\n 1. Create a list ");
printf("\n\n--------------------------");
printf("\n 2. Insert a node at beginning ");
printf("\n 3. Insert a node at end");
printf("\n 4. Insert a node at middle");
printf("\n\n--------------------------");
printf("\n 5. Delete a node from beginning");
printf("\n 6. Delete a node from Last");
printf("\n 7. Delete a node from Middle");
printf("\n\n--------------------------");
printf("\n 8. Display the list");
printf("\n 9. Exit");
printf("\n\n--------------------------");
printf("\n Enter your choice: ");
scanf("%d", &ch);
returnch;
}
void createlist(int n)
{
int i;
node *newnode,*temp;
nodectr = n;
for(i = 0; i < n ; i++)
{
newnode = getnode();
if(start == NULL)
{
start = newnode;
}
else
{
79
temp = start;
while(temp -> next != NULL)
temp = temp -> next;
temp -> next = newnode;
}
}
newnode ->next = start; /* last node is pointing to starting node */
}
void display()
{
node *temp;
temp = start;
printf("\n The contents of List (Left to Right): ");
if(start == NULL )
printf("\n Empty List");
else
{
do
{
printf("\t %d ", temp -> data);
temp = temp -> next;
} while(temp != start);
printf(" NULL ");
}
}
void cll_insert_beg()
{
node *newnode, *temp;
newnode = getnode();
if(start == NULL)
{
start = newnode;
newnode -> next = start;
}
else
{
temp = start;
while(temp -> next != start)
temp= temp -> next;
newnode -> next = start;
start = newnode;
temp -> next = start;
}
printf("\n Node inserted at beginning..");
nodectr++;
}
void cll_insert_end()
{
node *newnode, *temp;
newnode = getnode();
80
if(start == NULL )
{
start = newnode;
newnode -> next = start;
}
else
{
temp = start;
while(temp -> next != start)
temp = temp -> next;
temp -> next = newnode;
newnode -> next = start;
}
printf("\n Node inserted at end..");
nodectr++;
}
void cll_insert_mid()
{
node *newnode, *temp, *prev;
int i, pos ;
newnode = getnode();
printf("\n Enter the position: ");
scanf("%d", &pos);
if(pos> 1 &&pos<nodectr)
{
temp = start;
temp1= temp;
i= 1;
while(i <pos)
{
temp1 = temp;
temp = temp -> next;
i++;
}
temp1 -> next = newnode;
newnode -> next = temp;
nodectr++;
printf("\n Node inserted at middle..");
}
else
{
printf("position %d of list is not a middle position ", pos);
}
}
void cll_delete_beg()
{
node *temp, *last;
if(start == NULL)
{
printf("\n No nodes exist..");
81
getch();
return ;
}
else
{
last = temp = start;
while(last -> next != start)
last= last -> next;
start = start -> next;
last -> next = start;
free(temp);
nodectr--;
printf("\n Node deleted..");
if(nodectr == 0)
start = NULL;
}
}
void cll_delete_last()
{
node *temp,*prev;
if(start == NULL)
{
printf("\n No nodes exist..");
getch();
return ;
}
else
{
temp = start;
temp1 = start;
while(temp -> next != start)
{
temp1= temp;
temp = temp -> next;
}
temp1 -> next = start;
free(temp);
nodectr--;
if(nodectr == 0)
start = NULL;
printf("\n Node deleted..");
}
}
void cll_delete_mid()
{
int i = 0, pos;
node *temp, *prev;
if(start == NULL)
{
printf("\n No nodes exist..");
82
getch();
return ;
}
else
{
printf("\n Which node to delete: ");
scanf("%d", &pos);
if(pos>nodectr)
{
printf("\nThis node does not exist");
getch();
return;
}
if(pos> 1 &&pos<nodectr)
{
temp=start;
temp1 = start;
i= 0;
while(i <pos - 1)
{
temp1 = temp;
temp = temp -> next ;
i++;
}
temp1 -> next = temp -> next;
free(temp);
nodectr--;
printf("\n Node Deleted..");
}
else
{
printf("\n It is not a middle position..");
getch();
}
}
}
void main(void)
{
int result;
intch, n;
clrscr();
while(1)
{
ch = menu();
switch(ch)
{
case 1 :
if(start == NULL)
{
printf("\n Enter Number of nodes to create: ");
83
scanf("%d", &n);
createlist(n);
printf("\nList created..");
}
else
printf("\n List is already Exist..");
break;
case 2 :
cll_insert_beg();
break;
case 3 :
cll_insert_end();
break;
case 4 :
cll_insert_mid();
break;
case 5 :
cll_delete_beg();
break;
case 6 :
cll_delete_last();
break;
case 7 :
cll_delete_mid();
break;
case 8 :
display();
break;
case 9 :
exit(0);
}
Such a node does not represent an item in the linked list. The
information part of this node can be used to store any global information
about the whole linked list. A header node is a special dummy node found
at the front of the list. The use of header node is an alternative to remove
the first node in a list.
84
For example, the picture below
87
printf("\nEnter Second Polynomial..(in ascending-order of
exponent)");
poly2 = create_poly (poly2);
clrscr();
printf("\n Enter Polynomial 1: ");
display (poly1);
printf("\n Enter Polynomial 2: ");
display (poly2);
getch();
}
88
2. Column: It is an index of the column where a non-zero element is
located.
3. Value: The value of the non-zero element is located at the index (row,
column).
1 0 0 -4
0 6 0 0
0 0 7 0
0 5 0 0
89
Fig.4.19. Representation of Sparse Matrix using Linked List
4.14 SUMMARY
The doubly linked list has two pointer fields. One field is previous link
field and another is next link field. By using these two pointers we can
access any node efficiently whereas in singly linked list only one
pointer field which stores forward pointer.
In circular list the next pointer of last node points to start node,
whereas in doubly linked list each node has two pointers. The main
advantage of circular list over doubly linked list is that with the help of
single pointer field we can access start node quickly. So amount of
memory get saved.
The header node is the first node of linked list. This node is useful for
getting starting address of linked list.
Polynomials and Sparse Matrix are two important applications of
arrays and linked lists.
1. https://sites.google.com/site/datastructuresite/Home-Page/books
2. https://www.hackerearth.com/practice/data-structures/linked-
list/singly-linked-list/tutorial/
3. https://dscet.ac.in/questionbank/cse/third-sem/CS8391-DATA-
STRUCTURES.pdf
4.16 Bibliography
1.
at the end of a Doubly Linked List.
2. What is difference between the singly and doubly link list. Mention
the significance of a circular linked list.
3. What is doubly linked list? What advantages does a doubly linked
list have over linear linked lists?
4. How a linked list can be used to represent a polynomial of type:-
9x2y2-8xy2+10xy+9y2
5. Describe the applications of linked list on polynomial Expressions.
6. Describe the operations are performed on Circular Linked List.
7. Explain the operations are performed on the singly linked list.
8. What is header node and what is the use of it?
9. Write a C function to find product of all elements of Linked List?
10. What are advantages of doubly linked list over singly linked list?
11. Why the linked list is used for representation of polynomial?
12. What are advantages of circular linked list over doubly linked list?
13. Write program to implement circular linked list.
14. Write program to implement doubly linked list.
15. What is Circular Linked List? State the advantages and
disadvantages of Circular Link List Over Doubly Linked List and
Singly Linked List
91
Unit III
5
STACK
Unit Structure
5.0 Objectives
5.1 Introduction
5.2 Operations on the Stack Memory Representation of Stack
5.3 Array Representation of Stack
5.4 Applications of Stack
5.4.1 Evaluation of Arithmetic Expression
5.4.2 Matching Parenthesis
5.4.3 Infix and postfix operations
5.4.4 Memory management
5.4.5 Recursion
5.5 Summary
5.6 References
5.7 Unit End Exercise
5.0 OBJECTIVES
5.1 INTRODUCTION
92
Stack is an ordered list of similar data type.
Stack is a LIFO (Last in First out) structure or we can say FILO (First
in Last out).
push() function is used to insert new elements into the Stack
and pop() function is used to remove an element from the stack. Both
insertion and removal are allowed at only one end of Stack called Top.
Stack is said to be in Overflow state when it is completely full and is
said to be in Underflow state if it is completely empty.
Basic Operations:
93
Stack operations may involve initializing the stack, using it and then
de-initializing it. Apart from these basic stuffs, a stack is used for the
following two primary operations
push() Pushing (storing) an element on the stack.
pop() Removing (accessing) an element from the stack.
When data is Pushed onto stack. To use a stack efficiently, we need to
check the status of stack as well.
For the same purpose, the following functionality is added to stacks
peek() get the top data element of the stack, without removing it.
isFull() check if stack is full.
isEmpty() check if stack is empty.
At all times, we maintain a pointer to the last Pushed data on the stack.
As this pointer always represents the top of the stack, hence
named top.
The top pointer provides top value of the stack without actually
removing it.
// main function
int main() {
Stack s1;
s1.push(10);
s1.push(100);
}
95
Position of Top Status of Stack
-1 Stack is Empty
0 Only one element in Stack
N-1 Stack is Full
N Overflow state of Stack
Example:
We are given a stack of elements: 12, 08, 21, 33, 18, 40.
96
Step1:
Push (40)
Top = 40
Element is inserted at a[5]
Step2:
Push (18)
Top = 18
Element is inserted at a[4]
Step3:
Push (33)
Top = 33
Element is inserted at a[3]
Step 4:
Push (21)
Top = 21
Element is inserted at a[2]
Step 5:
Push (8)
Top = 8
Element is inserted at a[1]
Step 6:
Push (12)
Top = 12
Element is inserted at a[0]
97
Step 7:
Top = -1
End of array
// Push function here, inserts value in stack and increments stack top by 1
void push (struct Stack* stack, int item)
{
if (isFull(stack))
return;
stack->array[++stack->top] = item;
printf("We have pushed %d to stack\n", item);
}
int main ()
{
struct Stack* stack = create (10);
push(stack, 5);
push(stack, 10);
push(stack, 15);
int flag=1;
while(flag)
{
if(! isEmpty(stack))
printf("We have popped %d from stack\n", pop(stack));
else
printf("Can't Pop stack must be empty\n");
printf("Do you want to Pop again? Yes: 1 No: 0\n");
scanf("%d",&flag);
}
return 0;
}
Output:
We have pushed 5 to stack
99
We have pushed 10 to stack
We have pushed 15 to stack
We have popped 15 from the stack
Do you want to Pop again? Yes: 1 No: 0
0
100
Consider the above-mentioned unbalanced expressions:
The first expression (a + b is unbalanced as there is no closing
parenthesis given.
The second expression [ (c - d * e] is unbalanced as the closed
round parenthesis is not given.
The third expression { [( ] ) } is unbalanced as the nesting of
square parenthesis and the round parenthesis are incorrect.
Steps to find whether a given expression is balanced or unbalanced
Input the expression and put it in a character stack.
Scan the characters from the expression one by one.
If the scanned character is a starting bracket (‘(‘or ‘{‘or ‘[ ‘), then
push it to the stack.
If the scanned character is a closing bracket (‘)’ or ‘}’ or ‘]’), then
pop from the stack and if the popped character is the equivalent
starting bracket, then proceed. Else, the expression is unbalanced.
After scanning all the characters from the expression, if there is
any parenthesis found in the stack or if the stack is not empty, then
the expression is unbalanced.
101
Step 6: If there is more input, go to Step 1.
Step 7: If there is no more input, delete the remaining operators to output.
efg-+he-sh-o+/* NULL
fg-+he-sh-o+/* “e”
g-+he-sh-o+/* “f”
“e”
-+he-sh-o+/* “g”
“f”
“e”
+he-sh-o+/* “f”-“g”
“e”
he-sh-o+/* “e+f-g”
e-sh-o+/* “h”
“e+f-g”
-sh-o+/* “e”
“h”
“e+f-g”
sh-o+/* “h-e”
“e+f-g”
h-o+/* “s”
“h-e”
“e+f-g”
-o+/* “h”
“s”
“h-e”
“e+f-g”
o+/* “h-s”
“h-e”
“e+f-g”
+/* “o”
“s-h”
“h-e”
“e+f-g”
/* “s-h+o”
“h-e”
“e+f-g”
* “(h-e)/(s-h+o)”
“e+f-g”
NULL “(e+f-g) * (h-e)/(s-h+o)”
103
iii.Prefix to Infix:
Algorithm for Prefix to Infix Conversion
Step 1: The reversed input string is inserted into a stack ->
prefixToInfix(stack)
Step 2: If stack is not empty,
a. Temp -> pop the stack
b. If temp is an operator,
Write a opening parenthesis “(“to show -> prefixToInfix(stack)
Write temp to show -> prefixToInfix(stack)
Write a closing parenthesis “)” to show
c. Else If temp is a space ->prefixToInfix(stack)
d. Else, write temp to show if stack.top! = space -
>prefixToInfix(stack)
5.4.4Memory management:
The assignment of memory takes place in contiguous memory blocks.
We call this stack memory allocation because the assignment takes place
in the function call stack.
104
The size of the memory to be allocated is known to the compiler. When
a function is called, its variables get memory allocated on the stack.
When the function call is completed, the memory for the variables is
released. All this happens with the help of some predefined routines in the
compiler.
The user does not have to worry about memory allocation and release
of stack variables.
int main ()
{
// All these variables get memory
// allocated on stack
int f;
int a[10];
int c = 20;
int e[n];
}
The memory to be allocated to these variables is known to the compiler
and when the function is called, the allocation is done and when the
function terminates, the memory is released.
5.4.5 Recursion:
Some computer programming languages allow a module or function to
call itself. This technique is known as recursion.
In recursion, a function either calls itself directly or calls a
function that in turn calls the original function . The function is called
recursive function.
Example: a function calling itself.
int function (int value) {
if (value < 1)
return;
function (value - 1);
printf ("%d “, value);
}
Example a function that calls another function which in turn calls it
again.
int function1(int value1) {
if (value1 < 1)
return;
function2(value1 - 1);
printf ("%d ",value1);
}
int function2(int value2) {
function1(value2);
105
}
Properties:
A recursive function can go infinite like a loop. To avoid infinite running
of recursive function, there are two properties that a recursive function
must have
Base criteria There must be at least one base criteria or
condition, such that, when this condition is met the function stops
calling itself recursively.
Progressive approach The recursive calls should progress in
such a way that each time a recursive call is made it comes closer
to the base criteria.
5.5 SUMMARY
5.6 REFERENCES
1. https://www.tutorialspoint.com/
2. https://www.studytonight.com/
3. https://prepinsta.com/
4. https://www.tutorialride.com/
5. https://www.faceprep.in/
107
6
QUEUE
Unit Structure
6.0 Objectives
6.1 Introduction
6.2 Queue
6.3 Operations on the Queue
6.4 Memory Representation of Queue
6.5 Array representation of queue
6.6 Linked List Representation of Queue
6.7 Circular Queue
6.8 Deque
6.9 Priority Queue
6.10 Applications of Queues
6.11 Summary
6.12 Bibliography
6.13 Unit End Exercise
6.0 OBJECTIVES
6.1 INTRODUCTION
6.2 QUEUE
108
A good example of a queue is any queue of consumers for a resource
where the consumer that came first is served first. The difference
between stacks and queues is in removing. In a stack we remove the item
the most recently added; in a queue, we remove the item the least recently
added.
These are
peek() Gets the element at the front of the queue without removing it.
isfull() Checks if the queue is full.
isempty() Checks if the queue is empty.
Enqueue Operation
Queues maintain two data pointers, front and rear. Therefore, its
operations are comparatively difficult to implement than that of stacks.
109
The following steps should be taken to enqueue (insert) data into a
queue
rear = rear + 1;
queue[rear] = data;
return 1;
end procedure
Dequeue Operation
Accessing data from the queue is a process of two tasks access
the data where front is pointing and remove the data after access. The
following steps are taken to perform dequeue operation
return data;
}
110
6.4 MEMORY REPRESENTATION OF QUEUE
You don’t have to define the maximum number of elements in the queue.
Pointers (links) to store addresses of nodes for defining a queue are.
FRONT- address of the first element of the Linked list storing the Queue.
REAR- address of the last element of the Linked list storing the Queue.
The array implementation can not be used for the large scale
applications where the queues are implemented.
112
The storage requirement of linked representation of a queue with n
elements is o(n) while the time requirement for operations is o(1).
In a linked queue, each node of the queue consists of two parts i.e.
data part and the link part.
In the linked queue, there are two pointers maintained in the memory
i.e. front pointer and rear pointer. The front pointer contains the address of
the starting element of the queue while the rear pointer contains the
address of the last element of the queue.
The circular queue solves the major limitation of the normal queue.
In a normal queue, after a bit of insertion and deletion, there will be non-
usable empty space.
113
Here, indexes 0 and 1 can only be used after resetting the queue
(deletion of all elements).
6.8 DEQUE
In the first case, the enqueue operation takes place only at the rear,
but the dequeue operation takes place at both rear and front:
114
An input-restricted queue is useful when we need to remove an
item from the rear of the queue.
In the second case, the enqueue operation takes place at both rear
and front, but the dequeue operation takes place only at the front:
If two elements have the same priority, they are served according to
their order in the queue.
6.11 SUMMARY
116
6.12 BIBLIOGRAPHY
1. https://csveda.com/queue-applications-introduction-and-memory
representation/
2.
https://www.tutorialspoint.com/data_structures_algorithms/dsa_queue.htm
3. https://www.geeksforgeeks.org/queue-set-1introduction-and-array-
implementation/
4.https://www.javatpoint.com/array-representation-of-queue
5.https://www.programiz.com/dsa/circular-queue
6.https://www.baeldung.com/cs/types-of-queues
117