0% found this document useful (0 votes)
25 views49 pages

Notes - DS Using C++ Sem IV CBCS - Opt

Data structure

Uploaded by

Mahesh Mutnale
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
25 views49 pages

Notes - DS Using C++ Sem IV CBCS - Opt

Data structure

Uploaded by

Mahesh Mutnale
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 49

Data Structures Using C++

B. Sc. II (Computer Science)


Paper VIII
Course Code - DSC 12D

Author: Asst. Prof. N. S. Kulkarni


Email – [email protected]
Cell – 9890966539 / 9096194081
B.Sc. Part –II Computer Science (Semester– IV)
Course Code: DSC-12D Computer Paper –VIII Course Title: Data Structure Using C++
Total Contact Hours: 36 Hrs (45 Lectures of 48 Min.) Teaching Scheme: 03 Lect. / Week
Credits: 02 Total Marks: 50

Unit – I: Introduction to Data structure & Linear Data Structures: Array, Stack and Queue 18 Hrs.

Concept of Abstract Data Types,


Definitions – Data types, Data Object, Data structure (D-Data, A-Axioms, O-Operations),
Classification (Primitive, Non-Primitive: Array, Files, List: Linear, Non-Linear), Basic Operations
(Traversing, Searching, Insertion, Deletion, Sorting, Merging)
Array – Definition as a Data Structure, Types (one Dimensional, multi dimensional),
Applications of Array – Polynomial representation using array, Operations on Polynomial
(Addition & Product)
Sorting: Definition, Stable-Unstable Sorting, Adaptive-Non Adaptive Sorting, Order of Sorting
(Increasing, Decreasing, Non Increasing, Non Decreasing)
Sorting Techniques: Bubble sort, Selection sort, Insertion sort, Quick sort
Searching: Linear and Binary Search
Stack: Definition, Operations (Push, Pop, Peek, Isfull, Isempty), Implementation using array
Applications of stack: Recursion, Mathematical Expressions (Well-Parentheses, Notations: Infix,
Prefix, Postfix, Conversion from Infix to Postfix and Infix to Prefix)
Queue – Definition of queue, Operations (Enqueue, Dequeue, Peek, Isfull, Isempty), Types of queue
(Linear, Circular, Priority), Implementation Linear Queue using array(Compaction),
Implementation Circular Queue using array (Use of Counter), Applications of Queue

Unit – II: Non Linear Data Structures: Linked List and Trees 18 Hrs.

Linked List: Concept of linked list, Types of Linked List (Singly-Doubly, Linear-Circular),
Implementation of Linked list, Operations on linear linked list (Insertion, Deletion, Display,
Search)
Application: Implementation of stack and queue using linked list.
Trees: Definition, Terminologies (Root, Child, Parent, Siblings, Descendant, Ancestor,
Leaf/External node, Branch node/Internal node, Degree, Edge, Path, Level, Depth, Height of node,
Height of tree, Forest)
Binary Tree: Definition, Types (Full/Proper/Plane, Complete, Perfect, Skewed, Balanced), Array
representation of Binary Tree
Binary Search Tree: Definition, Representation, Operations (Insertion, Deletion, Search, Tree
Traversal:Preorder, Inorder, Postorder)

Reference Books
1. Data Strucure using C and C++ -Rajesh Shukla
2. Data Strucure using C and C++ - Tanenbaum
3. Data Strucure using C++ - E Balagurusamy
4. Data Strucure using C++ - Yashwant Kanetkar
5. Data Strucure using C++ - D.S.Malik
B. Sc. II Sem. IV (CBCS) Paper VII - Data Structures using C++ Course Code -DSC12D

Unit – I: Introduction to Data structure & Linear Data Structures: Array, Stack and Queue

1.1 Concept of Abstract Data Types

1.1.1 Definitions:

Data types: A data type is the most basic and the most common classification of data. It is this through
which the compiler gets to know the form or the type of information that will be used
throughout the code. So basically data type is a type of information transmitted between the
programmer and the compiler where the programmer informs the compiler about what type
of data is to be stored and also tells how much space it requires in the memory. Some basic
examples are int, float, string etc.

Data Object: A data object is a region of storage that contains a value or group of values. Each
value can be accessed using its identifier or a more complex expression that refers to the
object. In addition, each object has a unique data type. The data type of an object determines
the storage allocation for that object and the interpretation of the values during subsequent
access.

Data structure: (D-Data, A-Axioms, O-Operations)


Data structure is the structural representation of logical relationships between elements of
data. In other words a data structure is a way of organizing data items by considering its
relationship to each other. Data structure mainly specifies the structured organization of data,
by providing accessing methods with correct degree of associativity. Data structure affects the
design of both the structural and functional aspects of a program.

Algorithm + Data Structure = Program

Data Structures=Organized Data+ Operations

We can also define data structure as a mathematical or logical model of a particular


organization of data items. The representation of particular data structure in the main
memory of a computer is called as storage structure. The storage structure representation in
auxiliary memory is called as file structure. It is defined as the way of storing and manipulation
data in organized form so that it can be used efficiently.

Data structure mainly specifies the following four things


1. Organization of data
2. Accessing methods
3. Degree of associativity
4. Processing alternatives for information

Data Structure is a systematic way to organize data in order to use it efficiently. Following terms are
the foundation terms of a data structure.

Interface
Each data structure has an interface. Interface represents the set of operations that a data structure
supports. An interface only provides the list of supported operations, type of parameters they can
accept and return type of these operations.
Prof. N. S. Kulkarni (Cell: 9890966539/9096194081) 1
B. Sc. II Sem. IV (CBCS) Paper VII - Data Structures using C++ Course Code -DSC12D

Implementation
Implementation provides the internal representation of a data structure. Implementation also
provides the definition of the algorithms used in the operations of the data structure.

Advantages of data structures


I. Promotes re-use of important functions on data.
II. Implementation is hidden from the user to allow concentration on high level solutions of the
problem at hand.
III. A standard set of functions provides a separation from low-level implementation to the high
level application, giving room for enhancing/modifying the data structure functions to other
methodologies if the need be without touching the application code.

1.1.2 ADT (Abstract Data Type)


Abstract data types or ADTs are a mathematical specification of a set of data and the set of
operations that can be performed on the data. An abstract data type (ADT) is the way we look at a
data structure, focusing on what it does and ignoring how it does its job. The word ‘abstract’ in the
context of data structures means considered apart from the detailed specifications or implementation.
The actual implementation is not defined, and does not affect the use of the ADT. For example,
rational numbers (numbers that can be written in the form a/b where a and b are integers) cannot be
represented natively in a computer.
Data abstraction, or abstract data types, is a programming methodology where one defines
not only the data structure to be used, but the processes to manipulate the structure like process
abstraction, ADTs can be supported directly by programming languages To support it, there needs to
be mechanisms for defining data structures encapsulation of data structures and their routines to
manipulate the structures into one unit by placing all definitions in one unit, it can be compiled at one
time information hiding to protect the data structure from outside interference or manipulation the
data structure should only be accessible from code encapsulated with it so that the structure is hidden
and protected from the outside objects are one way to implement ADTs, but because objects have
additional properties.
• An Abstract Data Type is some sort of data together with a set of functions (interface)
that operate on the data.
• Access is only allowed through that interface.
• Implementation details are hidden from the user.
• An abstract data type (ADT) is an abstraction of a data structure
• An Abstract Data Type (ADT) is:
o a set of values
o a set of operations, which can be applied uniformly to all these values
• To abstract is to leave out information, keeping (hopefully) the more important parts
o What part of a Data Type does an ADT leave out?
• An ADT specifies:
o Data stored
o Operations on the data
o Error conditions associated with operations
• Example: ADT modeling a simple stock trading system
o The data stored are buy/sell orders
o The operations supported are
▪ order buy(stock, shares, price)
Prof. N. S. Kulkarni (Cell: 9890966539/9096194081) 2
B. Sc. II Sem. IV (CBCS) Paper VII - Data Structures using C++ Course Code -DSC12D
▪ order sell(stock, shares, price)
▪ void cancel(order)
o Error conditions:
▪ Buy/sell a nonexistent stock
▪ Cancel a nonexistent order

1.1.3 Classification

Data Structures

Primitive Non-Primitive

Floating
Integer Character Pointer Array List File
Point

Linear Non-Linear

Stack Queue Graph Tree

Data structures are generally categorized into two classes: primitive and non-primitive data structures.

1. Primitive Data Structures


Primitive data structures are the fundamental data types which are supported by a programming
language. Some basic data types are integer, real, character, and Boolean. The terms ‘data type’,
‘basic data type’, ’fundamental data types’ and ‘primitive data type’ are often used
interchangeably. These data structures are directly operated upon by the machine instructions.
Normally, primitive data structures have different representation on different computers.

Prof. N. S. Kulkarni (Cell: 9890966539/9096194081) 3


B. Sc. II Sem. IV (CBCS) Paper VII - Data Structures using C++ Course Code -DSC12D
For example - the integers, floating-point numbers, pointers, string constants, characters etc.
are some of the different primitive data structure.in C language, the different primitive data
structure are defined using the data type such as int, char, float, double etc.

2. Non-primitive Data Structures


