BRI304 Module 1
BRI304 Module 1
Module-I
Introduction: Data Structure, Classification (Primitive and non-operations. Pointers: Definition and Concepts,
Array of pointers, Structure and pointers
Linear Data Structures —Stacks: Introduction and Definition, Representation of stack: Array and structure
representation of stacks, Operations on stacks.
Stack Applications: Conversion of Expressions, Evaluation of expressions
Data Structure
Introduction
Data Structure can be defined as the group of data elements which provides an efficient way of storing and
organizing data in the computer so that it can be used efficiently. Some examples of Data Structures are
arrays, Linked List, Stack, Queue, etc. Data Structures are widely used in almost every aspect of Computer
Science i.e. Operating System, Compiler Design, Artificial intelligence, Graphics and many more.
Data Structures are the main part of many computer science algorithms as they enable the programmers to
handle the data in an efficient way. It plays a vital role in enhancing the performance of a software or a
program as the main function of the software is to store and retrieve the user's data as fast as possible.
Basic Terminology
Data structures are the building blocks of any program or the software. Choosing the appropriate data
structure for a program is the most difficult task for a programmer. Following terminology is used as far as
data structures are concerned.
Data: Data can be defined as an elementary value or the collection of values, for example, student's name
and its id are the data about the student.
Group Items: Data items which have subordinate data items are called Group item, for example, name of a
student can have first name and the last name.
Record: Record can be defined as the collection of various data items, for example, if we talk about the
student entity, then its name, address, course and marks can be grouped together to form the record for the
student.
File: A File is a collection of various records of one type of entity, for example, if there are 60 employees in
the class, then there will be 20 records in the related file where each record contains the data about each
employee.
Attribute and Entity: An entity represents the class of certain objects. it contains various attributes. Each
attribute represents the particular property of that entity.
Field: Field is a single elementary unit of information representing the attribute of an entity.
As applications are getting complex and amount of data is increasing day by day, there may arise the
following problems:
Processor speed: To handle very large amount of data, high speed processing is required, but as the data is
growing day by day to the billions of files per entity, processor may fail to deal with that much amount of
data.
Data Search: Consider an inventory size of 106 items in a store, If our application needs to search for a
particular item, it needs to traverse 106 items every time, results in slowing down the search process.
Multiple requests: If thousands of users are searching the data simultaneously on a web server, then there
are the chances that a very large server can be failed during that process in order to solve the above problems,
data structures are used. Data is organized to form a data structure in such a way that all items are not required
to be searched and required data can be searched instantly.
Efficiency: Efficiency of a program depends upon the choice of data structures. For example: suppose, we
have some data and we need to perform the search for a particular record. In that case, if we organize our
data in an array, we will have to search sequentially element by element. hence, using array may not be very
efficient here. There are better data structures which can make the search process efficient like ordered array,
binary search tree or hash tables.
Reusability: Data structures are reusable, i.e. once we have implemented a particular data structure, we can
use it at any other place. Implementation of data structures can be compiled into libraries which can be used
by different clients.
Abstraction: Data structure is specified by the ADT which provides a level of abstraction. The client
program uses the data structure through interface only, without getting into the implementation details.
Linear Data Structures: A data structure is called linear if all of its elements are arranged in the linear order.
In linear data structures, the elements are stored in non-hierarchical way where each element has the
successors and predecessors except the first and last element.
3. Stack
4. Queue
Arrays: An array is a collection of similar type of data items and each data item is called an element of the
array. The data type of the element may be any valid data type like char, int, float or double.
The elements of array share the same variable name but each one carries a different index number known as
subscript. The array can be one dimensional, two dimensional or
multidimensional.
The individual elements of the array age are:
age[0], age[1], age[2], age[3],......... age[98], age[99].
Linked List: Linked list is a linear data structure which is used to maintain a list in the memory. It can be
seen as the collection of nodes stored at non-contiguous memory locations. Each node of the list contains a
pointer to its adjacent node.
Stack: Stack is a linear list in which insertion and deletions are allowed only at one end, called top.
A stack is an abstract data type (ADT), can be implemented in most of the programming languages. It is
named as stack because it behaves like a real-world stack, for example: - piles of plates or deck of cards etc.
Queue: Queue is a linear list in which elements can be inserted only at one end called rear and deleted only
at the other end called front.
It is an abstract data structure, similar to stack. Queue is opened at both end therefore it follows First-In-
First-Out (FIFO) methodology for storing the data items.
If a data structure organizes the data in random order, then that data structure is called as Non-
Linear Data Structure.
Example
1. Tree
2. Graph
3. Dictionaries
4. Heaps
5. Tries, Etc.,
Types of Non Linear Data Structures are given below:
Trees: Trees are multilevel data structures with a hierarchical relationship among its elements known as
nodes. The bottommost nodes in the herierchy are called leaf node while the topmost node is called root
node. Each node contains pointers to point adjacent nodes.
Tree data structure is based on the parent-child relationship among the nodes. Each node in the tree can have
more than one children except the leaf nodes whereas each node can have atmost one parent except the root
node. Trees can be classfied into many categories which will be discussed later in this tutorial.
Graphs: Graphs can be defined as the pictorial representation of the set of elements (represented by vertices)
connected by the links known as edges. A graph is different from tree in the sense that a graph can have cycle
while the tree can not have the one.
Operations on data structure
1) Traversing: Every data structure contains the set of data elements. Traversing the data structure
means visiting each element of the data structure in order to perform some specific operation like searching
or sorting.
Example: If we need to calculate the average of the marks obtained by a student in 6 different subject, we
need to traverse the complete array of marks and calculate the total sum, then we will devide that sum by the
number of subjects i.e. 6, in order to find the average.
2) Insertion: Insertion can be defined as the process of adding the elements to the data structure at any
location.
If the size of data structure is n then we can only insert n-1 data elements into it.
3) Deletion:The process of removing an element from the data structure is called Deletion. We can
delete an element from the data structure at any random location.
If we try to delete an element from an empty data structure then underflow occurs.
4) Searching: The process of finding the location of an element within the data structure is called
Searching. There are two algorithms to perform searching, Linear Search and Binary Search. We will discuss
each one of them later in this tutorial.
5) Sorting: The process of arranging the data structure in a specific order is known as Sorting. There
are many algorithms that can be used to perform sorting, for example, insertion sort, selection sort, bubble
sort, etc.
6) Merging: When two lists List A and List B of size M and N respectively, of similar type of elements,
clubbed or joined to produce the third list, List C of size (M+N), then this process is called merging
Optimization of our code and improving the time complexity of one algorithm. Using pointers helps reduce the time
needed by an algorithm to copy data from one place to another. Since it used the memory locations directly, any
change made to the value will be reflected at all the locations.
Example:
• Call_by_value needs the value of arguments to be copied every time any operation needs to be performed.
• Call_by_reference makes this task easier using its memory location to update the value at memory locations.
Control Program Flow: Another use of pointers is to control the program flow. This is implemented by control tables
that use these pointers. These pointers are stored in a table to point to each subroutine’s entry point to be executed
one after the other. These pointers reference the addresses of the various procedures. This helps while working with
a recursive procedure or traversal of algorithms where there is a need to store the calling step’s location.
The next need of pointers arises in various secondary data structures such as linked lists or structures to point to the
next memory locations in the list.
StructNode{
intdata;
structNode*next;
};
Example:
Dynamic Memory Allocation: Many programming languages use dynamic memory allocations to allocate the
memory for run-time variables. For such type of memory, allocations heap is used rather than the stack, which uses
pointers. Here pointers hold the address of these dynamically generated data blocks or array of objects. Many
structured or OOPs languages use a heap or free store to provide them with storage locations. The last Node in the
linked list is denoted using a NULL pointer that indicates there is no element further in the list.
Defining a Pointer
Syntax:
<datatype> *variable_name
Example:
int *ptr1 // ptr1 referencestoa memory location that holds data of int datatype.
intvar30;
int*ptr1=&var;//pointertovar
int **ptr2 = & ptr1; // pointer to pointer variable ptr1
In the above example, ‘&’ is used to denote the unary operator, which returns a variable’s address.
And ‘*’ is a unary operator that returns the value stored at an address specified by the pointer variable, thus if we
need to get the value of variable referenced by a pointer, often called as dereferencing, we use:
print(“%d”,*ptr1)//prints30
print(“%d”,**ptr2) // prints 30
We need to specify datatype- It helps to identify the number of bytes data stored in a variable; thus. Simultaneously,
we increment a pointer variable, and it is incremented according to the size of this datatype only.
• Function pointer: This is a type of pointer to reference an executable code. It is mostly used in the recursive
procedure that holds the address of the code that needs to be executed later.
Disadvantage Of Pointers
It can lead to many programming errors as it allows the program to access a variable that has not been defined yet.
They can be easily manipulated as the number and made to point some void locations.
Thus to avoid such a situation, many programming languages have started using constructs. Programming languages
such as JAVA has replaced the concept of pointers with reference variables which can only be used to refer the
address of a variable and cannot be manipulated as a number.
Conclusion
Now we can easily conclude that pointers are the references to other memory locations used for the dynamic
implementation of various data structures and control its structure. The size of the pointer depends on the computer
architecture. Every programming language uses pointers in one way or another such as C/C++ etc.
ARRAYS
• An Array is defined as, an ordered set of similar data items. All the data items of an array are stored
in consecutive memory locations.
• The data items of an array are of same type and each data items can be accessed using the same
name but different index value.
• An array is a set of pairs, such that each index has a value associated with it. It can be called as
corresponding or a mapping
Ex: <index, value>
< 0 , 25 > list[0]=25
< 1 , 15 > list[1]=15
< 2 , 20 > list[2]=20
< 3 , 17 > list[3]=17
< 4 , 35 > list[4]=35
Here, list is the name of array. By using, list [0] to list [4] the data items in list can be accessed.
An abstract data type, sometimes abbreviated ADT, is a logical description of how we view the data and the
operations that are allowed without regard to how they will be implemented. This means that we are
concerned only with what data is representing and not with how it will eventually be constructed. By
providing this level of abstraction, we are creating an encapsulation around the data. The idea is that by
encapsulating
Structure Array is the details of
objects: A set of pairs <index, value> where for each value of the.
index there is a value from the set item. Index is a finite
ordered set of one or more dimensions, for example,
{0, … , n-1} for one dimension,
{(0,0),(0,1),(0,2),(1,0),(1,1),(1,2),(2,0),(2,1),(2,2)} for
two dimensions, etc.
Functions:
for all A Array, i index, x item, j, size integer
Array Create(j, list) ::= return an array of j dimensions where
list is a j-tuple whose ith element is
the size of the ith dimension. Items are
undefined.
Item Retrieve(A, i) ::= if (i index) return the item
associated with index value i
in array A
else return error
Array Store(A, i, x) ::= if (i in index) return an array that
is identical to array A except
the new pair
<i, x> has been inserted
else return error
end array
Abstract data type Array
implementation, we are hiding them from the user’s view. This is called information hiding. The
implementation of an abstract data type, often referred to as a data structure, will require that we provide a
physical view of the data using some collection of programming constructs and primitive data types
• When writing programs, sometimes we cannot reliably determine how large an array must be.
• A good solution to this problem is to
→ defer this decision to run-time &
→ allocate the array when we have a good estimate of required array-size
int i,n,*list;
printf("enter the number of numbers to generate");
scanf("%d",&n);
if(n<1)
{
printf("improper value");
exit(0);
}
MALLOC(list, n*sizeof(int));
• The above code would allocate an array of exactly the required size and hence would not
result in any wastage.
CALLOC
• These functions → allocate user-specified amount of memory & → initialize the allocated
memory to 0.
• On successful memory -allocation, it returns a pointer to the start of the new block. On
failure, it returns the value NULL.
• Memory can be allocated using calloc as shown below:
int *p;
p=calloc(n,sizeof(int));//where n=array size
• To create clean and readable programs, a CALLOC macro can be created as shown below:
#define CALLOC(p,n,s)
if((p=calloc(n,s))==NULL)
{
printf("insufficient
memory");
exit(1);
}
REALLOC
• These functions resize memory previously allocated by either malloc or calloc. For example, realloc(p,s);
//this changes the size of memory-block pointed at by p to s < oldSize, the rightmost oldSize-s bytes of
old block are freed..
• When s>oldSize, the additional s-oldSize have an unspecified value and when s
• On successful resizing, it returns a pointer to the start of the new block. On failure, it returns the value
NULL.
• To create clean and readable programs, the REALLOC macro can be created as shown below:
#define REALLOC(p,s) if((p=realloc(p,s))==NULL)
{ printf("insufficient memory"); exit(0);
}
STRUCTURES
Structures
Arrays are collections of data of the same type. In C there is an alternate way of grouping data that
permits the data to vary in type. This mechanism is called the struct, short for structure. A structure
(called a record in many other programming languages) is a collection of data items, where each item
is identified as to its type and name.
struct { char
name[10]; int
age; float
salary;
} person;
Creates a variable whose name is person and that has three fields:
• a name that is a character array
• an integer value representing the age of the person
• a float value representing the salary of the individual
Dot operator(.) is used to access a particular member of the structure.
strcpy(person.name,"james") ; person.age
person.salary = 35000;
We can create our own structure data types by using the typedef statement as below:
typedef struct human— typedef struct
being { char { char
name[10]; int age; name[10]; int
float salary; age; float
}; -OR- salary;
} human-being;
if (humans—equal(personl,person2))
printf("The two human beings are the same\n"); else
printf{"The two human beings are not the same\n");
typedef struct {
int month;
int day;
int year; } date;
A person born on February 11, 1944, would have the values for the date struct set as:
Stack
A Stack is linear data structure. A stack is a list of elements in which an element may be inserted or deleted
only at one end, called the top of the stack. Stack principle is LIFO (last in, first out). Which element
inserted last on to the stack that element deleted first from the stack.
As the items can be added or removed only from the top i.e. the last item to be added to a stack is the first
item to be removed.
Operations on stack:
While performing push and pop operations the following test must be conducted on the stack.
a) Stack is empty or not b) stack is full or not
1. Push: Push operation is used to add new elements in to the stack. At the time of addition first check
the stack is full or not. If the stack is full it generates an error message "stack overflow".
2. Pop: Pop operation is used to delete elements from the stack. At the time of deletion first check the
stack is empty or not. If the stack is empty it generates an error message "stack underflow".
All insertions and deletions take place at the same end, so the last element added to the stack will be the first
element removed from the stack. When a stack is created, the stack base remains fixed while the stack top
changes as elements are added and removed. The most accessible element is the top and the least accessible
element is the bottom of the stack.
Representation of Stack (or) Implementation of stack:
The stack should be represented in two ways:
1. Stack using array
2. Stack using linked list
1. push():When an element is added to a stack, the operation is performed by push(). Below Figure
shows the creation of a stack and addition of elements using push().
Initially top=-1, we can insert an element in to the stack, increment the top value i.e top=top+1. We can
insert an element in to the stack first check the condition is stack is full or not. i.e top>=size-1. Otherwise
add the element in to the stack.
Step 1: START
Step 2: if top>=size-1 then
Write “ Stack is Overflow”
Step 3: Otherwise
3.1: read data value ‘x’
3.2: top=top+1;
3.3: stack[top]=x;
Step 4: END
2. Pop(): When an element is taken off from the stack, the operation is performed by pop(). Below
figure shows a stack initially with three elements and shows the deletion of elements using pop().
We can insert an element from the stack, decrement the top value i.e top=top-1.
We can delete an element from the stack first check the condition is stack is empty or not. i.e
top==-1. Otherwise remove the element from the stack.
3. display(): This operation performed display the elements in the stack. We display the element in the
stack check the condition is stack is empty or not i.e top==-1.Otherwise display the list of elements in
the stack.
{
printf("Enter the
value?");
scanf("%d",&val);
top = top +1; stack[top]
= val;
} } void pop () {
if(top == -1)
printf("Stack Underflow");
else top
= top -1;
} void
display() {
if(top == -1)
{
printf("Stack is empty");
}
printf("stack elements are\n ")
for (i=top;i>=0;i--)
{
printf(" %d ",stack[i]);
}
OUTPUT:
Enter the number of elements in the stack 5
*********Stack operations using array*********
---------------------------------------------- Chose
one from the below options...
1.Push
2.Pop
3.Show
4.Exit
Enter your choice
5
BRI304 Data Structures and Algorithms
Module2 BTI
Please Enter valid choice Chose one from the below options...
1.Push
2.Pop
3.Show
4.Exit
Enter your choice
1
Enter the value?12
Chose one from the below options...
1.Push
2.Pop
3.Show
4.Exit
Enter your choice
3
stack elements are
12
Chose one from the below options...
1.Push
2.Pop
3.Show
4.Exit
Enter your choice
1
Enter the value?12
Chose one from the below options...
1.Push
2.Pop
3.Show
4.Exit
Enter your choice
3
stack elements are
12
12
Chose one from the below options...
1.Push
2.Pop
3.Show
4.Exit
Enter your choice
4
Exiting....
BRI304 Data Structures and Algorithms Module2
BTI
Applications of STACK:
Application of Stack :
• Recursive Function.
• Expression Evaluation.
• Expression Conversion. Infix to postfix Infix to prefix
Postfix to infix
Postfix to prefix
Prefix to infix
Prefix to postfix
• Reverse a Data
• Processing Function Calls
Expressions:
• Operands are the values on which the operators can perform the task. Here operand can
be a direct value or variable or address of memory location
Expression types:
Based on the operator position, expressions are divided into THREE types. They are as follows.
• Infix Expression
• Example
• Postfix Expression
• In postfix expression, operator is used after operands. We can say that "Operator
follows the Operands".
BRI304 Data Structures and Algorithms Module2
BTI
• Prefix Expression
• In prefix expression, operator is used before operands. We can say that "Operands
follows the Operator".
• If the scanned symbol is an operand, then place directly in the postfix expression
(output).
• If the symbol scanned is a right parenthesis, then go on popping all the items from the
stack and place them in the postfix expression till we get the matching left parenthesis.
• If the scanned symbol is an operator, then go on removing all the operators from the
stack and place them in the postfix expression, if and only if the precedence of the
operator which is on the top of the stack is greater than (or greater than or equal) to the
precedence of the scanned operator and push the scanned operator onto the stack
otherwise, push the scanned operator onto the stack.
Example-1
BRI304 Data Structures and Algorithms Module2
BTI
BRI304 Data Structures and Algorithms Module2
BTI
Example2:
Convert ((A – (B + C)) * D) ↑ (E + F) infix expression to postfix form:
Example3
Convert a + b * c + (d * e + f) * g the infix expression into postfix form.
SYMBOL POSTFIX STRING STACK REMARKS
a a
+ a +
b ab +
* ab +*
BRI304 Data Structures and Algorithms Module2
BTI
c abc +*
+ abc*+ +
( abc*+ +(
d abc*+d +(
* abc*+d +(*
e abc*+de +(*
+ abc*+de* +(+
f abc*+de*f +(+
) abc*+de*f+ +
* abc*+de*f+ +*
g abc*+de*f+g +*
End of The input is now empty. Pop the output symbols
string a b c * + d e * f + g * + from the stack until it is empty.
Example 3:
Convert the following infix expression A+(B *C–(D/E↑F)*G)*H into its equivalent postfix expression.
SYMBOL POSTFIX STRING STACK REMARKS
A A
+ A +
( A +(
B AB +(
* AB +(*
C ABC +(*
- ABC* +(-
( ABC* +(-(
D ABC* D +(-(
/ ABC* D +(-(/
E ABC* DE +(-(/
↑ ABC* DE +(-(/↑
F ABC* DE F +(-(/↑
) ABC* DE F ↑ / +(-
* ABC* DE F ↑ / +(-*
G ABC* DE F ↑ / G +(-*
) ABC* DE F ↑ / G* - +
* ABC* DE F ↑ / G* - +*
H ABC* DE F ↑ / G* - H +*
6 6
5 6, 5
2 6, 5, 2
8 2 3 5 6, 5, 5, 8 Next 8 is pushed
Example2
BRI304 Data Structures and Algorithms Module2
BTI
Example 3:
6 6
2 6, 2
3 6, 2, 3
+ 2 3 5 6, 5
- 6 5 1 1
3 6 5 1 1, 3
8 6 5 1 1, 3, 8
2 6 5 1 1, 3, 8, 2
/ 8 2 4 1, 3, 4
+ 3 4 7 1, 7
* 1 7 7 7
2 1 7 7 7, 2
↑ 7 2 49 49
3 7 2 49 49, 3
+ 49 3 52 52
Reverse a Data:
To reverse a given set of data, we need to reorder the data so that the first and last elements are
exchanged, the second and second last element are exchanged, and so on for all other elements.
o Reversing a string o
Converting Decimal to
Binary
Reverse a String
A Stack can be used to reverse the characters of a string. This can be achieved by simply pushing
one by one each character onto the Stack, which later can be popped from the Stack one by one.
Because of the last in first out property of the Stack, the first character of the Stack is on the
bottom of the Stack and the last character of the String is on the Top of the Stack and after
performing the pop operation in the Stack, the Stack returns the String in Reverse order.
When we invoke function A, which contains a call to function B, then its processing will not be
completed until function B has completed its execution and returned. Similarly for function B and
C. So we observe that function A will only be completed after function B is completed and function
B will only be completed after function C is completed. Therefore, function A is first to be started
and last to be completed. To conclude, the above function activity matches the last in first out
behavior and can easily be handled using Stack.
Consider addrA, addrB, addrC be the addresses of the statements to which control is returned after
completing the function A, B, and C, respectively.
The above figure shows that return addresses appear in the Stack in the reverse order in which
the functions were called. After each function is completed, the pop operation is performed, and
execution continues at the address removed from the Stack. Thus the program that calls several
functions in succession can be handled optimally by the stack data structure. Control returns to
each function at a correct place, which is the reverse order of the calling sequence.