Non-primitive data structures are those data structures which are created using primitive data
structures. Examples of such data structures include linked lists, stacks, trees, and graphs. The
non-primitive data structures are highly developed complex data structures. Basically, these are
developed from the primitive data structure. The non-primitive data structure is responsible for
organizing the group of homogeneous and heterogeneous data elements.
Non-primitive data structures can further be classified into two categories: linear and non-
linear data structures.
• Linear
If the elements of a data structure are stored in a linear or sequential order, then it is a
linear data structure. Data structure where data elements are arranged sequentially or
linearly where the elements are attached to its previous and next adjacent in what is
called a linear data structure. In linear data structure, single level is involved. Therefore,
we can traverse all the elements in single run only. Linear data structures are easy to
implement because computer memory is arranged in a linear way. Examples include
arrays, linked lists, stacks, and queues. Linear data structures can be represented in
memory in two different ways. One way is to have to a linear relationship between
elements by means of sequential memory locations. The other way is to have a linear
relationship between elements by means of links.
• Non-linear
However, if the elements of a data structure are not stored in a sequential order, then it is
a non-linear data structure. The relationship of adjacency is not maintained between
elements of a non-linear data structure. Examples include trees and graphs. Data
structures where data elements are not arranged sequentially or linearly are called non-
linear data structures. In a non-linear data structure, single level is not involved.
Therefore, we can’t traverse all the elements in single run only. Non-linear data structures
are not easy to implement in comparison to linear data structure. It utilizes computer
memory efficiently in comparison to a linear data structure.

Linear Data Structure Non-Linear Data Structure


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.
Single level is involved. Multiple levels are involved.
Its implementation is easy in comparison While its implementation is complex in
to non-linear data structure. comparison to linear data structure.
Data elements can be traversed in a single Data elements can’t be traversed in a single
run only. run only.
In a linear data structure, memory is not While in a non-linear data structure,
utilized in an efficient way. memory is utilized in an efficient way.
Its examples are: array, stack, queue,
While its examples are: trees and graphs.
linked list, etc.

Prof. N. S. Kulkarni (Cell: 9890966539/9096194081) 4


B. Sc. II Sem. IV (CBCS) Paper VII - Data Structures using C++ Course Code -DSC12D
1.1.4 Data Structure Basic Operations
Design of efficient data structure must take operations to be performed on the data structures into
account. The most commonly used operations on data structure are broadly categorized into following
types.
1. Create: The create operation results in reserving memory program elements. This can be
done by declaration statement. Creation of data structure may take place either during
compile-time or run-time.
2. Destroy: Destroy operations destroys memory space allocated for specified data structure.
3. Insertion: This operation inserts data item to data structure.
4. Deletion: This operation deletes particular data item from data structure.
5. Selection: Selection operation deals with accessing a particular data within a data structure.
6. Updation: It updates or modifies the data in the data structure.
7. 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.
8. Sorting: Sorting is a process of arranging all data items in a data structure in a particular
order, say for example either in ascending or descending order.
9. Merging: Merging is a process of combining data items of two data structures
10. Splitting: Splitting is a process of partitioning single data structure in multiple.
11. Traversal: Traversal is a process of visiting each and every data item of data structure in
systemic manner.

1.2 Array
An array is a collection of same type of values stored in consecutive memory location. It can be used to
store the values of similar data types; either it is int, float, double, char and string. In other words array
is nothing but collection of element of same type stored under common name. Each value in array is
referenced by name and subscript or index, which indicates the position of the value in array. As
subscripts are used in arrays they are also referred as subscripted variables. The individual values in an
array are called the elements of array. The structure of an array; Myarray containing n element shown
in figure
Myarray[0] Myarray[1] Myarray[2] …………….. Myarray[n-1]

In figure Myarray[0] represents the first element of the array , Myarray [1] represents the second
element of array, Myarray [n-1] represents nth element of array. The simplest form of array is a one-
dimensional array that may be defined as a finite ordered set of homogeneous elements, which is
stored in contiguous memory locations.

Features
i. It is collection of similar data types
ii. Array is Linear/Sequential Data types as it stores its elements/members in consecutive
memory locations in memory.
iii. Array members can be accessed using an integer value that always starts at 0 and
known as index or subscript.
iv. It is multivalued variable as it stores multiple values together.

Array is a linear data structures which stores same kind of element or data. It is called a data structure
because it provide unique index or space for unique element and you can insert, delete ,sort and search
any element easily.

Prof. N. S. Kulkarni (Cell: 9890966539/9096194081) 5


B. Sc. II Sem. IV (CBCS) Paper VII - Data Structures using C++ Course Code -DSC12D
1.2.1 Types of Arrays
Arrays are be broadly classified into two types one dimensional and multidimensional array. A one
dimensional array has only one subscript and multidimensional array has n subscripts, here n
represents dimensions of array. Multi-dimensional arrays can be further classified into two
dimensional and three dimensional arrays. The dimensionality of an array is determined by the
number of pair of square brackets placed after the array name. e.g. array1[ ] represents one
dimensional array,array2[ ][ ] represents two dimensional array ,and array3[ ][ ][ ] represents three
dimensional array.

1 Single-Dimensional Array/ 1D
A one dimensional array is used to store linear list of values of the same type. The element in one
dimensional array is stored with the index values starting from 0 to one less than size of array. Each
element of one dimensional array accessed using the same name and single subscripts.
• Declaring one dimensional array
Similar to a variable you need to declare an array before using it. A one dimensional array can be
declared using the following syntax.
<data type> arrayname[dimension];
Here data type represents data type of the array variable, it is either int, float, long, char etc.
arrayname represents name of the array variable and size is nothing but number of elements you
want to store In that array of given data type.
Eg. float per[100]; int array[10];
• Initializing array variable
Once you declared one dimensional an array. You can initialize the individual elements of the array
one by one in same way as you declare a variable, you can also initialize all the elements of an array at
the same time of declaring the array
int marks[5]={ 39,45,90,98,32};
You also initialized array variable following way;
Marks[0]=39;
Marks[1]=45;
Marks[2]=90;
Marks[3]=98;
Marks[4]=32;

2 Two-Dimensional Array / 2D
A two dimensional array is used to store table of values of the same type. It is similar to matrix
containing rows and column
• Declaring one dimensional array
Similar to a variable you need to declare an array before using it. A two dimensional array can be
declared using the following syntax.
<data type > arrayname [dimension] [dimension];
Here data type represents data type of the array variable, it is either int, float, long, char etc.
arrayname represents name of the array variable and size is nothing but number of elements you
want to store In that array of given data type. In preceding syntax, the data type represents the data
type of an array to be declared. Size1 represents the number of rows and size 2 represents the
number of column. Eg. int myarray[3][3];
• Initializing array variable

Prof. N. S. Kulkarni (Cell: 9890966539/9096194081) 6


B. Sc. II Sem. IV (CBCS) Paper VII - Data Structures using C++ Course Code -DSC12D
Once you declared two dimensional array you can initialize the individual elements of the array
one by one in same way as you declare a variable, you can also initialize all the elements of an array at
the same time of declaring the array
int myarray[3][3]={ {39,45,90},{98,32,67},{77,88,23}};
You also initialized array variable following way;
Marks[0][0]=39;
Marks[0][1]=45;
Marks[0][2]=90;
Marks[1][0]=98;
Marks[1][1]=32;
Marks[1][2]=67;

1.2.3 Applications of Array


1) Polynomial representation using array
A Polynomial is an expression that contains more than two terms. A term is made up of coefficient
and exponent. An example of Polynomial is
P(X) =4X3+6X2+7X+9
A Polynomial thus may be represented using arrays or linked lists. Array representation assumes
that the exponents of the given expression are arranged from 0 to the highest value (degree),
which is represented by the subscript of the array beginning with 0. The coefficients of the
respective exponent are placed at an appropriate index in the array. The array representation for
the above polynomial expression is given below:

arr 9 7 6 4 Coefficients
0 1 2 3 Exponents

a. Operations on Polynomial
1. Addition
For adding two polynomials using arrays is straightforward method, since both the arrays may
be added up element wise beginning from 0 to n-1, resulting in addition of two polynomials.

// Simple C++ program to add two polynomials


#include <iostream>
using namespace std;

// A utility function to return maximum of two integers


int max(int m, int n) { return (m > n)? m: n; }

/* A[] represents coefficients of first polynomial B[] represents coefficients of second


polynomial, m and n are sizes of A[] and B[] respectively */

int *add(int A[], int B[], int m, int n)


{
int size = max(m, n);
int *sum = new int[size];

Prof. N. S. Kulkarni (Cell: 9890966539/9096194081) 7


B. Sc. II Sem. IV (CBCS) Paper VII - Data Structures using C++ Course Code -DSC12D
// Initialize the porduct polynomial
for (int i = 0; i<m; i++)
sum[i] = A[i];

// Take ever term of first polynomial


for (int i=0; i<n; i++)
sum[i] += B[i];

return sum;
}

// A utility function to print a polynomial


void printPoly(int poly[], int n)
{
for (int i=0; i<n; i++)
{
cout << poly[i];
if (i != 0)
cout << "x^" << i ;
if (i != n-1)
cout << " + ";
}
}

// Driver program to test above functions


int main()
{
// The following array represents polynomial 5 + 10x^2 + 6x^3
int A[] = {5, 0, 10, 6};

// The following array represents polynomial 1 + 2x + 4x^2


int B[] = {1, 2, 4};
int m = sizeof(A)/sizeof(A[0]);
int n = sizeof(B)/sizeof(B[0]);

cout << "First polynomial is \n";


printPoly(A, m);
cout << "\nSecond polynomial is \n";
printPoly(B, n);

int *sum = add(A, B, m, n);


int size = max(m, n);

cout << "\nsum polynomial is \n";


printPoly(sum, size);

return 0;
}
Prof. N. S. Kulkarni (Cell: 9890966539/9096194081) 8
B. Sc. II Sem. IV (CBCS) Paper VII - Data Structures using C++ Course Code -DSC12D

Output:
First polynomial is
5 + 0x^1 + 10x^2 + 6x^3
Second polynomial is
1 + 2x^1 + 4x^2
Sum polynomial is
6 + 2x^1 + 14x^2 + 6x^3

2. Product
Multiplication of two polynomials however requires manipulation of each node such that the
exponents are added up and the coefficients are multiplied. After each term of first
polynomial is operated upon with each term of the second polynomial, then the result has to
be added up by comparing the exponents and adding the coefficients for similar exponents
and including terms as such with dissimilar exponents in the result.

// Simple C++ program to multiply two polynomials


#include <iostream>
using namespace std;

// A[] represents coefficients of first polynomial


// B[] represents coefficients of second polynomial
// m and n are sizes of A[] and B[] respectively
int *multiply(int A[], int B[], int m, int n)
{
int *prod = new int[m+n-1];

// Initialize the porduct polynomial


for (int i = 0; i<m+n-1; i++)
prod[i] = 0;

// Multiply two polynomials term by term

// Take ever term of first polynomial


for (int i=0; i<m; i++)
{
// Multiply the current term of first polynomial
// with every term of second polynomial.
for (int j=0; j<n; j++)
prod[i+j] += A[i]*B[j];
}
return prod;
}

// A utility function to print a polynomial


void printPoly(int poly[], int n)
{
for (int i=0; i<n; i++)
Prof. N. S. Kulkarni (Cell: 9890966539/9096194081) 9
B. Sc. II Sem. IV (CBCS) Paper VII - Data Structures using C++ Course Code -DSC12D
{
cout << poly[i];
if (i != 0)
cout << "x^" << i ;
if (i != n-1)
cout << " + ";
}
}

// Driver program to test above functions


int main()
{
// The following array represents polynomial 5 + 10x^2 + 6x^3
int A[] = {5, 0, 10, 6};

// The following array represents polynomial 1 + 2x + 4x^2


int B[] = {1, 2, 4};
int m = sizeof(A)/sizeof(A[0]);
int n = sizeof(B)/sizeof(B[0]);

cout << "First polynomial is n";


printPoly(A, m);
cout << "nSecond polynomial is n";
printPoly(B, n);

int *prod = multiply(A, B, m, n);

cout << "nProduct polynomial is n";


printPoly(prod, m+n-1);
return 0;
}

Output:
First polynomial is
5 + 0x^1 + 10x^2 + 6x^3
Second polynomial is
1 + 2x^1 + 4x^2
Product polynomial is
5 + 10x^1 + 30x^2 + 26x^3 + 52x^4 + 24x^5
2) Arrays are used to Store List of values
3) Arrays are used to Perform Matrix Operations
4) Arrays are used to implement Search Algorithms
5) Arrays are used to implement Sorting Algorithms

1.3 Sorting
Sorting is a process or operation of ordering items and data according to a specific criterion. For
example, sorting of numbers is ordering numbers either in ascending or descending order. Sorting
refers to the operation or technique of arranging and rearranging sets of data in some specific order. A
Prof. N. S. Kulkarni (Cell: 9890966539/9096194081) 10
B. Sc. II Sem. IV (CBCS) Paper VII - Data Structures using C++ Course Code -DSC12D
collection of records called a list where every record has one or more fields. The fields which contain a
unique value for each record is termed as the key field. For example, a phone number directory can be
thought of as a list where each record has three fields - 'name' of the person, 'address' of that person,
and their 'phone numbers'. Being unique phone number can work as a key to locate any record in the
list. The records are either sorted either numerically or alphanumerically. The records are then
arranged in ascending or descending order depending on the numerical value of the key. Here is an
example, where the sorting of a lists of marks obtained by a student in any particular subject of a class.
The techniques of sorting can be divided into two categories. These are:
• Internal Sorting
If all the data that is to be sorted can be adjusted at a time in the main memory, the internal
sorting method is being performed.

• External Sorting
When the data that is to be sorted cannot be accommodated in the memory at the same time
and some has to be kept in auxiliary memory such as hard disk, floppy disk, magnetic tapes
etc., then external sorting methods are performed.

1.3.1 Stable and Un-Stable Sorting


A sorting algorithm is said to be stable if it maintains the relative order of numbers/records in the case
of tie i.e. if you need to sort 1 1 2 3 then if you don't change order of those first two ones then your
algorithm is stable, but if you swap them then it becomes unstable, despite the overall result or
sorting order remain same. This difference becomes more obvious when you sort objects e.g. sorting
key-value pairs by keys. In the case of a stable algorithm, the original order of key-value pair is retained
as shown in the following example.

This is an example of stable sorting here 26 appears twice at position 6 and 8 and their order is
preserved in unsorted and sorted array i.e., element 26 (blue) at position 6 appears first in unsorted
and sorted array (before and after sorting).
In the case of an unstable sort, this order of appearance before and after sorting is not
necessarily preserved. If a sorting algorithm, after sorting the contents, changes the sequence of
similar content in which they appear, it is called unstable sorting.

Prof. N. S. Kulkarni (Cell: 9890966539/9096194081) 11


B. Sc. II Sem. IV (CBCS) Paper VII - Data Structures using C++ Course Code -DSC12D
Whereas a sorting algorithm is said to be unstable if there are two or more objects with equal keys
which don’t appear in same order before and after sorting.
Some sorting algorithms such as Insertion sort, Merge Sort, Bubble Sort, etc. are stable by
nature, and other sorting algorithms like Heap Sort, Quick Sort, etc. are not stable by nature.
Just remember, that if the original order of equal keys or number is maintained in the sorted
output then the algorithm is known as sorting algorithm. Some popular examples of stable sorting
algorithms are merge sort, insertion sort, and bubble sort.

1.3.2 Adaptive and Non-adaptive Sorting


A sorting algorithm that can take advantage of existing order in the input, reducing its requirements
for computational resources as a function of the disorder in the input.

A Non-Adaptive Sorting Algorithm does not care if the array is already sorted or not it will apply its all
resources to sort the sorted elements.

If order of the elements to be sorted of an input array matters (or) affects the time complexity of a
sorting algorithm, then that algorithm is called “Adaptive” sorting algorithm. For example, Insertion
sort is an adaptive sorting algorithm, if input is already sorted then time complexity will be O(n).
Therefore, if input is nearly sorted then go for insertion sort, though this is not the only parameter to
go for Insertion sort over other sorting algorithms.

Merge Sort is an “Non-Adaptive” Sorting algorithm, because the order of the elements in the input
array doesn’t matter, time complexity will always be O(nlogn).

Adaptive sorting algorithms:


1. Bubble Sort
2. Insertion Sort
3. Quick Sort

Non-adaptive sorting algorithms:


1. Selection Sort
2. Merge Sort
3. Heap Sort

An adaptive algorithm takes advantage of helpful properties of the input, while Non-adaptive doesn't.
A simple example from manual arithmetic is methods for multiplying. Non-adaptive means you
multiply every digit no matter what, adaptive would be taking advantage of shifting left to multiply by
10 and possibly other tricks.
In the context of sorting, a non-adaptive algorithm takes the same amount of time for a given number
of values no matter what. An adaptive algorithm takes advantage of properties of the data. This
usually means taking advantage of any near sorted or already sorted portions. Heap sort and quicksort
are non-adaptive. Non-adaptive algorithms have the advantage of simplicity, Adaptive is often faster,
but the algorithm is more complex.

1.3.3 Order of Sorting


Some terms are generally coined while discussing sorting techniques, here is a brief introduction to
them −

Prof. N. S. Kulkarni (Cell: 9890966539/9096194081) 12


B. Sc. II Sem. IV (CBCS) Paper VII - Data Structures using C++ Course Code -DSC12D
Increasing Order
A sequence of values is said to be in increasing order, if the successive element is greater than the
previous one. For example, 1, 3, 4, 6, 8, 9 are in increasing order, as every next element is greater
than the previous element.
Decreasing Order
A sequence of values is said to be in decreasing order, if the successive element is less than the
current one. For example, 9, 8, 6, 4, 3, 1 are in decreasing order, as every next element is less than
the previous element.
Non-Increasing Order
A sequence of values is said to be in non-increasing order, if the successive element is less than or
equal to its previous element in the sequence. This order occurs when the sequence contains
duplicate values. For example, 9, 8, 6, 3, 3, 1 are in non-increasing order, as every next element is less
than or equal to (in case of 3) but not greater than any previous element.
Non-Decreasing Order
A sequence of values is said to be in non-decreasing order, if the successive element is greater than
or equal to its previous element in the sequence. This order occurs when the sequence contains
duplicate values. For example, 1, 3, 3, 6, 8, 9 are in non-decreasing order, as every next element is
greater than or equal to (in case of 3) but not less than the previous one.

1.4 Sorting Techniques


1.4.1 Bubble sort
Bubble Sort is the simplest sorting algorithm that works by repeatedly swapping the adjacent elements
if they are in wrong order. Due to its simplicity, bubble sort is often used to introduce the concept of a
sorting algorithm. In computer graphics it is popular for its capability to detect a very small error (like
swap of just two elements) in almost-sorted arrays and fix it with just linear complexity (2n). For
example, it is used in a polygon filling algorithm, where bounding lines are sorted by their x coordinate
at a specific scan line (a line parallel to x axis) and with incrementing y their order changes (two
elements are swapped) only at intersections of two lines

// C++ program for implementation of Bubble sort


#include <bits/stdc++.h>
using namespace std;

void swap(int *xp, int *yp)


{
int temp = *xp;
*xp = *yp;
*yp = temp;
}

// A function to implement bubble sort


void bubbleSort(int arr[], int n)
{
int i, j;
for (i = 0; i < n-1; i++)

// Last i elements are already in place


Prof. N. S. Kulkarni (Cell: 9890966539/9096194081) 13
B. Sc. II Sem. IV (CBCS) Paper VII - Data Structures using C++ Course Code -DSC12D
for (j = 0; j < n-i-1; j++)
if (arr[j] > arr[j+1])
swap(&arr[j], &arr[j+1]);
}

/* Function to print an array */


void printArray(int arr[], int size)
{
int i;
for (i = 0; i < size; i++)
cout << arr[i] << " ";
cout << endl;
}

// Driver code
int main()
{
int arr[] = {64, 34, 25, 12, 22, 11, 90};
int n = sizeof(arr)/sizeof(arr[0]);
bubbleSort(arr, n);
cout<<"Sorted array: \n";
printArray(arr, n);
return 0;
}

Bubble Sort Applications


Bubble sort is used in the following cases where the complexity of the code does not matter a short
code is preferred

1.4.2 Selection sort


Selection sort is a simple sorting algorithm. This sorting algorithm is an in-place comparison-based
algorithm in which the list is divided into two parts, the sorted part at the left end and the unsorted
part at the right end. Initially, the sorted part is empty and the unsorted part is the entire list. The
smallest element is selected from the unsorted array and swapped with the leftmost element, and
that element becomes a part of the sorted array. This process continues moving unsorted array
boundary by one element to the right. This algorithm is not suitable for large data sets as its average
and worst case complexities are of Ο(n2), where n is the number of items.
How Selection Sort Works?
Consider the following depicted array as an example.

For the first position in the sorted list, the whole list is scanned sequentially. The first position where
14 is stored presently, we search the whole list and find that 10 is the lowest value.

So we replace 14 with 10. After one iteration 10, which happens to be the minimum value in the list,
appears in the first position of the sorted list.
Prof. N. S. Kulkarni (Cell: 9890966539/9096194081) 14
B. Sc. II Sem. IV (CBCS) Paper VII - Data Structures using C++ Course Code -DSC12D

For the second position, where 33 is residing, we start scanning the rest of the list in a linear manner.

We find that 14 is the second lowest value in the list and it should appear at the second place. We
swap these values.

After two iterations, two least values are positioned at the beginning in a sorted manner.

The same process is applied to the rest of the items in the array. Number of comparisons : (n-1) + (n-
2) + (n-3) +.....+ 1 = n(n-1)/2 nearly equals to n2. Complexity = O(n2)

Advantages
a. Easy/simple to implement
b. Useful when no. of elements are less
c. Useful when memory is less.
Disadvantages
a. It is slower when no. of elements is large.
b. Performance varies with initial order of input.

/* C++ Program - Selection Sort */


#include<iostream>
#include<stdio.h>
int main()
{
int size, arr[50], i, j, temp, index, small, count=0;
cout<<"Enter Array Size : ";
cin>>size;
cout<<"Enter Array Elements : ";
for(i=0; i<size; i++)
cin>>arr[i];
cout<<"Sorting array using selection sort...\n";
for(i=0; i<(size-1); i++)
{
small = arr[i];
for(j=(i+1); j<size; j++)
{
if(small>arr[j])
{
small = arr[j];
count++;
index = j;
}
Prof. N. S. Kulkarni (Cell: 9890966539/9096194081) 15
B. Sc. II Sem. IV (CBCS) Paper VII - Data Structures using C++ Course Code -DSC12D
}
if(count!=0)
{
temp = arr[i];
arr[i] = small;
arr[index] = temp;
}
count=0;
}
cout<<"Now the Array after sorting is :\n";
for(i=0; i<size; i++)
cout<<arr[i]<<" ";
getchar();
return 0;
}

1.4.3 Insertion sort


Insertion sort is based on the idea that one element from the input elements is consumed in each
iteration to find its correct position i.e, the position to which it belongs in a sorted array. It iterates the
input elements by growing the sorted array at each iteration. It compares the current element with
the largest value in the sorted array. If the current element is greater, then it leaves the element in its
place and moves on to the next element else it finds its correct position in the sorted array and moves
it to that position. This is done by shifting all the elements, which are larger than the current element,
in the sorted array to one position ahead
The array to be sorted is as follows:

Now for each pass, we compare the current element to all its previous elements. So in the first pass,
we start with the second element.
The illustration can be summarized in a tabular form:
Pass Unsorted list comparison Sorted list
1 {12,3,5,10,8,1} {12,3} {3,12,5,10,8,1}
2 {3,12,5,10,8,1} {3,12,5} {3,5,12,10,8,1}
3 {3,5,12,10,8,1} {3,5,12,10} {3,5,10,12,8,1}
4 {3,5,10,12,8,1} {3,5,10,12,8} {3,5,8,10,12,1}
5 {3,5,8,10,12,1} {3,5,8,10,12,1} {1,3,5,8,10,12}
6 {} {} {1,3,5,8,10,12}
As shown in the above illustration, we begin with the 2nd element as we assume that the first element
is always sorted. So we begin with comparing the second element with the first one and swap the
position if the second element is less than the first.

Average Case Complexity: O (n2)


It occurs when the elements of an array are in jumbled order (neither ascending nor descending).
Space Complexity

Prof. N. S. Kulkarni (Cell: 9890966539/9096194081) 16


B. Sc. II Sem. IV (CBCS) Paper VII - Data Structures using C++ Course Code -DSC12D
Advantages
a. Relatively simple and easy to implement.
b. Twice faster than Bubble sort

Disadvantages
a. Inefficient for large lists.

/* C++ Program - Insertion Sort */


#include<iostream>
#include<stdio.h>
using namespace std;
int main()
{
int size, arr[50], i, j, temp;
cout<<"Enter Array Size : ";
cin>>size;
cout<<"Enter Array Elements : ";
for(i=0; i<size; i++)
{
cin>>arr[i];
}
cout<<"Sorting array using selection sort ... \n";
for(i=1; i<size; i++)
{
temp=arr[i];
j=i-1;
while((temp<arr[j]) && (j>=0))
{
arr[j+1]=arr[j];
j=j-1;
}
arr[j+1]=temp;
}
cout<<"Array after sorting : \n";
for(i=0; i<size; i++)
{
cout<<arr[i]<<" ";
}
getchar();
return 0;
}

1.4.4 Quick sort


Quick sort is a highly efficient sorting algorithm and is based on partitioning of array of
data into smaller arrays. A large array is partitioned into two arrays one of which holds values
smaller than the specified value, say pivot, based on which the partition is made and another
array holds values greater than the pivot value. Quick sort partitions an array and then calls

Prof. N. S. Kulkarni (Cell: 9890966539/9096194081) 17


B. Sc. II Sem. IV (CBCS) Paper VII - Data Structures using C++ Course Code -DSC12D
itself recursively twice to sort the two resulting subarrays. This algorithm is quite efficient for
large-sized data sets as its average and worst case complexity are of Ο(n2), where n is the
number of items.
Quick sort is one of the most famous sorting algorithms based on divide and conquers
strategy which results in an O(n log n) complexity. So, the algorithm starts by picking a single item
which is called pivot and moving all smaller items before it, while all greater elements in the later
portion of the list. This is the main quick sort operation named as a partition, recursively repeated on
lesser and greater sublists until their size is one or zero - in which case the list is entirely sorted.
Choosing an appropriate pivot, as an example, the central element is essential for avoiding the
severely reduced performance of O(n2). Quick Sort is also called as Partition-Exchange Sort.
This algorithm divides the list into three main parts:
1. Elements less than the Pivot element
2. Pivot element(Central element)
3. Elements greater than the pivot element
Pivot element can be any element from the array, it can be the first element, the last element or any
random element. In this tutorial, we will take the rightmost element or the last element as pivot. For
example: In the array {52, 37, 63, 14, 17, 8, 6, 25}, we take 25 as pivot. So after the first pass, the list
will be changed like this. {6 8 17 14 25 63 37 52}. Hence after the first pass, pivot will be set at its
position, with all the elements smaller to it on its left and all the elements larger than to its right.
Now 6 8 17 14 and 63 37 52 are considered as two separate subarrays, and same recursive logic will
be applied on them, and we will keep doing this until the complete array is sorted.

#include <iostream>
#include <stdio.h>
template <class t>
using namespace std;

void quick_sort(t a[], int low, int high)


{
t k;
int i, j, flag = 1;
if (low < high) {
k = a[low];
i = low + 1;
j = high;
while (flag) {
while ((a[i] <= k) && (i < j)) i++; while (a[j] > k)
j--;
if (i < j)
swap(a, i, j);
else
flag = 0;
}
swap(a, low, j);
quick_sort(a, low, j - 1);
quick_sort(a, j + 1, high);
}
}
Prof. N. S. Kulkarni (Cell: 9890966539/9096194081) 18
B. Sc. II Sem. IV (CBCS) Paper VII - Data Structures using C++ Course Code -DSC12D
void swap(t1 a[], int x, int y)
{
t1 temp;
temp = a[x];
a[x] = a[y];
a[y] = temp;
}
int main()
{
int i, n, a[20];
cout << "Enter the number of elements to be sort::"; cin >> n;
cout << "Enter elements:\n";
for (i = 0; i < n; i++) cin >> a[i];
quick_sort(a, 0, n - 1);
cout << "The sorted elements are:\n";
for (i = 0; i < n; i++)
cout << a[i] << endl;
return 0;
}

1.5 Searching:
Searching is a process of locating a particular element present in a given set of elements. The element
may be a record, a table, or a file. A search algorithm is an algorithm that accepts an argument ‘a’ and
tries to find an element whose value is ‘a’. It is possible that the search for a particular element in a set
is unsuccessful if that element does not exist. There are number of techniques available for searching
1.5.1 Linear/Sequential Search
Sequential search is also called as Linear Search. Sequential search starts at the beginning of the list
and checks every element of the list. It is a basic and simple search algorithm. Sequential search
compares the element with all the other elements given in the list. If the element is matched, it
returns the value index, else it returns -1.

The above figure shows how sequential search works. It searches an element or value from an array till
the desired element or value is not found. If we search the element 25, it will go step by step in a
sequence order. It searches in a sequence order. Sequential search is applied on the unsorted or
unordered list when there are fewer elements in a list. In case of a sorted list searching starts from
0th element and continues until the element is found from the list or the element whose value is
greater than (assuming the list is sorted in ascending order), the value being searched is reached.

// C++ code to linearly search x in arr[]. If x is present then return its location,
// otherwise return -1

#include <iostream>
using namespace std;

Prof. N. S. Kulkarni (Cell: 9890966539/9096194081) 19


B. Sc. II Sem. IV (CBCS) Paper VII - Data Structures using C++ Course Code -DSC12D
int search(int arr[], int n, int x)
{
int i;
for (i = 0; i < n; i++)
if (arr[i] == x)
return i;
return -1;
}

int main(void)
{
int arr[] = { 2, 3, 4, 10, 40 };
int x = 10;
int n = sizeof(arr) / sizeof(arr[0]);
int result = search(arr, n, x);
(result == -1)? cout<<"Element is not present in array"
: cout<<"Element is present at index " <<result;
return 0;
}

1.5.2 Binary Search


Binary Search is used for searching an element in a sorted array. It is a fast search algorithm with run-
time complexity of O(log n).
• Binary search works on the principle of divide and conquer. Search a sorted array by repeatedly
dividing the search interval in half. Begin with an interval covering the whole array. If the value of
the search key is less than the item in the middle of the interval, narrow the interval to the lower
half. Otherwise narrow it to the upper half. Repeatedly check until the value is found or the
interval is empty.
• This searching technique looks for a particular element by comparing the middle most element
of the collection.
• It is useful when there are large number of elements in an array.

• The above array is sorted in ascending order. As we know binary search is applied on sorted lists
only for fast searching.
For example, if searching an element 25 in the 7-element array, following figure shows how binary
search works:

Prof. N. S. Kulkarni (Cell: 9890966539/9096194081) 20


B. Sc. II Sem. IV (CBCS) Paper VII - Data Structures using C++ Course Code -DSC12D

Binary searching starts with middle element. If the element is equal to the element that we are
searching then return true. If the element is less than then move to the right of the list or if the
element is greater than then move to the left of the list. Repeat this, till you find an element.

// C++ program to implement recursive Binary Search


#include <iostream>
using namespace std;

// A recursive binary search function. It returns


// location of x in given array arr[l..r] is present,
// otherwise -1
int binarySearch(int arr[], int l, int r, int x)
{
if (r >= l) {
int mid = l + (r - l) / 2;

// If the element is present at the middle


// itself
if (arr[mid] == x)
return mid;

// If element is smaller than mid, then


// it can only be present in left subarray
if (arr[mid] > x)
return binarySearch(arr, l, mid - 1, x);

// Else the element can only be present


Prof. N. S. Kulkarni (Cell: 9890966539/9096194081) 21
B. Sc. II Sem. IV (CBCS) Paper VII - Data Structures using C++ Course Code -DSC12D
// in right subarray
return binarySearch(arr, mid + 1, r, x);
}

// We reach here when element is not


// present in array
return -1;
}

int main()
{
int arr[] = { 2, 3, 4, 10, 40 };
int x = 10;
int n = sizeof(arr) / sizeof(arr[0]);
int result = binarySearch(arr, 0, n - 1, x);
(result == -1) ? cout << "Element is not present in array"
: cout << "Element is present at index " << result;
return 0;
}

1.6 Stack:
Stack is an abstract data type with a bounded (predefined) capacity. It is a simple data
structure that allows adding and removing elements in a particular order. Every time an element is
added, it goes on the top of the stack and the only element that can be removed is the element that is
at the top of the stack, just like a pile of objects.
Stack is a fundamental data structure which is used to store elements in a linear fashion. A
stack is similar to real-life stack or a pile of things that we stack one above the other. Stack follows
LIFO (last in, first out) order or approach in which the operations are performed. This means that the
element which was added last to the stack will be the first element to be removed from the stack.
Basic Operations
Following are the basic operations that are supported by the stack.
1. push – Adds or pushes an element into the stack.
2. pop – Removes or pops an element out of the stack.
3. peek – Gets the top element of the stack but doesn’t remove it.
4. isFull – Tests if the stack is full.
5. isEmpty – Tests if the stack is empty.

The stacks of elements of any particular type is a finite sequence of elements of that type together
with the following operations:
1. Initialize the stack to be empty
2. Determine whether the stack is empty or not
3. Check whether the stack is full or not
4. If the stack is not full, add or insert a new node at the top of the stack. This operation is
termed as Push Operation
5. If the stack is not empty, then retrieve the node at its top
6. If the stack is not empty, the delete the node at its top. This operation is called as Pop
operation

Prof. N. S. Kulkarni (Cell: 9890966539/9096194081) 22


B. Sc. II Sem. IV (CBCS) Paper VII - Data Structures using C++ Course Code -DSC12D

The stack can be represented in memory with the use of arrays. To do this job, you need to maintain a
linear array STACK, a pointer variable top which contains the top element.
#include <iostream>
#include<stdlib.h>
using namespace std;

class stack {
int stk[5];
int top;

public:
stack()
{
top = -1;
}
void push(int x)
{
if (top > 4) {
cout << "stack overflow";
return;
}
stk[++top] = x;
cout << "inserted " << x;
}
void pop()
{
if (top < 0) {
cout << "stack underflow";
return;
}
cout << "deleted " << stk[top--];
}
void display()
{

Prof. N. S. Kulkarni (Cell: 9890966539/9096194081) 23


B. Sc. II Sem. IV (CBCS) Paper VII - Data Structures using C++ Course Code -DSC12D
if (top < 0) {
cout << " stack empty"; return; } for (int i = top; i >= 0; i--)
cout << stk[i] << " ";
}
};

int main()
{
int ch;
stack st;
while (1) {
cout << "\n1.push 2.pop 3.display 4.exit\nEnter ur choice: "; cin >> ch;
switch (ch) {
case 1:
cout << "enter the element: "; cin >> ch;
st.push(ch);
break;
case 2:
st.pop();
break;
case 3:
st.display();
break;
case 4:
exit(0);
}
}
}

Applications of stack:
1. Recursion
It is technique of solving any problem by calling same function again and again until some breaking
(base) condition where recursion stops and it starts calculating the solution from there on. Thus in
recursion last function called needs to be completed first. Now Stack is a LIFO data structure and
hence it is used to implement recursion. The High level Programming languages, such as Pascal, C
etc. that provides support for recursion, use stack. In each recursive call, there is need to save the
current values of parameters, local variables and the return address (the address where the
control has to return from the call). Also, as a function calls to another function, first its
arguments, then the return address and finally space for local variables is pushed onto the stack.
2. Well-formed parentheses
One of the most important application of stacks is to check if the parentheses are balanced in a
given expression. The compiler generated an error if the parentheses are not matched. Following
are the steps to find whether a given expression is balanced or unbalanced
i. Input the expression and put it in a character Stack
ii. Scan the character from the expression one by one
iii. If the scanned character is a starting bracket then push it to the stack

Prof. N. S. Kulkarni (Cell: 9890966539/9096194081) 24


B. Sc. II Sem. IV (CBCS) Paper VII - Data Structures using C++ Course Code -DSC12D
iv. If the scanned character is a closing bracket then pop from the stack and if the
popped character is the equivalent starting bracket, then proceed. Else, the
expression is unbalanced.
v. After scanning all the characters from the expression, if there is any parentheses
found in the stack or if the stack is not empty, then expression is unbalanced
3. Notations
The way to write arithmetic expression is known as a notation. An arithmetic expression can
be written in three different but equivalent notations, i.e., without changing the essence or
output of an expression. These notations are
 Infix Notation
We write expression in infix notation, e.g. a - b + c, where operators are used in-between
operands. It is easy for us humans to read, write, and speak in infix notation but the same
does not go well with computing devices. An algorithm to process infix notation could be
difficult and costly in terms of time and space consumption.
 Prefix (Polish) Notation
In this notation, operator is prefixed to operands, i.e. operator is written ahead of
operands. For example, +ab. This is equivalent to its infix notation a + b. Prefix notation is
also known as Polish Notation.
 Postfix (Reverse-Polish) Notation
This notation style is known as Reversed Polish Notation. In this notation style, the
operator is post fixed to the operands i.e., the operator is written after the operands. For
example, ab+. This is equivalent to its infix notation a + b.
The following table briefly tries to show the difference in all three notations −

Sr. No. Infix Notation Prefix Notation Postfix Notation

1 a+b +ab ab+

2 (a + b) ∗ c ∗+abc ab+c∗

3 a ∗ (b + c) ∗a+bc abc+∗

4 a/b+c/d +/ab/cd ab/cd/+

5 (a + b) ∗ (c + d) ∗+ab+cd ab+cd+∗

6 ((a + b) ∗ c) - d -∗+abcd ab+c∗d-

a. Conversion from Infix to Postfix using Stack


Let, X is an arithmetic expression written in infix notation. This algorithm finds the equivalent
postfix expression Y.
1. Push “(“onto Stack, and add “)” to the end of X.
2. Scan X from left to right and repeat Step 3 to 6 for each element of X until the Stack is
empty.
3. If an operand is encountered, add it to Y.
4. If a left parenthesis is encountered, push it onto Stack.
5. If an operator is encountered ,then:

Prof. N. S. Kulkarni (Cell: 9890966539/9096194081) 25


B. Sc. II Sem. IV (CBCS) Paper VII - Data Structures using C++ Course Code -DSC12D
1. Repeatedly pop from Stack and add to Y each operator (on the top of Stack)
which has the same precedence as or higher precedence than operator.
2. Add operator to Stack.
[End of If]
6. If a right parenthesis is encountered ,then:
1. Repeatedly pop from Stack and add to Y each operator (on the top of Stack)
until a left parenthesis is encountered.
2. Remove the left Parenthesis.
[End of If]
[End of If]
7. END.

b. Conversion from Infix to Prefix using Stack


1. Push “)” onto STACK, and add “(“ to end of the A
2. Scan A from right to left and repeat step 3 to 6 for each element of A until the STACK
is empty
3. If an operand is encountered add it to B
4. If a right parenthesis is encountered push it onto STACK
5. If an operator is encountered then:
a. Repeatedly pop from STACK and add to B each operator (on the top of STACK)
which has same or higher precedence than the operator.
b. Add operator to STACK
6. If left parenthesis is encountered then
a. Repeatedly pop from the STACK and add to B (each operator on top of stack until a
left parenthesis is encountered)
b. Remove the left parenthesis
7. Exit

1.7 Queue
Queue is an abstract data structure, somewhat similar to Stacks. Unlike stacks, a queue is open at
both its ends. One end is always used to insert data (enqueue) and the other is used to remove
data (dequeue). Queue follows First-In-First-Out methodology, i.e., the data item stored first will
be accessed first.

A real-world example of queue can be a single-lane one-way road, where the vehicle enters first,
exits first. More real-world examples can be seen as queues at the ticket windows and bus-stops.
Queue is a linear data structure where the first element is inserted from one end
called REAR and deleted from the other end called as FRONT. Front points to the beginning of the
queue and Rear points to the end of the queue. Queue follows the FIFO (First - In - First
Out) structure. According to its FIFO structure, element inserted first will also be removed first.
The enqueue() and dequeue() are two important functions used in a queue.
As in stacks, a queue can also be implemented using Arrays, Linked-lists, Pointers and
Structures. For the sake of simplicity, we shall implement queues using one-dimensional array.

1.7.1 Basic Operations


Prof. N. S. Kulkarni (Cell: 9890966539/9096194081) 26
B. Sc. II Sem. IV (CBCS) Paper VII - Data Structures using C++ Course Code -DSC12D
Queue operations may involve initializing or defining the queue, utilizing it, and then completely
erasing it from the memory. Here we shall try to understand the basic operations associated with
queues −
• enqueue() − add (store) an item to the queue.
• dequeue() − remove (access) an item from the queue.
Few more functions are required to make the above-mentioned queue operation efficient. 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.
In queue, we always dequeue (or access) data, pointed by front pointer and while enqueing (or
storing) data in the queue we take help of rear pointer.
 Enqueue Operation
Queues maintain two data pointers, front and rear. Therefore, its operations are
comparatively difficult to implement than that of stacks.
 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.

1.7.2 Types of Queue


a. Linear/Simple

As is clear from the name itself, simple queue lets us perform the operations simply.
i.e., the insertion and deletions are performed likewise. Insertion occurs at the rear
(end) of the queue and deletions are performed at the front (beginning) of the queue
list. All nodes are connected to each other in a sequential manner. The pointer of the
first node points to the value of the second and so on.

b. Circular

Unlike the simple queues, in a circular queue each node is connected to the next
node in sequence but the last node’s pointer is also connected to the first node’s
address. Hence, the last node and the first node also gets connected making a circular
link overall.

c. Priority
Priority queue makes data retrieval possible only through a pre-determined priority
number assigned to the data items. While the deletion is performed in accordance to
Prof. N. S. Kulkarni (Cell: 9890966539/9096194081) 27
B. Sc. II Sem. IV (CBCS) Paper VII - Data Structures using C++ Course Code -DSC12D
priority number (the data item with highest priority is removed first), insertion is
performed only in the order.

d. Double ended
The doubly ended queue or dequeue allows the insert and delete operations from
both ends (front and rear) of the queue.

1.7.3 Implementation of Linear Queue using array

#include<iostream>
#include<process.h>
#define MAX 50
using namespace std;

class Queue
{
int queue_arr[MAX];
int rear,front;
public:
Queue()
{
rear=-1;
front=-1;
}
//This function will insert an element to the queue
void enqueue()
{
int added_item;
if (rear==MAX-1)
{
cout<<"\nQueue Overflow\n";
return;
}
else

Prof. N. S. Kulkarni (Cell: 9890966539/9096194081) 28


B. Sc. II Sem. IV (CBCS) Paper VII - Data Structures using C++ Course Code -DSC12D
{
if (front==-1) /*If queue is initially empty */
front=0;
cout<<"\nInput the element for adding in queue:";
cin>>added_item;
rear=rear+1;
//Inserting the element
queue_arr[rear] = added_item ;
}
}
//This function will delete (or pop) an element from the queue
void dequeue()
{
if (front==-1 || front>rear)
{
cout<<"\nQueue Underflow\n";
}
else
{
//deleteing the element
cout<<"\nElement deleted from queue is :\n"<<queue_arr[front];
front=front+1;
}
}
//Displaying all the elements of the queue
void traverse()
{
int i;
//Checking whether the queue is empty or not
if (front ==-1 || front>rear)
{
cout<<"\nQueue is empty\n";
}
else
{
cout<<"\nQueue is :\n";
for(i=front;i<= rear;i++)
cout<<queue_arr[i]<<"\n";
}
}/*End of display() */
};
void main()
{
int choice;
Queue q;
while (1)
{

Prof. N. S. Kulkarni (Cell: 9890966539/9096194081) 29


B. Sc. II Sem. IV (CBCS) Paper VII - Data Structures using C++ Course Code -DSC12D
//Menu options
cout<<"\n1.Enqueue\n2.Dequeue\n3.Traverse\n4.Quit\n";
cout<<"\nEnter your choice:";
cin>>choice;
switch(choice)
{
case 1 :
q.enqueue();
break;
case 2:
q.dequeue();
break;
case 3:
q.traverse();
break;
case 4:
exit(1);
default:
cerr<<"\n Wrong choice\n";

}
}
}

1.7.4 Implementation of Circular Queue using array


#include <iostream>
#define SIZE 5 /* Size of Circular Queue */
using namespace std;
class Queue {
private:
int items[SIZE], front, rear;

public:
Queue(){
front = -1;
rear = -1;
}

bool isFull(){
if(front == 0 && rear == SIZE - 1){
return true;
}
if(front == rear + 1) {
return true;
}
return false;
}
bool isEmpty(){
Prof. N. S. Kulkarni (Cell: 9890966539/9096194081) 30
B. Sc. II Sem. IV (CBCS) Paper VII - Data Structures using C++ Course Code -DSC12D
if(front == -1)
return true;
else
return false;
}

void enQueue(int element){


if(isFull()){
cout << "Queue is full";
}
else {
if(front == -1)
front = 0;
rear = (rear + 1) % SIZE;
items[rear] = element;
cout << endl << "Inserted " << element << endl;
}
}

int deQueue(){
int element;
if(isEmpty() ){
cout << "Queue is empty" << endl;
return(-1);
}
else {
element = items[front];
if(front == rear){
front = -1;
rear = -1;
} /* Q has only one element, so we reset the queue after deleting it. */
else {
front=(front+1) % SIZE;
}
return(element);
}
}

void display()
{
/* Function to display status of Circular Queue */
int i;
if(isEmpty()) {
cout << endl << "Empty Queue" << endl;
}
else
{
cout << "Front -> " << front;
Prof. N. S. Kulkarni (Cell: 9890966539/9096194081) 31
B. Sc. II Sem. IV (CBCS) Paper VII - Data Structures using C++ Course Code -DSC12D
cout << endl << "Items -> ";
for(i=front; i!=rear;i=(i+1)%SIZE)
cout << items[i];
cout << items[i];
cout << endl << "Rear -> " << rear;
}
}

};
int main()
{
Queue q;

// Fails because front = -1


q.deQueue();
q.enQueue(1);
q.enQueue(2);
q.enQueue(3);
q.enQueue(4);
q.enQueue(5);

// Fails to enqueue because front == 0 && rear == SIZE - 1


q.enQueue(6);
q.display();

int elem = q.deQueue();

if( elem != -1)


cout << endl << "Deleted Element is " << elem;

q.display();
q.enQueue(7);
q.display();

// Fails to enqueue because front == rear + 1


q.enQueue(8);
return 0;
}
1.7.5 Applications of Queue
i. Job Scheduling
ii. Print Queue
iii. I/O Operations
iv. Recognizing Palindrome
v. Traffic Light functioning (Circular Q)
vi. Page replacement algorithms (Circular Q)
vii. Prim’s , Dijkstra’s shortest path , A* algorithms implementation (Priority Q)
viii. Load balancing, interrupt handling (Priority Q)

Prof. N. S. Kulkarni (Cell: 9890966539/9096194081) 32


B. Sc. II Sem. IV (CBCS) Paper VII - Data Structures using C++ Course Code -DSC12D

Unit – II: Non Linear Data Structures-Linked List and Trees

2.1 Linked List:


A linked list, in simple terms, is a linear collection of data elements. These data elements are called
nodes. Linked list is a data structure which in turn can be used to implement other data structures.
Thus, it acts as a building block to implement data structures such as stacks, queues, and their
variations. A linked list can be perceived as a train or a sequence of nodes in which each node
contains one or more data fields and a pointer to the next node. Linked List is a very commonly
used linear data structure which consists of group of nodes in a sequence. Each node holds its
own data and the address of the next node hence forming a chain like structure. In Linked list
elements are not stored at contiguous memory locations. The elements in a linked list are linked
using pointers.

We can see a linked list in which every node contains two parts, data and a pointer to the next
node. The left part of the node which contains data may include a simple data type, an array, or a
structure. The right part of the node contains a pointer to the next node (or address of the next
node in sequence). The last node will have no next node connected to it, so it will store a special
value called NULL. Arrays can be used to store linear data of similar types, but arrays have the
following limitations-
1. The size of the arrays is fixed: So we must know the upper limit on the number of elements in
advance. Also, generally, the allocated memory is equal to the upper limit irrespective of the
usage.
2. Inserting a new element in an array of elements is expensive because the room has to be
created for the new elements and to create room existing elements have to be shifted.

The primitive operations performed on the linked list are as follows -


1. Creation
Creation operation is used to create a linked list. Once a linked list is created with one node,
insertion operation can be used to add more elements in a node.
2. Insertion
Insertion operation is used to insert a new node at any specified location in the linked list. A new
node may be inserted.
(a) At the beginning of the linked list
(b) At the end of the linked list
(c) At any specified position in between in a linked list
3. Deletion
Deletion operation is used to delete an item (or node) from the linked list. A node may be deleted
from the
(a) Beginning of a linked list
(b) End of a linked list
(c) Specified location of the linked list
4. Traversing
Prof. N. S. Kulkarni (Cell: 9890966539/9096194081) 33
B. Sc. II Sem. IV (CBCS) Paper VII - Data Structures using C++ Course Code -DSC12D
Traversing is the process of going through all the nodes from one end to another end of a linked
list. In a singly linked list we can visit from left to right, forward traversing, and nodes only. But in
doubly linked list forward and backward traversing is possible.
5. Searching

2.1.1 Advantages and Disadvantages


Linked list have many advantages and some of them are:
1. Linked list are dynamic data structure. That is, they can grow or shrink during the
execution of a program.
2. Efficient memory utilization: In linked list (or dynamic) representation, memory is not
pre-allocated. Memory is allocated whenever it is required. And it is de-allocated (or
removed) when it is not needed.
3. Insertion and deletion are easier and efficient. Linked list provides flexibility in
inserting a data item at a specified position and deletion of a data item from the given
position.
4. Many complex applications can be easily carried out with linked list.
Linked list has following disadvantages
1. More memory: to store an integer number, a node with integer data and address field
is allocated. That is more memory space is needed.
2. Access to an arbitrary data item is little bit cumbersome and also time consuming.

2.1.2 Types of Linked List


a. Singly linked
All the nodes in a singly linked list are arranged sequentially by linking with a pointer. A singly
linked list can grow or shrink, because it is a dynamic data structure. Begins with a pointer to
the first node terminates with a null pointer & only traversed in one direction.
b. Doubly linked
Has two start pointers pointing to first element and last element. Each node has a forward
pointer and a backward pointer. Allows traversals both forwards and backwards.
c. Linear
Linear Linked list is the default linked list and a linear data structure in which data is not stored
in contiguous memory locations but each data node is connected to the next data node via a
pointer, hence forming a chain.
d. Circular
Circular Linked List is little more complicated linked data structure. In the circular linked list
the previous element stores the address of the next element and the last element stores the
address of the starting element. The elements points to each other in a circular way which
forms a circular chain. A circular linked list is one, which has no beginning and no end. A singly
linked list can be made a circular linked list by simply storing the address of the very first node
in the linked field of the last node.

Pointer in the last node points back to the first node


Prof. N. S. Kulkarni (Cell: 9890966539/9096194081) 34
B. Sc. II Sem. IV (CBCS) Paper VII - Data Structures using C++ Course Code -DSC12D
Drawbacks
1. Random access is not allowed. We have to access elements sequentially starting from the
first node. So we cannot do binary search with linked lists efficiently with its default
implementation. Read about it here.
2. Extra memory space for a pointer is required with each element of the list.
3. Not cache friendly. Since array elements are contiguous locations, there is locality of
reference which is not there in case of linked lists.

2.1.3 Implementation
A linked list is represented by a pointer to the first node of the linked list. The first node is called
the head. If the linked list is empty, then the value of the head is NULL. Each node in a list consists
of at least two parts:
1) Data
2) Pointer (Or Reference) to the next node.
In C it can be represented as Structure but In C++, Linked List can be represented as a class and a
Node as a separate class. The Linked List class contains a reference of Node class type.
#include <iostream.h>
using namespace std;

class Node {
public:
int data;
Node* next;
};

// Program to create a simple linked


// list with 3 nodes
int main()
{
Node* head = NULL;
Node* second = NULL;
Node* third = NULL;

// allocate 3 nodes in the heap


head = new Node();
second = new Node();
third = new Node();
head->data = 1; // assign data in first node
head->next = second; // Link first node with
// the second node
// assign data to second node
second->data = 2;

// Link second node with the third node


second->next = third;
third->data = 3; // assign data to third node
third->next = NULL;
return 0;
Prof. N. S. Kulkarni (Cell: 9890966539/9096194081) 35
B. Sc. II Sem. IV (CBCS) Paper VII - Data Structures using C++ Course Code -DSC12D
}

2.1.4 Application
a) Implementation of stack using linked list.
A stack can be easily implemented through the linked list. In stack Implementation, a stack
contains a top pointer, which is “head” of the stack where pushing and popping items
happens at the head of the list. first node have null in link field and second node link have
first node address in link field and so on and last node address in “top” pointer.
The main advantage of using linked list over an arrays is that it is possible to
implements a stack that can shrink or grow as much as needed. In using array will put a
restriction to the maximum capacity of the array which can lead to stack overflow. Here
each new node will be dynamically allocate, so overflow is not possible.

b) Implementation of queue using linked list.


The major problem with the queue implemented using an array is, it will work for an only fixed
number of data values. That means, the amount of data must be specified at the beginning
itself. Queue using an array is not suitable when we don't know the size of data which we are
going to use. A queue data structure can be implemented using a linked list data structure.
The queue which is implemented using a linked list can work for an unlimited number of
values. That means, queue using linked list can work for the variable size of data (No need to
fix the size at the beginning of the implementation). The Queue implemented using linked list
can organize as many data values as we want.

In linked list implementation of a queue, the last inserted node is always pointed by 'rear' and
the first node is always pointed by 'front'.
Example

In above example, the last inserted node is 50 and it is pointed by 'rear' and the first inserted
node is 10 and it is pointed by 'front'. The order of elements inserted is 10, 15, 22 and 50.

2.2 Trees:
In computer science, a tree is a widely used abstract data type (ADT) that simulates a
hierarchical tree structure, with a root value and sub-trees of children with a parent node,
represented as a set of linked nodes. A tree is a collection of entities called nodes. Nodes are
connected by edges. Each node contains a value or data, and it may or may not have a child node.
The first node of the tree is called the root. If this root node is connected by another node,
the root is then a parent node and the connected node is a child. All Tree nodes are connected by
links called edges. It’s an important part of trees, because it’s manages the relationship
between nodes. Leaves are the last nodes on a tree. They are nodes without children. Like real
trees, we have the root, branches, and finally the leaves. The height of a tree is the length of the
longest path to a leaf. The depth of a node is the length of the path to its root.
Tree is a hierarchical data structure which stores the information naturally in the form of
hierarchy style. Tree is one of the most powerful and advanced data structures. It is a non-linear
data structure compared to arrays, linked lists, stack and queue.

Prof. N. S. Kulkarni (Cell: 9890966539/9096194081) 36


B. Sc. II Sem. IV (CBCS) Paper VII - Data Structures using C++ Course Code -DSC12D

2.2.1 Terminologies
Field Description

Root is a special node in a tree. The entire tree is referenced through it. It does
Root
not have a parent.

Parent Node Parent node is an immediate predecessor of a node.

Child Node All immediate successors of a node are its children.

Siblings Nodes with the same parent are called Siblings.

Path Path is a number of successive edges from source node to destination node.

Height of a node represents the number of edges on the longest path between
Height of Node
that node and a leaf.

Height of Tree Height of tree represents the height of its root node.

Depth of a node represents the number of edges from the tree's root node to
Depth of Node
the node.

Degree of Node Degree of a node represents a number of children of a node.

Edge is a connection between one node to another. It is a line between two


Edge
nodes or a node and a leaf.

Forest Forest is a collection of disjoint trees.

Branch/Internal An internal node (also known as an inner node, inode for short, or branch node)
Node is any node of a tree that has child nodes

External/Leaf An external node (also known as an outer node, leaf node, or terminal node) is
/Terminal Node any node that does not have child nodes.

A descendant node of a node is any node in the path from that node to the
Descendant leaf node (including the leaf node). The immediate descendant of a node is the
“child” node.

An ancestor node of a node is any node in the path from that node to the
Ancestor
root node (including the root node).
It is the number of edges arriving at a node. The root node is the only node that
In-Degree
has an in-degree equal to zero.

Prof. N. S. Kulkarni (Cell: 9890966539/9096194081) 37


B. Sc. II Sem. IV (CBCS) Paper VII - Data Structures using C++ Course Code -DSC12D

Out-degree Out-degree of a node is the number of edges leaving that node.

2.2.2 Advantages of Tree


o Tree reflects structural relationships in the data.
o It is used to represent hierarchies.
o It provides an efficient insertion and searching operations.
o Trees are flexible. It allows to move sub-trees around with minimum effort.

2.3 Binary Tree:


A binary tree is a special type of tree in which every node or vertex has either no child node or one
child node or two child nodes. A binary tree is an important class of a tree data structure in which
a node can have at most two children. This is one of the most commonly used trees. Child node in
a binary tree on the left is termed as 'left child node' and node in the right is termed as the 'right
child node.'
In the figure mentioned below, the root node 8 has two children 3 and 10; then this two
child node again acts as a parent node for 1 and 6 for left parent node 3 and 14 for right parent
node 10. Similarly, 6 and 14 has a child node.

A binary tree may also be defined as follows:


→ A binary tree is either an empty tree.
→ Or a binary tree consists of a node called the root node, a left sub-tree and a right sub-
tree, both of which will act as a binary tree once again

2.3.1 Types of Binary Tree


a. Full/Proper/Plane/Strict
A Binary Tree is full if every node has 0 or 2 children. We can also say a full binary tree is a
binary tree in which all nodes except leaves have two children. In other words, if all the nodes
other than leaf nodes has 0 or 2 children, then the tree is Full Binary Tree. All of the nodes in
such tree are of degree zero of two, never degree one.
In a Full Binary, number of leaf nodes is number of internal nodes plus 1. L=I+1, Where L =
Number of leaf nodes, I = Number of internal nodes

Prof. N. S. Kulkarni (Cell: 9890966539/9096194081) 38


B. Sc. II Sem. IV (CBCS) Paper VII - Data Structures using C++ Course Code -DSC12D

b. Complete
A Binary Tree is complete Binary Tree if all levels are completely filled except possibly the last
level and the last level has all keys as left as possible.

c. Perfect
A Binary tree is Perfect Binary Tree in which all internal nodes have exactly two children and all
leaves are at the same level. A Perfect Binary Tree of height h (where height is the number of
nodes on the path from the root to leaf) has 2h – 1 node.

d. Skewed
A Binary tree, which is dominated solely by left child noted or right child nodes, is called a
skewed binary tree, more specifically left skewed binary tree or right skewed binary tree. All
skewed trees are pathological trees (tree where every parent node has only one child either
left or right).

e. Balanced
A binary tree is balanced if the height of the tree is O(Log n) where n is the number of nodes.
For Example, AVL tree maintains O(Log n) height by making sure that the difference between
heights of left and right sub-trees is at most 1. Red-Black trees maintain O(Log n) height by
making sure that the number of Black nodes on every root to leaf paths are same and there
Prof. N. S. Kulkarni (Cell: 9890966539/9096194081) 39
B. Sc. II Sem. IV (CBCS) Paper VII - Data Structures using C++ Course Code -DSC12D
are no adjacent red nodes. Balanced Binary Search trees are performance wise good as they
provide O(log n) time for search, insert and delete.

2.3.2 Array representation of Binary Tree


This method is easy to understand and implement. It's very useful for certain kinds of tree
applications, such as heaps, and fairly useless for others. Steps to implement binary trees using
arrays:
1. Take a complete binary tree and number its nodes from top to bottom, left to right.
2. The root is 0, the left child 1, the right child 2, the left child of the left child 3, etc.
3. Put the data for node i of this tree in the ith element of an Array.
4. If you have a partial (incomplete) binary tree, and node i is absent, put some value that
represents "no data" in the ith position of the array.

Three simple formulae allow you to go from the index of the parent to the index of its children and
vice versa:
• if index(parent) = N, index(left child) = 2*N+1
• if index(parent) = N, index(right child) = 2*N+2
• if index(child) = N, index(parent) = (N-1)/2 (integer division with truncation)

Figure: Array Representation of Trees

2.4 Binary Search Tree:


A binary search tree is a binary tree in which the data in the nodes are ordered in a particular way.
To be precise, starting at any given node, the data in any nodes of its left sub tree must all be less
than the item in the given node, and the data in any nodes of its right sub tree must be greater
than or equal to the data in the given node. For numbers this can obviously be done. For strings,

Prof. N. S. Kulkarni (Cell: 9890966539/9096194081) 40


B. Sc. II Sem. IV (CBCS) Paper VII - Data Structures using C++ Course Code -DSC12D
alphabetical ordering is often used. For records of data, a comparison based on a particular field
(the key field) is often used.
2.4.1 Representation of Binary Search Tree
A Binary Search Tree (BST) is a tree in which all the nodes follow the below-mentioned properties

• The left sub-tree of a node has a key less than or equal to its parent node's key.
• The right sub-tree of a node has a key greater than to its parent node's key.

Thus, BST divides all its sub-trees into two segments; the left sub-tree and the right sub-tree and
can be defined as − left_subtree (keys) ≤ node (key) ≤ right_subtree (keys)

BST is a collection of nodes arranged in a way where they maintain BST properties. Each
node has a key and an associated value. While searching, the desired key is compared to the keys
in BST and if found, the associated value is retrieved. Following is a pictorial representation of BST

We observe that the root node key (27) has all less-valued keys on the left sub-tree and the
higher valued keys on the right sub-tree.
Let us consider that we have a tree T. let our tree T is a binary tree that us complete binary
tree. Then there is an efficient way of representing T in the memory called the sequential
representation or array representation of T. This representation uses only a linear array TREE as
follows:
1. The root N of T is stored in TREE [1].
2. If a node occupies TREE [k] then its left child is stored in TREE [2 * k] and its right child is
stored into TREE [2 * k + 1].
For Example:
Consider the following Tree:

Its sequential representation is as follow:

2.4.2 Operations
1. Insertion

Prof. N. S. Kulkarni (Cell: 9890966539/9096194081) 41


B. Sc. II Sem. IV (CBCS) Paper VII - Data Structures using C++ Course Code -DSC12D
In a binary search tree, the insertion operation is performed with O(log n) time complexity. In
binary search tree, new node is always inserted as a leaf node. The insertion operation is
performed as follows...

Step 1 - Create a newNode with given value and set its left and right to NULL.
Step 2 - Check whether tree is Empty.
Step 3 - If the tree is Empty, then set root to newNode.
Step 4 - If the tree is Not Empty, then check whether the value of newNode is smaller or
larger than the node (here it is root node).
Step 5 - If newNode is smaller than or equal to the node then move to its left child. If
newNode is larger than the node then move to its right child.
Step 6- Repeat the above steps until we reach to the leaf node (i.e., reaches to NULL).
Step 7 - After reaching the leaf node, insert the newNode as left child if the newNode
is smaller or equal to that leaf node or else insert it as right child.

2. Deletion
In a binary search tree, the deletion operation is performed with O(log n) time complexity.
Deleting a node from Binary search tree includes following three cases...
Case 1: Deleting a Leaf node (A node with no children)
We use the following steps to delete a leaf node from BST...
Step 1 - Find the node to be deleted using search operation
Step 2 - Delete the node using free function (If it is a leaf) and terminate the function.
Case 2: Deleting a node with one child
We use the following steps to delete a node with one child from BST...
Step 1 - Find the node to be deleted using search operation
Step 2 - If it has only one child then create a link between its parent node and child
node.
Step 3 - Delete the node using free function and terminate the function.
Case 3: Deleting a node with two children
We use the following steps to delete a node with two children from BST...
Step 1 - Find the node to be deleted using search operation
Step 2 - If it has two children, then find the largest node in its left subtree (OR)
the smallest node in its right subtree.
Step 3 - Swap both deleting node and node which is found in the above step.
Step 4 - Then check whether deleting node came to case 1 or case 2 or else goto step
2
Step 5 - If it comes to case 1, then delete using case 1 logic.
Step 6- If it comes to case 2, then delete using case 2 logic.
Step 7 - Repeat the same process until the node is deleted from the tree.

3. Search
In a binary search tree, the search operation is performed with O(log n) time complexity. The
search operation is performed as follows...
Step 1 - Read the search element from the user.
Step 2 - Compare the search element with the value of root node in the tree.
Step 3 -If both are matched, then display "Given node is found!!!" and terminate the
function

Prof. N. S. Kulkarni (Cell: 9890966539/9096194081) 42


B. Sc. II Sem. IV (CBCS) Paper VII - Data Structures using C++ Course Code -DSC12D
Step 4 - If both are not matched, then check whether search element is smaller or larger
than that node value.
Step 5 - If search element is smaller, then continue the search process in left sub-tree.
Step 6 - If search element is larger, then continue the search process in right sub-tree.
Step 7 - Repeat the same until we find the exact element or until the search element is
compared with the leaf node
Step 8 - If we reach to the node having the value equal to the search value then display
"Element is found" and terminate the function.
Step 9 - If we reach to the leaf node and if it is also not matched with the search element,
then display "Element is not found" and terminate the function.
Example:
Construct a Binary Search Tree by inserting the following sequence of numbers...
10, 12, 5, 4,20,8,7,15 and 13
Above elements are inserted into a Binary Search Tree as follows...

4. Traversal

Prof. N. S. Kulkarni (Cell: 9890966539/9096194081) 43


B. Sc. II Sem. IV (CBCS) Paper VII - Data Structures using C++ Course Code -DSC12D

a. Pre-order
1. Visit the root
2. Traverse the left sub tree i.e. call Preorder (left sub tree)
3. Traverse the right sub tree i.e. call Preorder (right sub tree)
Root → Left → Right

Preorder Traversal Shortcut


Traverse the entire tree starting from the root node keeping yourself to the left.

Applications-
• Preorder traversal is used to get prefix expression of an expression tree.
• Preorder traversal is used to create a copy of the tree

b. In-order
Traverse the left sub tree i.e. call Inorder (left sub tree)
1. Visit the root
2. Traverse the right sub tree i.e. call Inorder (right sub tree)
Prof. N. S. Kulkarni (Cell: 9890966539/9096194081) 44
B. Sc. II Sem. IV (CBCS) Paper VII - Data Structures using C++ Course Code -DSC12D
Left → Root → Right

Consider the following example-

Inorder Traversal Shortcut


Keep a plane mirror horizontally at the bottom of the tree and take the projection of all the nodes.

Application-
• Inorder traversal is used to get infix expression of an expression tree.

c. Post-order
1. Traverse the left sub tree i.e. call Postorder (left sub tree)
2. Traverse the right sub tree i.e. call Postorder (right sub tree)
3. Visit the root
Left → Right → Root

Example-
Consider the following example-

Prof. N. S. Kulkarni (Cell: 9890966539/9096194081) 45


B. Sc. II Sem. IV (CBCS) Paper VII - Data Structures using C++ Course Code -DSC12D

Postorder Traversal Shortcut


Pluck all the leftmost leaf nodes one by one

Applications-

• Postorder traversal is used to get postfix expression of an expression tree.


• Postorder traversal is used to delete the tree.
• This is because it deletes the children first and then it deletes the parent.

d. Breadth First Traversal-


Breadth First Traversal of a tree prints all the nodes of a tree level by level. Breadth First Traversal
is also called as Level Order Traversal.

Example-

Prof. N. S. Kulkarni (Cell: 9890966539/9096194081) 46


B. Sc. II Sem. IV (CBCS) Paper VII - Data Structures using C++ Course Code -DSC12D

Application-
• Level order traversal is used to print the data in the same order as stored in the array
representation of a complete binary tree.

Prof. N. S. Kulkarni (Cell: 9890966539/9096194081) 47

You might also like