Data Structure Through C++
Data Structure Through C++
c++ E-BOOK
Page 1 of 278
Page 2 of 278
UNIT - 1
Analysis of Algorithm
Page 3 of 278
Analysis of Algorithm
8/13/2015 scorm content
Introduction
Welcome to the session on Analysis of Algorithm.
This course will help you to understand what is data structure to solve the real time problems.
In computer science, a data structure is a particular way of storing and organizing data in a
computer so that it can be used efficiently.
Different kinds of data structures are suited to different kinds of applications, and some are
highly specialized to specific tasks.
At the end of this session, you will be able to:
To understand the concepts in object oriented language such as c++.
Analysis step by step and develop algorithm to solve real time problems.
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit1/assets/2.html 4 of 278 1/1
Analysis of Algorithm
8/13/2015 scorm content
Introduction to algorithm design and Data Structure
What this course is about:
Data structures & algorithms
ADT
Algorithm analysis
Additional of C++
Representing information is fundamental to computer science.
The primary purpose of most computer programs is not to perform calculations, but to store and
retrieve information usually as fast as possible. For this reason, the study of data structures and
the algorithms that manipulate them is at the heart of computer science.
And that is what this course is about — helping you to understand how to structure information
to support efficient processing.
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit1/assets/3.html 5 of 278 1/1
Analysis of Algorithm
8/13/2015 scorm content
Goals of this courses
A data structure is a particular way of storing and organizing data in a computer so that it can be
used efficiently.
The first is to present the commonly used data structures.
These form a programmer’s basic data structure toolkit.
For many problems, some data structure in the toolkit provides a good solution.
The second goal is to introduce the idea of tradeoffs and reinforce the concept that there are
costs and benefits associated with every data structure.
This is done by describing, for each data structure, the amount of space and time required for
typical operations.
The third goal is to teach how to measure the effectiveness of a data structure or algorithm.
Only through such measurement can you determine which data structure in your toolkit is most
appropriate for a new problem.
The techniques presented also allow you to judge the merits of new data structures that you or
others might invent.
There are often many approaches to solving a problem.
How do we choose between them?
For that two goals are developed.
The resulting program is true to both of these goals. we might say that such a program is
“elegant.”
While the algorithms and program code examples presented here attempt to be elegant in this
sense, it is not the purpose of this book to explicitly treat issues related to goal.
At the heart of computer program design two goals for efficient.
To design an algorithm that is easy to understand, code, and debug.
To design an algorithm that makes efficient use of the computer’s resources.
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit1/assets/4.html 6 of 278 1/1
Analysis of Algorithm
8/13/2015 scorm content
Need for Data Structures
A solution is said to be efficient if it solves the problem within the required resource constraints.
Need to utilize the hardware effectively.
Easy to do operations such as insertion, deletion, update, searching.
You might think that with ever more powerful computers, program efficiency is becoming less
important.
After all, processor speed and memory size still continue to improve.
Won’t any efficiency problem we might have today be solved by tomorrow’s hardware?
We develop more powerful computers, our history so far has always been to use that additional
computing power to tackle more complex problems, be it in the form of more sophisticated user
interfaces, bigger problem sizes, or new problems previously deemed computationally infeasible.
Today’s computer scientists must be trained to have a thorough understanding of the principles
behind efficient program design, because their ordinary life experiences often do not apply when
designing computer programs.
When selecting a data structure to solve a problem, you should follow these steps.
Analyze your problem to determine the basic operations that must be supported. Examples of
basic operations include inserting a data item into the data structure, deleting a data item
from the data structure, and finding a specified data item.
Quantify the resource constraints for each operation.
Select the data structure that best meets these requirements.
These threestep approach to selecting a data structure operationalizes a data centered view of
the design process.
The first concern is for the data and the operations to be performed on them, the next concern is
the representation for those data, and the final concern is the implementation of that
representation.
Ask yourself whenever you must choose a data structure:
Are all data items inserted into the data structure at the beginning, or are insertions
interspersed with other operations? Static applications (where the data are loaded at the
beginning and never change) typically require only simpler data structures to get an efficient
implementation than do dynamic applications.
Can data items be deleted? If so, this will probably make the implementation more
complicated.
Are all data items processed in some well defined order, or is search for specific data items
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit1/assets/5.html 7 of 278 1/2
Analysis of Algorithm
8/13/2015 scorm content
allowed? “Random access” search generally requires more complex data structures.
These three questions are must to choose the data structure.
The first question says about the data insertion and its time complicity.
Second question represents the deletion operation and its complicity.
Third question is to access the data in welldefined order, so that the complicity is to be less.
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit1/assets/5.html 8 of 278 2/2
Analysis of Algorithm
8/13/2015 scorm content
Structure: how data is organized
Place data contiguously
Place data here and there with links
Place data with formula
Placing data is organized in three different ways, The 1st one is to store it in continuous order.
The second method is to place it randomly using links to refer the data, the third is using
formulas.
We can″t differ these three method using efficiently, because the efficiency would be differ in
different situations.
In one situation the continuous method should give more efficient than the random method, in
other situation the random method would be good than continuous.
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit1/assets/6.html 9 of 278 1/1
Analysis of Algorithm
8/13/2015 scorm content
ADT
An abstract model of a data structure together with the operations (can be treated as a form of
algorithms) processed on the data structure.
In C++ or Java, an ADT can be implemented as a class.
In C++ the abstract data type is fulfilled by creation of class.
It is a model of data structure together with the operation processed on the data structure.
It would be static, not a dynamic model.
The relationship between data items, abstract data types, and data structures.
The ADT defines the logical form of the data type.
The data structure implements the physical form of the datatype.
Data types have both a logical and a physical form.
The definition of the data Type in terms of an ADT is its logical form.
The implementation of the data type as a data structure is its physical form.
When you implement an ADT, you are dealing with the physical form of the associated data
type.
When you use an ADT elsewhere in your program, you are concerned with the associated data
type’s logical form.
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit1/assets/7.html 10 of 278 1/1
Analysis of Algorithm
8/13/2015 scorm content
Design and analysis of algorithm: Algorithms definition
An algorithm is a method or a process followed to solve a problem.
Algorithm is a step by step process.
Is used to solve a big problem by dividing it into small pieces.
A problem can be solved using a single algorithm or it would be solved by integrating many
algorithm.
If the problem is viewed as a function, then an algorithm is an implementation for the function
that transforms an input to the corresponding output.
Advantages of algorithm
There are many advantages creating an algorithm.
Solve a big problem in simple way.
It is a step by step process so that it would be understandable.
Every algorithm is best in any one of the situation.
Modification is simple in every based on the situation.
Every algorithm should contain an individual advantage.
Here it presents an common advantage for creation an algorithm.
The main advantage is solving a big problem in simple way by step by step process.
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit1/assets/8.html 11 of 278 1/1
Analysis of Algorithm
8/13/2015 scorm content
Algorithm Properties
It must be correct.
It must compute the desired function, converting each input to the correct output.
Note that every algorithm implements some function, because every algorithm maps every
input to some output.
At issue here is whether a given algorithm implements the intended function.
It is composed of a series of concrete steps.
Concrete means that the action described by that step is completely understood — and
doable — by the person or machine that must perform the algorithm.
Each step must also be do able in a finite amount of time.
The algorithm gives us a recipe for solving the problem by performing a series of steps,
where each such step is within our capacity to perform.
The ability to perform a step can depend on who or what is intended to execute the recipe.
For example, the steps of a cookie recipe in a cookbook might be considered sufficiently
concrete for instructing a human cook, but not for programming an automated cookie making
factory.
There can be no ambiguity as to which step will be performed next.
Often it is the next step of the algorithm description.
Selection is normally a part of any language for describing algorithms.
Example the if statement in C++.
Selection allows a choice for which step will be performed next, but the selection process is
unambiguous at the time when the choice is made.
It must be composed of a finite number of steps.
If the description for the algorithm were made up of an infinite number of steps, we could
never hope to write it down, nor implement it as a computer program.
Most languages for describing provide some way to perform repeated actions, known as
iteration.
Examples of iteration in programming languages include the while and for loop constructs of
C++.
Iteration allows for short descriptions, with the number of steps actually performed controlled
by the input
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit1/assets/9.html 12 of 278 1/2
Analysis of Algorithm
8/13/2015 scorm content
It must terminate
It may not go into an Infinite Loop.
If an algorithm contains any loop means it should be terminate.
No closed loop should be allowed.
This property is used to avoid the deadlock.
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit1/assets/9.html 13 of 278 2/2
Analysis of Algorithm
8/13/2015 scorm content
Algorithm Analysis
A process of determining the amount of time, resource, etc. required when executing an
algorithm.
Analysis of algorithm is used to determine the efficient of algorithm.
It used to compare the algorithm based on the problems defined.
The main factor to find out the efficient of the algorithm is time, space complicity.
An algorithm is useful in every situation for a specific problem with less time and space
complicity is a good algorithm.
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit1/assets/10.html 14 of 278 1/1
Analysis of Algorithm
8/13/2015 scorm content
Big Oh Notation
Big Oh notation is used to capture the most dominant term in a function, and to represent the
growth rate.
Also called asymptotic upper bound.
We need an measure value to differ the algorithm.
For those problem the data structure represents an mathematical notation called Big oh.
This notation is used to capture the most dominant terms in a function and also for the growth
rate.
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit1/assets/11.html 15 of 278 1/1
Analysis of Algorithm
8/13/2015 scorm content
Functions in order of increasing growth rate
Function Name
C Constant
LogN Logarithmic
Log 2 N Logsquared
N Linear
NlogN NlogN
N2 Quaratic
N3 Cubic
2n Exponential
The table shows the functions in order of increasing growth rate.
If the result would be C, then it called as constant. Same value for each iteration.
The next rate is LogN, where n is the number of steps followed by the algorithm.
The next iteration is Log 2 N, it is a medium rate.
Next is N, called as N steps followed by the algorithm.
NlogN, worst than the N
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit1/assets/12.html 16 of 278 1/1
Analysis of Algorithm
8/13/2015 scorm content
Examples of Algorithm Running Times
Min element in an array: O(n).
Closest points in the plane, ie. Smallest distance pairs: n(n1)/2 => O(n 2 ).
Colinear points in the plane, ie. 3 points on a straight line: n(n1)(n2)/6 => O(n 3 ).
It shows the three different running time of three different algorithm in three different complicity.
The O() notate the oh notation.
Here the out comes are O(n), O(n 2 ), O(n 3 ).
The O(n) is the best case, O(n 3 ) is the worst cases regarding this examples.
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit1/assets/13.html 17 of 278 1/1
Analysis of Algorithm
8/13/2015 scorm content
Brute Force Algorithm
Brute force is a crude algorithm which works through every possible answer until the correct one
is found.
Some problems can be solved this way but others for instance obtaining the prime factors of
large numbers or picking the best chess move, have far too many possibilities to be solved that
way except in simple cases.
We do not need precise calculations for a BigOh estimate.
In many cases, we can use the simple rule of multiplying the size of all the nested loops.
template <class Comparable>
Comparable maxSubSum(const vector<Comparable> a,
int & seqStart, int & seqEnd){
int n = a.size();
Comparable maxSum = 0;
for(int i = 0; i < n; i++){ // for each possible start point
for(int j = i; j < n; j++){ // for each possible end point
Comparable thisSum = 0;
for(int k = i; k <= j; k++)
thisSum += a[k];//dominant term
if( thisSum > maxSum){
maxSum = thisSum;
seqStart = i;
seqEnd = j;
}
}
}
return maxSum;
} //A cubic maximum contiguous subsequence sum algorithm
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit1/assets/14.html 18 of 278 1/1
Analysis of Algorithm
8/13/2015 scorm content
O(N 2) algorithm
An improved algorithm makes use of the fact that.
If we have already calculated the sum for the subsequence i, …, j1.
Then we need only one more addition to get the sum for the subsequence i, …, j.
However, the cubic algorithm throws away this information.
If we use this observation, we obtain an improved algorithm with the running time O(N 2 ).
template <class Comparable>
Comparable maxSubsequenceSum(const vector<Comparable>& a,
int & seqStart, int &seqEnd){
int n = a.size();
Comparable maxSum = 0;
for( int i = 0; i < n; i++){
Comparable thisSum = 0;
for( int j = i; j < n; j++){
thisSum += a[j];
if( thisSum > maxSum){
maxSum = thisSum;
seqStart = i;
seqEnd = j;
}
}
}
return maxSum;
}
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit1/assets/15.html 19 of 278 1/1
Analysis of Algorithm
8/13/2015 scorm content
O(N) algorithm
An improved algorithm makes use of the fact that.
O(n) is the average case in the time complicity.
If we use this observation, we obtain an improved algorithm with the running time O(N).
Here this algorithm provides the sample for O(n) case. Where every loop iterates only n times.
template <class Comparable>
Comparable maxSubsequenceSum(const vector<Comparable>& a,
int & seqStart, int &seqEnd){
int n = a.size();
Comparable thisSum = 0, maxSum = 0;
int i=0;
for( int j = 0; j < n; j++){
thisSum += a[j];
if( thisSum > maxSum){
maxSum = thisSum;
seqStart = i;
seqEnd = j;
}else if( thisSum < 0) {
i = j + 1;
thisSum = 0;
}
}
return maxSum;
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit1/assets/16.html 20 of 278 1/1
Analysis of Algorithm
8/13/2015 scorm content
General BigOh Rules
Def: (BigOh) T(n) is O(F(n)) if there are positive constants c and n0 such that T(n)<= cF(n)
when n >= n0
Def: (BigOmega) T(n) is Ω(F(n)) if there are positive constant c and n0 such that T(n) >= cF(n)
when n >= n0
Def: (BigTheta) T(n) is Θ(F(n)) if and only if T(n) = O(F(n)) and T(n) = Ω(F(n))
Def: (LittleOh) T(n) = o(F(n)) if and only if T(n) = O(F(n)) and T(n) != Θ(F(n))
Big O is transitive. That is, if f(n) = O(g(n)) and g(n) is O(h(n)), then f(n) = O(h(n)).
log a n = O(log b n) for any a, b > 1. This practically means that we don″t care, asymptotically,
what base we take our logarithms to.
n k = O((1+ξ ) n )) for any positive k and ξ. That is, any polynomial is bound from above by any
exponential. So any algorithm that runs in polynomial time is (eventually, for large enough value
of n) preferable to any algorithm that runs in exponential time.
(log n)ξ = O(n k) for any positive k and ξ. That means a logarithm to any power grows more
slowly than a polynomial So an algorithm that runs in logarithmic time is preferable to an
algorithm that runs in polynomial.
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit1/assets/17.html 21 of 278 1/1
Analysis of Algorithm
8/13/2015 scorm content
Mathematical Expression related to rate of growth
Mathematical Expression Relative Rates of Growth
T(n) = O(F(n)) Growth of T(n) <= growth of F(n)
T(n) = Ω(F(n)) Growth of T(n) >= growth of F(n)
T(n) = Θ(F(n)) Growth of T(n) = growth of F(n)
T(n) = o(F(n)) Growth of T(n) < growth of F(n)
The table shows the relationship between mathematical expression and rate of growth.
T is called as BigOh.
F is called as Function.
If T(n) =O(F(n)) then the growth is equal.
As same like this the table denotes for each cases.
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit1/assets/18.html 22 of 278 1/1
Analysis of Algorithm
8/13/2015 scorm content
Various growth rates
The results show the rate between the mathematical and functional relationship.
If T(n) is equal to O(1), then it should be constant.
Like while the slide shows the results for every cases in time complicity.
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit1/assets/19.html 23 of 278 1/1
Analysis of Algorithm
8/13/2015 scorm content
Worstcase vs. Averagecase
A worstcase bound is a guarantee over all inputs of size N.
In an averagecase bound, the running time is measured as an average over all of the possible
inputs of size N.
We will mainly focus on worstcase analysis, but sometimes it is useful to do average one.
It represents the average and worst case difference.
As is said before the O(n) is the average case for a specified algorithm.
More than O(n) are called as worst case.
In some times the average case will be a best case, depends upon the situations.
Therefore the worst case is consider as average case.
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit1/assets/20.html 24 of 278 1/1
Analysis of Algorithm
8/13/2015 scorm content
Static Searching problem
Given an integer X and an array A, return the position of X in A or an indication that it is not
present.
If X occurs more than once, return any occurrence.
The array A is never altered.
Sequential search: =>O(n).
Binary search (sorted data): => O(logn).
Interpolation search (data must be uniform distributed): making guesses and search =>O(n) in
worse case, but better than binary search on average BigOh performance, (impractical in
general).
Sequential Search
A sequential search steps through the data sequentially until a match is found.
A sequential search is useful when the array is not sorted.
A sequential search is linear O(n) (i.e. proportional to the size of input)
Unsuccessful search n times
Successful search (worst) n times
Successful search (average) n/2 times
Binary Search
Binary search is useful only if the array is already sorted.
Binary search is starts by middle, rather than the end.
If the array is sorted the time complicity should be low, otherwise it should be high.
Binary Search 3ways comparisons
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit1/assets/21.html 25 of 278 1/3
Analysis of Algorithm
8/13/2015 scorm content
template < class Comparable>
int binarySearch(const vector<Comparable>& a, const Comparable & x){
int low = 0;
int high = a.size() – 1;
int mid;
while(low < high) {
mid = (low + high) / 2;
if(a[mid] < x)
low = mid + 1;
else if( a[mid] > x)
high = mid 1;
else
return mid;
}
return NOT_FOUND; // NOT_FOUND = 1
}
The example shows 3way comparison of binary searching.
In this it would be compared by using If conditions.
Three if conditions will get three different ways of complicity.
Here the if(a[mid] < x) will get lower, the next else if will get average and the last else will get
higher case.
Binary search is logarithmic O(logN) because the search range is halved in each iteration.
Binary Search 2ways comparisons
template < class Comparable>
int binarySearch(const vector<Comparable>& a, const Comparable & x){
int low, mid;
int high = a.size() – 1;
while(low < high) {
mid = (low + high) / 2;
if(a[mid] < x)
low = mid + 1;
else
high = mid;
}
return (low == high && a[low] == x) ? low: NOT_FOUND;
}
The code shows the 2way comparison.
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit1/assets/21.html 26 of 278 2/3
Analysis of Algorithm
8/13/2015 scorm content
2ways comparisons binary search is still O(logN)
This is effective than the 3way comparison.
The program is about comparing 2 numbers.
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit1/assets/21.html 27 of 278 3/3
Analysis of Algorithm
8/13/2015 scorm content
Limitations of BigOh Analysis
The constants coefficients might have a significant influence on the performance when the size
of the problem is not large.
Ex: f(n)=2nlogn vs. g(n)=1000n. Which is faster? => it depends on n, for little n, f(n) is better
although it growth rate is larger.
Worst case is sometimes uncommon and can be safely ignored. At other times, it is very
common and cannot be ignored.
Averagecase analysis is almost always much more difficult than worstcase analysis.
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit1/assets/22.html 28 of 278 1/1
Analysis of Algorithm
8/13/2015 scorm content
Dynamic Programming
In dynamic programming there are followed by two approaches.
Top down approach Many smaller instances are computed more than once.
Bottom up approach Solutions for smaller instances are stored in a table for later use.
An Algorithm Design Technique.
A framework to solve Optimization problems.
Elements of Dynamic Programming.
Dynamic programming version of a recursive algorithm.
Developing a Dynamic Programming Algorithm.
Example: Multiplying a Sequence of Matrices.
It sometimes happens that the natural way of dividing an instance suggested by the structure of
the problem leads us to consider several overlapping sub instances.
If we solve each of these independently, they will in turn create a large number of identical sub
instances.
If we pay no attention to this duplication, it is likely that we will end up with an inefficient
algorithm.
If, on the other hand, we take advantage of the duplication and solve each sub instance only
once, saving the solution for later use, then a more efficient algorithm will result.
The underlying idea of dynamic programming is thus quite simple: avoid calculating the same
thing twice, usually by keeping a table of known results, which we fill up as sub instances are
solved.
Dynamic programming is a bottomup technique.
Examples:
Fibonacci numbers
Computing a Binomial coefficient
Dynamic Programming is a general algorithm design technique.
Invented by American mathematician Richard Bellman in the 1950s to solve optimization
problems.
“Programming” here means “planning”.
Main idea:
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit1/assets/23.html 29 of 278 1/3
Analysis of Algorithm
8/13/2015 scorm content
Solve several smaller (overlapping) sub problems.
Record solutions in a table so that each sub problem is only solved once.
Final state of the table will be (or contain) solution.
Define a container to store intermediate results.
Access container versus recomputing results.
Fibonacci numbers example (top down): Use vector to store results as calculated so they are not
recalculated
Fibonacci numbers: 0, 1, 1, 2, 3, 5, 8, 13, 21, 24.
f(0) = 0
f(1) = 1
f(n) = f(n1) + f(n2) for n ≥ 2
int fib(int n) {
if (n <= 1) return n; // stopping conditions
else return fib(n1) + fib(n2); // recursive step
}
int fibDyn(int n, vector<int>& fibList) {
int fibValue;
if (fibList[n] >= 0) // check for a previously computed result and return
return fibList[n];
// otherwise execute the recursive algorithm to obtain the result
if (n <= 1) // stopping conditions
fibValue = n;
else // recursive step
fibValue = fibDyn(n1, fibList) + fibDyn(n2, fibList);
// store the result and return its value
fibList[n] = fibValue;
return fibValue;
}
The program shows detail view of normal algorithm and dynamic algorithm.
The output computes the different.
Recursive calls for fibonacci
The output diagram shows the Fibonacci serious in recursive call.
Fibonacci Using Dynamic Programming
The output diagram shows the Fibonacci serious in dynamic programming.
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit1/assets/23.html 30 of 278 2/3
Analysis of Algorithm
8/13/2015 scorm content
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit1/assets/23.html 31 of 278 3/3
Analysis of Algorithm
8/13/2015 scorm content
Statistics (function calls)
The statistics between normal programming and dynamic programming show by using the
function call.
The result is dynamic programming is effective than the normal programming.
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit1/assets/24.html 32 of 278 1/1
Analysis of Algorithm
8/13/2015 scorm content
Top down vs. Bottom up
The Top down dynamic programming moves through recursive process and stores results as
algorithm computes.
Bottom up dynamic programming evaluates by computing all function values in order, starting at
lowest and using previously computed values.
This is the different between the top down.
And bottom up approach in dynamic programming.
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit1/assets/25.html 33 of 278 1/1
Analysis of Algorithm
8/13/2015 scorm content
Examples of Dynamic Programming Algorithms
Computing binomial coefficients.
Optimal chain matrix multiplication.
Floyd’s algorithms for allpairs shortest paths.
Constructing an optimal binary search tree.
Some instances of difficult discrete optimization problems:
Travelling salesman
Knapsack
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit1/assets/26.html 34 of 278 1/1
Analysis of Algorithm
8/13/2015 scorm content
A framework to solve Optimization problems
For each current choice:
Determine what sub problem(s) would remain if this choice were made.
Recursively find the optimal costs of those sub problems.
Combine those costs with the cost of the current choice itself to obtain an overall cost for this
choice.
Select a current choice that produced the minimum overall cost.
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit1/assets/27.html 35 of 278 1/1
Analysis of Algorithm
8/13/2015 scorm content
Elements of Dynamic Programming
Constructing solution to a problem by building it up dynamically from solutions to smaller (or
simpler) subproblems.
Subinstances are combined to obtain subinstances of increasing size, until finally arriving at
the solution of the original instance.
Make a choice at each step, but the choice may depend on the solutions to subproblems.
Principle of optimality
The optimal solution to any nontrivial instance of a problem is a combination of optimal
solutions to some of its subinstances.
Memorization (for overlapping subproblems)
Avoid calculating the same thing twice,
Usually by keeping a table of know results that fills up as subinstances are solved.
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit1/assets/28.html 36 of 278 1/1
Analysis of Algorithm
8/13/2015 scorm content
Development of a dynamic programming algorithm
Characterize the structure of an optimal solution
Breaking a problem into subproblem.
Whether principle of optimality apply.
Recursively define the value of an optimal solution.
Define the value of an optimal solution based on value of solutions to subproblems.
Compute the value of an optimal solution in a bottomup fashion.
Compute in a bottomup fashion and save the values along the way.
Later steps use the save values of pervious steps.
Construct an optimal solution from computed information.
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit1/assets/29.html 37 of 278 1/1
Analysis of Algorithm
8/13/2015 scorm content
Binomial Formulas
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit1/assets/30.html 38 of 278 1/1
Analysis of Algorithm
8/13/2015 scorm content
Frequency Count
Examine a piece of code and predict the number of instructions to be executed.
For each instruction predict how many times each will be encountered as the code runs.
Counting each code
Loop counting
The F.C(Frequency Count), n is the term used for counting.
Order of magnitude
In the previous example:
best_case = avg_case = worst_case
Example is based on fixed iteration n
By itself, Freq. Count is relatively meaningless
Order of magnitude > estimate of performance vs. amount of data
To convert F.C. to order of magnitude:
discard constant terms
disregard coefficients
pick the most significant term
Worst case path through algorithm >
order of magnitude will be Big O (i.e. O(n))
Another example
Big O = O(n 2 )
Discarding constant terms produces : 3n 2 +2n
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit1/assets/31.html 39 of 278 1/2
Analysis of Algorithm
8/13/2015 scorm content
Clearing coefficients : n 2 +n
Picking the most significant term: n 2
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit1/assets/31.html 40 of 278 2/2
Analysis of Algorithm
8/13/2015 scorm content
Complexity measures in terms of time and space
In examining algorithm efficiency we must understand the idea of complexity.
Space complexity The space is about memory.
Time Complexity The time is about number of instructions.
Time complexity
The time complexity of an algorithm quantifies the amount of time taken by an algorithm to run
as a function of the length of the string representing the input.
The time complexity of an algorithm is commonly expressed using big O notation, which
excludes coefficients and lower order terms.
When expressed this way, the time complexity is said to be described asymptotically.
Time complexity is commonly estimated by counting the number of elementary operations
performed by the algorithm, where an elementary operation takes a fixed amount of time to
perform.
Thus the amount of time taken and the number of elementary operations performed by the
algorithm differ by at most a constant factor.
Since an algorithm″s performance time may vary with different inputs of the same size, one
commonly uses the worstcase time complexity of an algorithm, denoted as T(n), which is
defined as the maximum amount of time taken on any input of size n.
Time complexities are classified by the nature of the function T(n). For instance, an algorithm
with T(n) = O(n) is called a linear time algorithm, and an algorithm with T(n) = O(2 n ) is said to be
an exponential time algorithm.
Constant Time
An algorithm is said to be constant time (also written as O(1) time) if the value of T(n) is
bounded by a value that does not depend on the size of the input.
For example, accessing any single element in an array takes constant time as only one
operation has to be performed to locate it.
However, finding the minimal value in an unordered array is not a constant time operation as a
scan over each element in the array is needed in order to determine the minimal value.
Hence it is a linear time operation, taking O(n) time.
If the number of elements is known in advance and does not change, however, such an
algorithm can still be said to run in constant time.
Despite the name "constant time", the running time does not have to be independent of the
problem size, but an upper bound for the running time has to be bounded independently of the
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit1/assets/32.html 41 of 278 1/6
Analysis of Algorithm
8/13/2015 scorm content
problem size.
For example, the task "exchange the values of a and b if necessary so that a≤b" is called
constant time even though the time may depend on whether or not it is already true that a≤b.
However, there is some constant t such that the time required is always at most t.
Constant time effectively means you can give a constant upper bound to how long the program
will take to run which isn′t affected by any of the input parameters.
Compare that with, say, linear time (for some input n which will often actually be the size of the
input data rather than a direct value) which means that the upper bound of the time taken can
be expressed as mn + k for some values of m and k.
Here are some examples of code fragments that run in constant time:
Logarithmic Time
An algorithm is said to take logarithmic time if T(n) = O(log n).
Due to the use of the binary numeral system by computers, the logarithm is frequently base 2
(that is, log 2 n, sometimes written lg n).
However, by the change of base for logarithms, log a n and log b n differ only by a constant
multiplier, which in bigO notation is discarded; thus O(log n) is the standard notation for
logarithmic time algorithms regardless of the base of the logarithm.
Algorithms taking logarithmic time are commonly found in operations on binary trees or when
using binary search.
An O(log n) algorithm is considered highly efficient, as the operations per instance required to
complete decrease with each instance.
A very simple example of this type of f(n) is an algorithm that cuts a string in half.
It will take O(log n) time since we chop the string in half before each print.
This means, in order to increase the number of prints, we have to double the length of the string.
The most common attributes of logarithmic runningtime function are that:
The choice of the next element on which to perform some action is one of several
possibilities, and
Only one will need to be chosen or
The elements on which the action is performed are digits of n
Polylogarithmic Time
An algorithm is said to run in polylogarithmic time if T(n) = O((log n) k), for some constant k. For
example, matrix chain ordering can be solved in polylogarithmic time on a Parallel Random
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit1/assets/32.html 42 of 278 2/6
Analysis of Algorithm
8/13/2015 scorm content
Access Machine.
Polylogarithmic time is set to be T(n)=O(log n) k.
Matrix chain is the pure example for Polylogarithmic time.
Sublinear time
An algorithm is said to run in sublinear if T(n) = o(n).
In particular this includes algorithms with the time complexities defined above, as well as others
such as the O(n ½) Grover′s search algorithm.
Typical algorithms that are exact and yet run in sublinear time use parallel processing or
alternatively have guaranteed assumptions on the input structure.
However, languages such as the set of all strings that have a 1bit in the position indicated by
the first log(n) bits of the string may depend on every bit of the input and yet be computable in
sublinear time.
The specific term sub linear time algorithm is usually reserved to algorithms that are unlike the
above in that they are run over classical serial machine models and are not allowed prior
assumptions on the input.
They are however allowed to be randomized, and indeed must be randomized for all but the
most trivial of tasks.
As such an algorithm must provide an answer without reading the entire input, its particulars
heavily depend on the access allowed to the input.
Usually for an input that is represented as a binary string b 1 ,...,b k it is assumed that the
algorithm can in time O(1) request and obtain the value of bi for any i.
Sublinear time algorithms are typically randomized, and provide only approximate solutions.
In fact, the property of a binary string having only zeros can be easily proved not to be decidable
by a sublinear time algorithm.
Sublinear time algorithms arise naturally in the investigation of property testing.
Linear time
An algorithm is said to take linear time, or O(n) time, if its time complexity is O(n).
Informally, this means that for large enough input sizes the running time increases linearly with
the size of the input.
For example, a procedure that adds up all elements of a list requires time proportional to the
length of the list.
This description is slightly inaccurate, since the running time can significantly deviate from a
precise proportionality, especially for small values of n.
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit1/assets/32.html 43 of 278 3/6
Analysis of Algorithm
8/13/2015 scorm content
Linear time is often viewed as a desirable attribute for an algorithm. Much research has been
invested into creating algorithms exhibiting linear time or better.
This research includes both software and hardware methods. In the case of hardware, some
algorithms which, mathematically speaking, can never achieve linear time with standard
computation models are able to run in linear time.
There are several hardware technologies which exploit parallelism to provide this.
An example is contentaddressable memory. This concept of linear time is used in string
matching algorithms such as the BoyerMoore Algorithm and Ukkonen″s Algorithm.
Linearithmic time
A linearithmic function is a function of the form n • log n.An algorithm is said to run in linearithmic
time if T(n) = O(n log n).
Compared to other functions, a linearithmic function is ω(n), o(n 1+ε) for every ε > 0, and Θ(n • log
n).
Thus, a linearithmic term grows faster than a linear term but slower than any polynomial in n with
exponent strictly greater than 1.
In many cases, the n • log n running time is simply the result of performing a Θ(log n) operation
n times.
For example, binary tree sort creates a binary tree by inserting each element of the nsized
array one by one. Since the insert operation on a selfbalancing binary search tree takes O(log
n) time, the entire algorithm takes linearithmic time.
Comparison sorts require at least linearithmic number of comparisons in the worst case because
log(n!) = Θ(n log n), by Stirling″s approximation. They also frequently arise from the recurrence
relation T(n) = 2 T(n/2) + O(n).
Some famous algorithms that run in linearithmic time include:
Quicksort in the average case
Heapsort, merge sort, introsort, binary tree sort, smoothsort, patience sorting, etc. in the
worst case
Fast Fourier transforms
Monge array calculation
Quasilinear time
A generalization of linearithmic time is quasilinear time.
An algorithm is said to run in quasilinear time if T(n) = O(n log k n) for any constant k; linearithmic
time is the case k = 1.
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit1/assets/32.html 44 of 278 4/6
Analysis of Algorithm
8/13/2015 scorm content
Quasilinear time algorithms are also o(n 1+ε) for every ε > 0, and thus run faster than any
polynomial in n with exponent strictly greater than 1.
Algorithms which run in quasilinear time, in addition to the linearithmic algorithms listed above,
include: Inplace merge sort, O(n log 2 n)
Subquadratic time
An algorithm is said to be subquadratic time if T(n) = o(n 2 ).
Example:
Insertion sort
Shell sort
For example, most naïve comparisonbased sorting algorithms are quadratic, but more
advanced algorithms can be found that are subquadratic.
No generalpurpose sorts run in linear time, but the change from quadratic to subquadratic is of
great practical importance.
Polynomial Time
An algorithm is said to be of polynomial time if its running time is upper bounded by a polynomial
expression in the size of the input for the algorithm, i.e., T(n) = O(n k) for some constant k.
Problems for which a deterministic polynomial time algorithm exists belong to the complexity
class P, which is central in the field of computational complexity theory.
Cobham′s thesis states that polynomial time is a synonym for "tractable", "feasible", "efficient", or
"fast".
Some examples of polynomial time algorithms:
The quicksort sorting algorithm on n integers performs at most An 2 operations for some
constant A.
Thus it runs in time O(n 2 ) and is a polynomial time algorithm.
All the basic arithmetic operations (addition, subtraction, multiplication, division, and
comparison) can be done in polynomial time.
Maximum matchings in graphs can be found in polynomial time.
Strongly and Weakly Polynomial Time
In some contexts, especially in optimization, one differentiates between strongly polynomial time
and weakly polynomial time algorithms.
These two concepts are only relevant if the inputs to the algorithms consist of integers.
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit1/assets/32.html 45 of 278 5/6
Analysis of Algorithm
8/13/2015 scorm content
Strongly polynomial time is defined in the arithmetic model of computation.
In this model of computation the basic arithmetic operations (addition, subtraction, multiplication,
division, and comparison) take a unit time step to perform, regardless of the sizes of the
operands.
The algorithm runs in strongly polynomial time if
The number of operations in the arithmetic model of computation is bounded by a polynomial
in the number of integers in the input instance;
The space used by the algorithm is bounded by a polynomial in the size of the input.
Any algorithm with these two properties can be converted to a polynomial time algorithm by
replacing the arithmetic operations by suitable algorithms for performing the arithmetic
operations on a Turing machine.
If the second of the above requirement is not met, then this is not true anymore.
n
Given the integer 2 n (which takes up space proportional to n), it is possible to compute 2 2 with
n multiplications using repeated squaring.
n
However, the space used to represent 2 2 is proportional to, 2 n and thus exponential rather than
polynomial in the space used to represent the input.
Hence, it is not possible to carry out this computation in polynomial time on a Turing machine,
but it is possible to compute it by polynomial many arithmetic operations.
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit1/assets/32.html 46 of 278 6/6
Analysis of Algorithm
8/13/2015 scorm content
Complexity Classes
The concept of polynomial time leads to several complexity classes in computational complexity
theory.
Some important classes defined using polynomial time are the following.
P: The complexity class of decision problems that can be solved on a deterministic Turing
machine in polynomial time.
NP: The complexity class of decision problems that can be solved on a nondeterministic
Turing machine in polynomial time.
ZPP: The complexity class of decision problems that can be solved with zero error on a
probabilistic Turing machine in polynomial time.
RP: The complexity class of decision problems that can be solved with 1sided error on a
probabilistic Turing machine in polynomial time.
BPP: The complexity class of decision problems that can be solved with 2sided error on a
probabilistic Turing machine in polynomial time.
BQP: The complexity class of decision problems that can be solved with 2sided error on a
quantum Turing machine in polynomial time.
P is the smallest timecomplexity class on a deterministic machine which is robust in terms of
machine model changes.
Any given abstract machine will have a complexity class corresponding to the problems which
can be solved in polynomial time on that machine.
Superpolynomial Time
An algorithm is said to take superpolynomial time if T(n) is not bounded above by any
polynomial.
It is ω(n c) time for all constants c, where n is the input parameter, typically the number of bits in
the input.
For example, an algorithm that runs for 2 n steps on an input of size n requires superpolynomial
time.
An algorithm that uses exponential resources is clearly superpolynomial, but some algorithms
are only very weakly superpolynomial.
For example, the Adleman–Pomerance–Rumely primality test runs for n O(log log n) time on nbit
inputs; this grows faster than any polynomial for large enough n, but the input size must become
impractically large before it cannot be dominated by a polynomial with small degree.
An algorithm that requires superpolynomial time lies outside the complexity class P.
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit1/assets/33.html 47 of 278 1/4
Analysis of Algorithm
8/13/2015 scorm content
Cobham′s thesis posits that these algorithms are impractical, and in many cases they are.
Since the P versus NP problem is unresolved, no algorithm for an NPcomplete problem is
currently known to run in polynomial time.
Quasipolynomial Time
Quasipolynomial time algorithms are algorithms which run slower than polynomial time, yet not
so slow as to be exponential time.
c) for some fixed c.
The worst case running time of a quasipolynomial time algorithm is 2 O((log n)
The bestknown classical algorithm for integer factorization, the general number field sieve,
which runs in time about is not quasipolynomial since the running time cannot be
c) for some fixed c.
expressed as 2 O((log n)
If the constant "c" in the definition of quasipolynomial time algorithms is equal to 1, we get a
polynomial time algorithm, and if it is less than 1, we get a sublinear time algorithm.
Quasipolynomial time algorithms typically arise in reductions from an NPhard problem to
another problem.
For example, one can take an instance of an NP hard problem, say 3SAT, and convert it to an
c) The complexity class QP
instance of another problem B, but the size of the instance becomes 2 O((log n)
consists of all problems which have quasipolynomial time algorithms.
It can be defined in terms of DTIME as follows.
Relation to NP
Complete
Problems
In complexity theory, the unsolved P versus NP problem asks if all problems in NP have
polynomialtime algorithms.
All the bestknown algorithms for NPcomplete problems like 3SAT etc. take exponential time.
Indeed, it is conjectured for many natural NPcomplete problems that they do not have sub
exponential time algorithms.
Here "subexponential time" is taken to mean the second definition presented above.
This conjecture (for the kSAT problem) is known as the exponential time hypothesis.
Since it is conjectured that NPcomplete problems do not have quasipolynomial time algorithms,
some in approximability results in the field of approximation algorithms make the assumption
that NPcomplete problems do not have quasipolynomial time algorithms.
For example, see the known in approximability results for the set cover problem.
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit1/assets/33.html 48 of 278 2/4
Analysis of Algorithm
8/13/2015 scorm content
Subexponential Time
The term subexponential time is used to express that the running time of some algorithm may
grow faster than any polynomial but is still significantly smaller than an exponential.
In this sense, problems that have subexponential time algorithms are somewhat more tractable
than those that only have exponential algorithms.
The precise definition of "subexponential" is not generally agreed upon, and we list the two
most widely used ones below.
Subexponential Time First Definition
A problem is said to be subexponential time solvable if it can be solved in running times whose
logarithms grow smaller than any given polynomial.
More precisely, a problem is in subexponential time if for every ε > 0 there exists an algorithm
ε
which solves the problem in time O(2 n ).
The set of all such problems is the complexity class SUBEXP which can be defined in terms of
DTIME as follows.
Note that this notion of subexponential is non
uniform in terms of ε in the sense that ε is not
part of the input and each ε may have its own
algorithm for the problem.
Subexponential Time Second Definition
Subexponential time as running times in 2 o(n).
This definition allows larger running times than the first definition of subexponential time.
An example of such a subexponential time algorithm is the bestknown classical algorithm for
integer factorization, the general number field sieve, which runs in time about ,
where the length of the input is n.
Another example is the bestknown algorithm for the graph isomorphism
problem, which runs in time 2 O(√(n log n)).
(L,K) of decision problems and parameters k. SUBEPT is the class of all parameterized
problems that run in time subexponential in k and polynomial in the input size n:
SUBEPT = DTIME(2 o(K).poly(n))
More precisely, SUBEPT is the class of all parameterized problems (L,K) for which there is a
computable function f:N→N with f∈o(K) and an algorithm that decides L in time 2 f(K).poly(n).
Note that it makes a difference whether the algorithm is allowed to be subexponential in the size
of the instance, the number of vertices, or the number of edges.
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit1/assets/33.html 49 of 278 3/4
Analysis of Algorithm
8/13/2015 scorm content
In parameterized complexity, this difference is made explicit by considering pairs.
Exponential Time Hypothesis
The exponential time hypothesis (ETH) is that 3SAT, the satisfiability problem of Boolean
formulas in conjunctive normal form with at most three literals per clause and with n variables,
cannot be solved in time 2 o(n).
More precisely, the hypothesis is that there is some absolute constant c>0 such that 3SAT
cannot be decided in time 2 cn by any deterministic Turing machine.
With m denoting the number of clauses, ETH is equivalent to the hypothesis that kSAT cannot
be solved in time 2 o(m) for any integer k ≥ 3.
The exponential time hypothesis implies P ≠ NP.
Exponential Time
An algorithm is said to be exponential time, if T(n) is upper bounded by 2 poly(n), where poly(n) is
some polynomial in n.
More formally, an algorithm is exponential time if T(n) is bounded by O(2 nk) for some constant k.
Problems which admit exponential time algorithms on a deterministic Turing machine form the
complexity class known as EXP.
Double Exponential Time
An algorithm is said to be double exponential time if T(n) is
upper bounded by 2 2poly(n), where poly(n) is some polynomial
in n.
Such algorithms belong to the complexity class 2EXPTIME.
Double exponential time algorithms include:
Decision procedures for Presburger arithmetic.
Computing a Gröbner basis (in the worst case).
Quantifier elimination on real closed fields takes at least double exponential time (but is not
even known to be computable in ELEMENTARY).
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit1/assets/33.html 50 of 278 4/4
Analysis of Algorithm
8/13/2015 scorm content
Space Complexity
When memory was expensive we focused on making programs as space efficient as possible
and developed schemes to make memory appear larger than it really was virtual memory and
memory paging schemes.
Space complexity is still important in the field of embedded computing.
Space complexity = The amount of memory required by an algorithm to run to completion.
[Core dumps = the most often encountered cause is “memory leaks” – the amount of
memory required larger than the memory available on a given system].
Some algorithms may be more efficient if data completely loaded into memory.
To look also at system limitations.
E.g. Classify 2GB of text in various categories [politics, tourism, sport, natural disasters, etc.]
– can I afford to load the entire collection?
Fixed part: The size required to store certain data/variables, that is independent of the size of
the problem:
E.g. name of the data collection.
Same size for classifying 2GB or 1MB of texts.
Variable part: Space needed by variables, whose size is dependent on the size of the problem:
E.g. actual text.
Load 2GB of text VS. load 1MB of text.
S(P) = c + S(instance characteristics)
c = constant.
Example:
Space? one word for n, one for a [passed by
reference!], one for i à constant space!
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit1/assets/34.html 51 of 278 1/1
Analysis of Algorithm
8/13/2015 scorm content
Structured Programming
A Structured programming is a programming paradigm aimed on improving the clarity, quality,
and development time of a computer program by making extensive use of subroutines, block
structures and for and while loops—in contrast to using simple tests and jumps such as the goto
statement which could lead to "spaghetti code" which is both difficult to follow and to maintain.
Lowlevel Structured Programming
At a low level, structured programs are often composed of simple, hierarchical program flow
structures.
These are sequence, selection, and repetition:
A language is described as blockstructured when it has a syntax for enclosing structures
between bracketed keywords, such as an ifstatement bracketed by if..fi as in ALGOL 68, or a
code section bracketed by BEGIN..END, as in PL/I or the curly braces {...} of C and many later
languages.
"Sequence" refers to an ordered execution of statements.
In "selection" one of a number of statements is executed depending on the state of the program.
This is usually expressed with keywords such as if..then..else..endif, switch, or case.
In some languages keywords cannot be written verbatim, but must be stopped.
In "repetition" a statement is executed until the program reaches a certain state, or operation
have been applied to every element of a collection.
This is usually expressed with keywords such as while, repeat, for or do..until.
Often it is recommended that each loop should only have one entry point.
Common Deviations
While go to has now largely been replaced by the structured constructs of selection and
repetition , few languages are purely structured.
The most common deviation, found in many languages, is the use of a return statement for early
exit from a subroutine.
This results in multiple exit points, instead of the single exit point required by structured
programming.
There are other constructions to handle cases that are awkward in purely structured
programming.
Structured Programming Languages
It is possible to do structured programming in any programming language, though it is preferable
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit1/assets/35.html 52 of 278 1/3
Analysis of Algorithm
8/13/2015 scorm content
to use something like a procedural programming language.
But most new procedural programming languages since that time have included features to
encourage structured programming, and sometimes deliberately left out features – notably
GOTO – in an effort to make unstructured programming more difficult.
Outcome
By the end of the 20th century nearly all computer scientists were convinced that it is useful to
learn and apply the concepts of structured programming.
Early Exit
The most common deviation from structured programming is early exit from a function or loop.
At the level of functions, this is a return statement.
At the level of loops, this is a break statement or continue statement.
In structured programming, these can be replicated by adding additional branches or test, but
for returns from nested code this can add significant complexity.
C is an early and prominent example of these constructs.
Some newer languages also have labeled breaks, which allowing breaking out of more than just
the innermost loop.
Exceptions also allow early exit, but have further consequences, and thus are treated below.
Multiple exits can arise for a variety of reasons, most often either that the subroutine has no
more work to do , or has encountered "exceptional" circumstances that prevent it from
continuing, hence needing exception handling.
The most common problem in early exit is that cleanup or final statements are not executed –
for example, allocated memory is not unallocated, or open files are not closed, causing memory
leaks or resource leaks.
These must be done at each return site, which is brittle and can easily result in bugs.
For instance, in later development, a return statement could be overlooked by a developer, and
an action which should be performed at the end of a subroutine might not be performed in all
cases.
Languages without a return statement, such as standard Pascal don′t have this problem.
Exception Handling
The "stop and inform" may be achieved by throwing an exception, returning from the procedure,
a labeled loop break, or even a goto.
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit1/assets/35.html 53 of 278 2/3
Analysis of Algorithm
8/13/2015 scorm content
The procedure above breaks the rules of Dijkstra′s structured programming because the while
loop can terminate in a way that is not specified in the while condition (the "reading not
finished"), and because it has two exit points(the end of the procedure and the "stop" on error).
Recoding this to use a structured while loop and a single point of exit is trivial:
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit1/assets/35.html 54 of 278 3/3
UNIT - 2
Basics of C++, Elementary Data Structures :
Arrays, linked lists
Page 55 of 278
Basics of C++, Elementary Data Structures : Arrays, linked lists
8/13/2015 scorm content
Basics of C++
A programming language is said to use static typing when type checking is performed during
compiletime as opposed to runtime.
The most important thing to do when learning C++ is to focus on concepts and not get lost in
language technical details.
The purpose of learning a programming language is to become a better programmer; that is, to
become more effective at designing and implementing new systems and at maintaining old
ones.
C++ supports a variety of programming styles. You can write in the style of Fortran, C, Smalltalk,
etc., in any language. Each style can achieve its aims effectively while maintaining runtime and
space efficiency.
C++ is regarded as a middlelevel language, as it comprises a combination of both highlevel
and lowlevel language features.
C++ was developed by Bjarne Stroustrup starting in 1979 at Bell Labs in Murray Hill, New
Jersey, as an enhancement to the C language and originally named C with Classes but later it
was renamed C++ in 1983.
C++ is a superset of C, and that virtually any legal C program is a legal C++ program.
The ANSI standard is an attempt to ensure that C++ is portable that code you write for
Microsoft′s compiler will compile without errors, using a compiler on a Mac, UNIX, a Windows
box, or an Alpha.
The ANSI standard has been stable for a while, and all the major C++ compiler manufacturers
support the ANSI standard.
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit2/assets/2.html 56 of 278 1/1
Basics of C++, Elementary Data Structures : Arrays, linked lists
8/13/2015 scorm content
Basic Syntax
When we consider a C++ program, it can be defined as a collection of objects that communicate
via invoking each other′s methods.
Let us now briefly look into what do class, object, methods and instant variables mean.
Object
Objects have states and behaviors.
Example: A dog has states color, name, breed as well as behaviors wagging, barking,
and eating. An object is an instance of a class.
Class
A class can be defined as a template/blueprint that describes the behaviors/states that object
of its type support.
Methods
A method is basically a behavior.
A class can contain many methods.
It is in methods where the logics are written, data is manipulated and all the actions are
executed.
Instant Variables
Each object has its unique set of instant variables.
An object′s state is created by the values assigned to these instant variables.
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit2/assets/3.html 57 of 278 1/1
Basics of C++, Elementary Data Structures : Arrays, linked lists
8/13/2015 scorm content
C++ Program Structure
Let us look at a simple code that would print the words Hello World.
The C++ language defines several headers, which contain information that is either
necessary or useful to your program.
For this program, the header <iostream> is needed.
The line using namespace std; tells the compiler to use the std namespace.
Namespaces are a relatively recent addition to C++.
The next line // main() is where program execution begins. is a singleline comment available
in C++.
Singleline comments begin with // and stop at the end of the line.
The line int main() is the main function where program execution begins.
The next line cout << " Hello World."; causes the message "This is my first C++ program" to
be displayed on the screen.
The next line return 0; terminates main( )function and causes it to return the value 0 to the
calling process.
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit2/assets/4.html 58 of 278 1/1
Basics of C++, Elementary Data Structures : Arrays, linked lists
8/13/2015 scorm content
Compile & Execute C++ Program
Open a text editor and add the code as above.
Save the file as: hello.cpp.
Open a command prompt and go to the directory where you saved the file.
Type ‘g++ hello.cpp’ and press enter to compile your code.
If there are no errors in your code the command prompt will take you to the next line and would
generate a.out executable file.
Now, type ‘ a.out’ to run your program.
You will be able to see ‘ Hello World ’ printed on the window.
Let′s look at how to save the file, compile and run the program.
Make sure that g++ is in your path and that you are running it in the directory containing file
hello.cpp.
You can compile C/C++ programs using make file.
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit2/assets/5.html 59 of 278 1/1
Basics of C++, Elementary Data Structures : Arrays, linked lists
8/13/2015 scorm content
C++ Identifiers
A C++ identifier is a name used to identify a variable, function, class, module, or any other user
defined item.
An identifier starts with a letter A to Z or a to z or an underscore (_) followed by zero or more
letters, underscores, and digits (0 to 9).
C++ does not allow punctuation characters such as @, $, and % within identifiers.
C++ is a casesensitive programming language.
Thus, Manpower and manpower are two different identifiers in C++.
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit2/assets/6.html 60 of 278 1/1
Basics of C++, Elementary Data Structures : Arrays, linked lists
8/13/2015 scorm content
Trigraphs
Trigraphs are expanded anywhere they appear, including within string literals and character
literals, in comments, and in preprocessor directives.
A few characters have an alternative representation, called a trigraph sequence.
A trigraph is a threecharacter sequence that represents a single character and the sequence
always starts with two question marks.
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit2/assets/7.html 61 of 278 1/1
Basics of C++, Elementary Data Structures : Arrays, linked lists
8/13/2015 scorm content
Whitespace in C++
Whitespace is the term used in C++ to describe blanks, tabs, newline characters and comments.
Whitespace separates one part of a statement from another and enables the compiler to identify
where one element in a statement, such as int, ends and the next element begins.
Therefore, in the statement, int age;
There must be at least one whitespace character (usually a space) between int and age for
the compiler to be able to distinguish them.
On the other hand, in the statement, fruit = apples + oranges; // Get the total fruit
No whitespace characters are necessary between fruit and =, or between = and apples,
although you are free to include some if you wish for readability purpose.
A line containing only whitespace, possibly with a comment, is known as a blank line, and C++
compiler totally ignores it.
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit2/assets/8.html 62 of 278 1/1
Basics of C++, Elementary Data Structures : Arrays, linked lists
8/13/2015 scorm content
Comments in C++
Program comments are explanatory statements that you can include in the C++ code that you
write and helps anyone reading it′s source code.
All programming languages allow for some form of comments.
Within a /* and */ comment, // characters have no special meaning. Within a // comment, /* and */
have no special meaning.
Thus, you can "nest" one kind of comment within the other kind.
C++ supports singleline and multiline comments.
All characters available inside any comment are ignored by C++ compiler.
C++ comments start with /* and end with */.
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit2/assets/9.html 63 of 278 1/1
Basics of C++, Elementary Data Structures : Arrays, linked lists
8/13/2015 scorm content
Data Types
C++ offer the programmer a rich assortment of builtin as well as user defined data types.
The basic types can be modified using one or more of these type modifiers:
signed.
unsigned.
short.
long.
While doing programming in any programming language, you need to use various variables to
store various information.
Variables are nothing but reserved memory locations to store values. This means that when you
create a variable you reserve some space in memory.
You may like to store information of various data types like character, wide character, integer,
floating point, double floating point, Boolean etc.
Based on the data type of a variable, the operating system allocates memory and decides what
can be stored in the reserved memory.
typedef Declarations
You can create a new name for an existing type using typedef. Following is the simple syntax to
define a new type using typedef:
typedef type newname;
For example, the following tells the compiler that feet is another name for int:
typedef int feet;
Now, the following declaration is perfectly legal and creates an integer variable called distance:
feet distance;
Enumerated Types
An enumerated type declares an optional type name and a set of zero or more identifiers that
can be used as values of the type.
Each enumerator is a constant whose type is the enumeration.
To create an enumeration requires the use of the keyword enum. The general form of an
enumeration type is:
enum enumname { list of names } varlist;
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit2/assets/10.html 64 of 278 1/2
Basics of C++, Elementary Data Structures : Arrays, linked lists
8/13/2015 scorm content
Here, the enumname is the enumeration′s type name. The list of names is comma separated.
For example, the following code defines an enumeration of colors called colors and the variable
c of type color. Finally, c is assigned the value "blue".
enum color { red, green, blue } c;
c = blue;
By default, the value of the first name is 0, the second name has the value 1, the third has the
value 2, and so on. But you can give a name a specific value by adding an initializer.
For example, in the following enumeration, green will have the value 5.
enum color { red, green=5, blue };
Here, blue will have a value of 6 because each name will be one greater than the one that
precedes it.
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit2/assets/10.html 65 of 278 2/2
Basics of C++, Elementary Data Structures : Arrays, linked lists
8/13/2015 scorm content
Variables
A variable provides us with named storage that our programs can manipulate.
Each variable in C++ has a specific type, which determines the size and layout of the variable′s
memory; the range of values that can be stored within that memory; and the set of operations
that can be applied to the variable.
The name of a variable can be composed of letters, digits, and the underscore character. It must
begin with either a letter or an underscore.
Upper and lowercase letters are distinct because C++ is casesensitive.
C++ also allows to define various other types of variables like Enumeration, Pointer, Array,
Reference, Data structures, and Classes.
Variable Definition in C++
A variable definition means to tell the compiler where and how much to create the storage for
the variable.
A variable definition specifies a data type, and contains a list of one or more variables of that
type as follows:
type variable_list;
Here, type must be a valid C++ data type including char, w_char, int, float, double, bool or any
userdefined object, etc., and variable_list may consist of one or more identifier names
separated by commas.
Some valid declarations are shown here:
The line int i, j, k; both declares and defines the variables i, j and k; which instructs the compiler
to create variables named i, j and k of type int.
Variables can be initialized (assigned an initial value) in their declaration. The initializer consists
of an equal sign followed by a constant expression as follows:
type variable_name = value;
Some examples are:
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit2/assets/11.html 66 of 278 1/3
Basics of C++, Elementary Data Structures : Arrays, linked lists
8/13/2015 scorm content
For definition without an initializer: variables with static storage duration are implicitly initialized
with NULL (all bytes have the value 0); the initial value of all other variables is undefined.
Variable Declarations in C++
A variable declaration provides assurance to the compiler that there is one variable existing with
the given type and name so that compiler proceed for further compilation without needing
complete detail about the variable.
A variable declaration has its meaning at the time of compilation only, compiler needs actual
variable declaration at the time of linking of the program.
Lvalues and Rvalues
Variables are lvalues and so may appear on the lefthand side of an assignment. Numeric
literals are rvalues and so may not be assigned and can not appear on the lefthand side.
Following is a valid statement:
Lvalue: An expression that is an lvalue may appear as either the lefthand or righthand side
of an assignment.
Rvalue: An expression that is an rvalue may appear on the right but not lefthand side of an
assignment.
Variable Scope
A scope is a region of the program and broadly speaking there are three places, where variables
can be declared:
Inside a function or a block which is called local variables.
In the definition of function parameters which is called formal parameters.
Outside of all functions which is called global variables.
Local Variables
Variables that are declared inside a function or block are local variables.
They can be used only by statements that are inside that function or block of code.
Local variables are not known to functions outside their own.
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit2/assets/11.html 67 of 278 2/3
Basics of C++, Elementary Data Structures : Arrays, linked lists
8/13/2015 scorm content
Global Variables
Global variables are defined outside of all the functions, usually on top of the program.
The global variables will hold their value throughout the lifetime of your program.
A global variable can be accessed by any function.
That is, a global variable is available for use throughout your entire program after its
declaration.
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit2/assets/11.html 68 of 278 3/3
Basics of C++, Elementary Data Structures : Arrays, linked lists
8/13/2015 scorm content
Constants
Constants refer to fixed values that the program may not alter and they are called literals.
There are two simple ways in C++ to define constants:
The #define Preprocessor
Following is the form to use #define preprocessor to define a constant:
#define identifier value.
The const Keyword
You can use const prefix to declare constants with a specific type as follows:
const type variable = value;
Constants can be of any of the basic data types and can be divided into Integer Numerals,
FloatingPoint Numerals, Characters, Strings and Boolean Values.
Again, constants are treated just like regular variables except that their values cannot be
modified after their definition.
Integer Literals
An integer literal can be a decimal, octal, or hexadecimal constant.
A prefix specifies the base or radix: 0x or 0X for hexadecimal, 0 for octal, and nothing for
decimal.
An integer literal can also have a suffix that is a combination of U and L, for unsigned and long,
respectively.
The suffix can be uppercase or lowercase and can be in any order.
Floatingpoint Literals
A floatingpoint literal has an integer part, a decimal point, a fractional part, and an exponent
part.
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit2/assets/12.html 69 of 278 1/3
Basics of C++, Elementary Data Structures : Arrays, linked lists
8/13/2015 scorm content
You can represent floating point literals either in decimal form or exponential form.
While representing using decimal form, you must include the decimal point, the exponent, or
both and while representing using exponential form, you must include the integer part, the
fractional part, or both.
The signed exponent is introduced by e or E.
Boolean Literals
There are two Boolean literals and they are part of standard C++ keywords:
A value of true representing true.
A value of false representing false.
You should not consider the value of true equal to 1 and value of false equal to 0.
String literals
String literals are enclosed in double quotes.
A string contains characters that are similar to character literals: plain characters, escape
sequences, and universal characters.
You can break a long line into multiple lines using string literals and separate them using
whitespaces.
Character Literals
Character literals are enclosed in single quotes. If the literal begins with L (uppercase only), it is
a wide character literal (e.g., L‘x’) and should be stored in wchar_t type of variable.
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit2/assets/12.html 70 of 278 2/3
Basics of C++, Elementary Data Structures : Arrays, linked lists
8/13/2015 scorm content
Otherwise, it is a narrow character literal (e.g., ‘x’) and can be stored in a simple variable of char
type.
A character literal can be a plain character (e.g., ‘x’), an escape sequence (e.g., ‘\t’), or a
universal character (e.g., ‘\u02C0’).
There are certain characters in C++ when they are preceded by a backslash they will have
special meaning and they are used to represent like newline (\n) or tab (\t).
Following is the example to show few escape sequence characters:
When the above code is compiled and executed, it produces the following result:
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit2/assets/12.html 71 of 278 3/3
Basics of C++, Elementary Data Structures : Arrays, linked lists
8/13/2015 scorm content
Modifiers
The modifiers signed, unsigned, long, and short can be applied to integer base types.
In addition, signed and unsigned can be applied to char, and long can be applied to double.
The modifiers signed and unsigned can also be used as prefix to long or short modifiers. For
example, unsigned long int.
C++ allows a shorthand notation for declaring unsigned, short, or long integers.
You can simply use the word unsigned, short, or long, without the int. The int is implied.
For example, the following two statements both declare unsigned integer variables.
unsigned x;
unsigned int y;
There are C++ allows the char, int, and double data types to have modifiers preceding them.
A modifier is used to alter the meaning of the base type so that it more precisely fits the needs of
various situations.
The data type modifiers are listed here:
signed.
unsigned.
long.
short.
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit2/assets/13.html 72 of 278 1/1
Basics of C++, Elementary Data Structures : Arrays, linked lists
8/13/2015 scorm content
Type Qualifiers in C++
Const
Objects of type const cannot be changed by your program during execution.
Volatile
The modifier volatile tells the compiler that a variable′s value may be changed in ways not
explicitly specified by the program.
Restrict
A pointer qualified by restrict is initially the only means by which the object it points to can be
accessed. Only C99 adds a new type qualifier called restrict.
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit2/assets/14.html 73 of 278 1/1
Basics of C++, Elementary Data Structures : Arrays, linked lists
8/13/2015 scorm content
Storage Classes in C++
A storage class defines the scope (visibility) and lifetime of variables and/or functions within a
C++ Program.
These specifiers precede the type that they modify.
The Auto Storage Class
The auto storage class is the default storage class for all local variables.
The example above defines two variables with the same storage class, auto can only be used
within functions, i.e., local variables.
The Register Storage Class
The register storage class is used to define local variables that should be stored in a register
instead of RAM.
This means that the variable has a maximum size equal to the register size (usually one word)
and can′t have the unary ‘&’ operator applied to it (as it does not have a memory location).
The register should only be used for variables that require quick access such as counters.
It should also be noted that defining ‘register’ does not mean that the variable will be stored in a
register.
It means that it MIGHT be stored in a register depending on hardware and implementation
restrictions.
The Static Storage Class
The static storage class instructs the compiler to keep a local variable in existence during the
lifetime of the program instead of creating and destroying it each time it comes into and goes
out of scope.
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit2/assets/15.html 74 of 278 1/3
Basics of C++, Elementary Data Structures : Arrays, linked lists
8/13/2015 scorm content
Therefore, making local variables static allows them to maintain their values between function
calls.
The static modifier may also be applied to global variables.
When this is done, it causes that variable′s scope to be restricted to the file in which it is
declared.
In C++, when static is used on a class data member, it causes only one copy of that member to
be shared by all objects of its class.
The Extern Storage Class
The extern storage class is used to give a reference of a global variable that is visible to ALL the
program files.
When you use ‘extern’ the variable cannot be initialized as all it does is point the variable name
at a storage location that has been previously defined.
When you have multiple files and you define a global variable or function, which will be used in
other files also, then extern will be used in another file to give reference of defined variable or
function.
Just for understanding extern is used to declare a global variable or function in another file.
The extern modifier is most commonly used when there are two or more files sharing the same
global variables or functions.
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit2/assets/15.html 75 of 278 2/3
Basics of C++, Elementary Data Structures : Arrays, linked lists
8/13/2015 scorm content
The Mutable Storage Class
The mutable specifier applies only to class objects.
It allows a member of an object to override constness.
That is, a mutable member can be modified by a const member function.
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit2/assets/15.html 76 of 278 3/3
Basics of C++, Elementary Data Structures : Arrays, linked lists
8/13/2015 scorm content
Operators
An operator is a symbol that tells the compiler to perform specific mathematical or logical
manipulations.
Arithmetic Operators
(+) Adds two operands.
() Subtracts second operand from the first.
(*) Multiplies both operands.
(/) Divides numerator by denumerator.
(%) Modulus Operator and remainder of after an integer division.
(++) Increment operator, increases integer value by one.
() Decrement operator, decreases integer value by one.
Relational Operators
(==) Checks if the values of two operands are equal or not, if yes then condition becomes true.
(!=) Checks if the values of two operands are equal or not, if values are not equal then condition
becomes true.
(>) Checks if the value of left operand is greater than the value of right operand, if yes then
condition becomes true.
(<) Checks if the value of left operand is less than the value of right operand, if yes then
condition becomes true.
(>=) Checks if the value of left operand is greater than or equal to the value of right operand, if
yes then condition becomes true.
(<=) Checks if the value of left operand is less than or equal to the value of right operand, if yes
then condition becomes true.
Logical Operators
(&&) Called Logical AND operator. If both the operands are nonzero, then condition becomes
true.
(||) Called Logical OR Operator. If any of the two operands is nonzero, then condition becomes
true.
(!) Called Logical NOT Operator. Use to reverses the logical state of its operand. If a condition is
true, then Logical NOT operator will make false.
Bitwise Operators
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit2/assets/16.html 77 of 278 1/3
Basics of C++, Elementary Data Structures : Arrays, linked lists
8/13/2015 scorm content
(&) Binary AND Operator copies a bit to the result if it exists in both operands.
(|) Binary OR Operator copies a bit if it exists in either operand.
(^) Binary XOR Operator copies the bit if it is set in one operand but not both.
(~) Binary Ones Complement Operator is unary and has the effect of ‘flipping’ bits.
(<<) Binary Left Shift Operator. The left operands value is moved left by the number of bits
specified by the right operand.
(>>) Binary Right Shift Operator. The left operands value is moved right by the number of bits
specified by the right operand.
Assignment Operators
(=) Simple assignment operator, Assigns values from right side operands to left side operand.
(+=) Add AND assignment operator, It adds right operand to the left operand and assign the
result to left operand.
(=) Subtract AND assignment operator, It subtracts right operand from the left operand and
assign the result to left operand.
(*=) Multiply AND assignment operator, It multiplies right operand with the left operand and
assign the result to left operand.
(/=) Divide AND assignment operator, It divides left operand with the right operand and assign
the result to left operand.
(%=) Modulus AND assignment operator, It takes modulus using two operands and assign the
result to left operand.
(<<=) Left shift AND assignment operator.
(>>=) Right shift AND assignment operator.
(&=) Bitwise AND assignment operator.
(^=) Bitwise exclusive OR and assignment operator.
(|=) Bitwise inclusive OR and assignment operator.
Misc Operators
(Sizeof) Sizeof operator returns the size of a variable. For example, sizeof(a), where a is integer,
will return 4.
(Condition ? X : Y) Conditional operator. If Condition is true ? then it returns value X : otherwise
value Y.
(,) Comma operator causes a sequence of operations to be performed. The value of the entire
comma expression is the value of the last expression of the commaseparated list.
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit2/assets/16.html 78 of 278 2/3
Basics of C++, Elementary Data Structures : Arrays, linked lists
8/13/2015 scorm content
(. (dot) and > (arrow)) Member operators are used to reference individual members of classes,
structures, and unions.
(Cast) Casting operators convert one data type to another. For example, int(2.2000) would
return 2.
(&) Pointer operator & returns the address of an variable. For example &a; will give actual
address of the variable.
(*) Pointer operator * is pointer to a variable. For example *var; will pointer to a variable var.
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit2/assets/16.html 79 of 278 3/3
Basics of C++, Elementary Data Structures : Arrays, linked lists
8/13/2015 scorm content
C++ Basic Input & output
C++ I/O occurs in streams, which are sequences of bytes.
If bytes flow from a device like a keyboard, a disk drive, or a network connection etc. to main
memory, this is called input operation and if bytes flow from main memory to a device like a
display screen, a printer, a disk drive, or a network connection, etc, this is called output
operation.
I/O Library Header Files
This file defines the cin, cout, cerr and clog objects, which correspond to the standard input
stream, the standard output stream, the unbuffered standard error stream and the buffered
standard error stream, respectively.
This file declares services useful for performing formatted I/O with socalled parameterized
stream manipulators, such as setw and setprecision.
This file declares services for usercontrolled file processing.
< iostream >
< iomanip >
< fstream >
The Standard Output Stream (cout)
The predefined object cout is an instance of ostream class. The cout object is said to be
"connected to" the standard output device, which usually is the display screen.
The cout is used in conjunction with the stream insertion operator, which is written as << which
are two less than signs.
The C++ compiler also determines the data type of variable to be output and selects the
appropriate stream insertion operator to display the value.
The << operator is overloaded to output data items of builtin types integer, float, double, strings
and pointer values.
The insertion operator << may be used more than once in a single statement and endl is used to
add a newline at the end of the line.
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit2/assets/17.html 80 of 278 1/3
Basics of C++, Elementary Data Structures : Arrays, linked lists
8/13/2015 scorm content
When the above code is compiled and executed, it produces the following result:
The Standard Input Stream (cin)
The predefined object cin is an instance of istream class. The cin object is said to be attached to
the standard input device, which usually is the keyboard.
The cin is used in conjunction with the stream extraction operator, which is written as >> which
are two greater than signs.
The C++ compiler also determines the data type of the entered value and selects the
appropriate stream extraction operator to extract the value and store it in the given variables.
The stream extraction operator >> may be used more than once in a single statement. To
request more than one datum you can use the following:
This will be equivalent to the following two statements:
When the above code is compiled and executed, it will prompt you to enter a name. You enter a
value and then hit enter to see the result something as follows:
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit2/assets/17.html 81 of 278 2/3
Basics of C++, Elementary Data Structures : Arrays, linked lists
8/13/2015 scorm content
The Standard Error Stream (cerr)
The predefined object cerr is an instance of ostream class. The cerr object is said to be attached
to the standard error device, which is also a display screen but the object cerr is unbuffered and
each stream insertion to cerr causes its output to appear immediately.
The cerr is also used in conjunction with the stream insertion operator.
The Standard Log Stream (clog)
The predefined object clog is an instance of ostream class. The clog object is said to be
attached to the standard error device, which is also a display screen but the object clog is
buffered.
This means that each insertion to clog could cause its output to be held in a buffer until the
buffer is filled or until the buffer is flushed.
The clog is also used in conjunction with the stream insertion operator.
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit2/assets/17.html 82 of 278 3/3
Basics of C++, Elementary Data Structures : Arrays, linked lists
8/13/2015 scorm content
C++ Loop Types
Programming languages provide various control structures that allow for more complicated
execution paths.
A loop statement allows us to execute a statement or group of statements multiple times and
following is the general from of a loop statement in most of the programming languages.
There may be a situation, when you need to execute a block of code several number of times.
In general statements are executed sequentially: The first statement in a function is executed
first, followed by the second, and so on.
While loop.
For loop.
Do…while loop.
Nested loops.
Repeats a statement or group of statements while a given condition is true.
It tests the condition before executing the loop body.
Execute a sequence of statements multiple times and abbreviates the code that manages the
loop variable.
Like a while statement, except that it tests the condition at the end of the loop body.
You can use one or more loop inside any another while, for or do..while loop.
Loop Control Statements
Loop control statements change execution from its normal sequence.
When execution leaves a scope, all automatic objects that were created in that scope are
destroyed.
Break statement.
Continue statement.
Goto statement.
Terminates the loop or switch statement and transfers execution to the statement immediately
following the loop or switch.
Causes the loop to skip the remainder of its body and immediately retest its condition prior to
reiterating.
Transfers control to the labeled statement.
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit2/assets/18.html 83 of 278 1/2
Basics of C++, Elementary Data Structures : Arrays, linked lists
8/13/2015 scorm content
Though it is not advised to use goto statement in your program.
Infinite Loop
A loop becomes infinite loop if a condition never becomes false. The for loop is traditionally used
for this purpose.
Since none of the three expressions that form the for loop are required, you can make an
endless loop by leaving the conditional expression empty.
When the conditional expression is absent, it is assumed to be true.
You may have an initialization and increment expression, but C++ programmers more commonly
use the for(;;) construct to signify an infinite loop.
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit2/assets/18.html 84 of 278 2/2
Basics of C++, Elementary Data Structures : Arrays, linked lists
8/13/2015 scorm content
C++ Decision Making
Decision making structures require that the programmer specify one or more conditions to be
evaluated or tested by the program, along with a statement or statements to be executed if the
condition is determined to be true, and optionally, other statements to be executed if the
condition is determined to be false.
C++ programming language provides following types of decision making statements.
If statement
An if statement consists of a boolean expression followed by one or more statements.
If…else statement
An if statement can be followed by an optional else statement, which executes when the
boolean expression is false.
Switch statement
A switch statement allows a variable to be tested for equality against a list of values.
Nested if statements
You can use one if or else if statement inside another if or else if statement(s).
Nested switch statements.
You can use one switch statement inside another switch statement(s).
The ?: Operator
Exp1 ? Exp2 : Exp3;
Where Exp1, Exp2, and Exp3 are expressions. Notice the use and placement of the colon.
The value of a ? expression is determined like this: Exp1 is evaluated. If it is true, then
Exp2 is evaluated and becomes the value of the entire ? expression. If Exp1 is false, then
Exp3 is evaluated and its value becomes the value of the expression.
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit2/assets/19.html 85 of 278 1/1
Basics of C++, Elementary Data Structures : Arrays, linked lists
8/13/2015 scorm content
Functions
A function is a group of statements that together perform a task.
Every C++ program has at least one function, which is main(), and all the most trivial programs
can define additional functions.
A function declaration tells the compiler about a function′s name, return type, and parameters.
A function definition provides the actual body of the function.
A function is knows as with various names like a method or a subroutine or a procedure etc.
You can divide up your code into separate functions.
How you divide up your code among different functions is up to you, but logically the division
usually is so each function performs a specific task.
The C++ standard library provides numerous builtin functions that your program can call.
For example, function strcat() to concatenate two strings, function memcpy() to copy one
memory location to another location and many more functions.
Defining a Function
The general form of a C++ function definition is as follows:
A C++ function definition consists of a function header and a function body. Here are all the parts
of a function:
Return Type.
A function may return a value. The return_type is the data type of the value the function
returns.
Some functions perform the desired operations without returning a value. In this case, the
return_type is the keyword void.
Function Name.
This is the actual name of the function.
The function name and the parameter list together constitute the function signature.
Parameters.
A parameter is like a placeholder. When a function is invoked, you pass a value to the
parameter.
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit2/assets/20.html 86 of 278 1/3
Basics of C++, Elementary Data Structures : Arrays, linked lists
8/13/2015 scorm content
This value is referred to as actual parameter or argument.
The parameter list refers to the type, order, and number of the parameters of a function.
Parameters are optional; that is, a function may contain no parameters.
Function Body.
The function body contains a collection of statements that define what the function does.
Function Declarations
A function declaration tells the compiler about a function name and how to call the function. The
actual body of the function can be defined separately.
A function declaration has the following parts:
return_type function_name(parameter list);
Parameter names are not importan in function declaration only their type is required, so
following is also valid declaration:
int max(int num1, int num2);
int max(int, int);
Function declaration is required when you define a function in one source file and you call that
function in another file. In such case, you should declare the function at the top of the file calling
the function.
Calling a Function
When a program calls a function, program control is transferred to the called function.
A called function performs defined task and when its return statement is executed or when its
functionending closing brace is reached, it returns program control back to the main program.
To call a function, you simply need to pass the required parameters along with function name,
and if function returns a value, then you can store returned value.
While creating a C++ function, you give a definition of what the function has to do. To use a
function, you will have to call or invoke that function.
Function Arguments
If a function is to use arguments, it must declare variables that accept the values of the
arguments. These variables are called the formal parameters of the function.
The formal parameters behave like other local variables inside the function and are created
upon entry into the function and destroyed upon exit.
While calling a function, there are two ways that arguments can be passed to a function:
Call by value
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit2/assets/20.html 87 of 278 2/3
Basics of C++, Elementary Data Structures : Arrays, linked lists
8/13/2015 scorm content
This method copies the actual value of an argument into the formal parameter of the
function.
In this case, changes made to the parameter inside the function have no effect on the
argument.
Call by pointer
This method copies the address of an argument into the formal parameter.
Inside the function, the address is used to access the actual argument used in the call.
This means that changes made to the parameter affect the argument.
Call by reference
This method copies the reference of an argument into the formal parameter.
Inside the function, the reference is used to access the actual argument used in the call.
This means that changes made to the parameter affect the argument.
By default, C++ uses call by value to pass arguments.
In general, this means that code within a function cannot alter the arguments used to call the
function and above mentioned example while calling max() function used the same method.
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit2/assets/20.html 88 of 278 3/3
Basics of C++, Elementary Data Structures : Arrays, linked lists
8/13/2015 scorm content
Arrays
C++ provides a data structure, the array, which stores a fixedsize sequential collection of
elements of the same type.
An array is used to store a collection of data, but it is often more useful to think of an array as a
collection of variables of the same type.
All arrays consist of contiguous memory locations.
The lowest address corresponds to the first element and the highest address to the last element.
Arrays are important to C++ and should need lots of more detail.
There are following few important concepts, which should be clear to a C++ programmer:
Multidimensional arrays.
Pointer to an array.
Passing arrays to functions.
Return array from functions.
C++ supports multidimensional arrays. The simplest form of the multidimensional array is the
twodimensional array.
You can generate a pointer to the first element of an array by simply specifying the array name,
without any index.
You can pass to the function a pointer to an array by specifying the array′s name without an
index.
C++ allows a function to return an array.
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit2/assets/21.html 89 of 278 1/1
Basics of C++, Elementary Data Structures : Arrays, linked lists
8/13/2015 scorm content
Strings
strcpy(s1, s2);
Copies string s2 into string s1.
strcat(s1, s2);
Concatenates string s2 onto the end of string s1.
strlen(s1);
Returns the length of string s1.
strcmp(s1, s2);
Returns 0 if s1 and s2 are the same; less than 0 if s1s2.
strchr(s1, ch);
Returns a pointer to the first occurrence of character ch in string s1.
strstr(s1, s2);
Returns a pointer to the first occurrence of string s2 in string s1.
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit2/assets/22.html 90 of 278 1/1
Basics of C++, Elementary Data Structures : Arrays, linked lists
8/13/2015 scorm content
Pointers
C++ pointers are easy and fun to learn.
Some C++ tasks are performed more easily with pointers, and other C++ tasks, such as dynamic
memory allocation, cannot be performed without them.
A pointer is a variable whose value is the address of another variable.
Like any variable or constant, you must declare a pointer before you can work with it.
The general form of a pointer variable declaration is:
type *varname;
Here, type is the pointer′s base type; it must be a valid C++ type and varname is the name of
the pointer variable.
The asterisk you used to declare a pointer is the same asterisk that you use for multiplication.
However, in this statement the asterisk is being used to designate a variable as a pointer.
Following are the valid pointer declaration:
int *ip; // pointer to an integer
double *dp; // pointer to a double
float *fp; // pointer to a float
char *ch // pointer to character
The actual data type of the value of all pointers, whether integer, float, character, or otherwise, is
the same, a long hexadecimal number that represents a memory address.
The only difference between pointers of different data types is the data type of the variable or
constant that the pointer points.
Pointers have many but easy concepts and they are very important to C++ programming.
There are following few important pointer concepts which should be clear to a C++ programmer:
C++ Null Pointers
C++ supports null pointer, which is a constant with a value of zero defined in several
standard libraries.
C++ Pointer Arithmetic
There are four arithmetic operators that can be used on pointers: ++, , +, .
C++ Pointers vs Arrays
There is a close relationship between pointers and arrays. Let us check how?
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit2/assets/23.html 91 of 278 1/2
Basics of C++, Elementary Data Structures : Arrays, linked lists
8/13/2015 scorm content
C++ Array of Pointers
You can define arrays to hold a number of pointers.
C++ Pointer to Pointer
C++ allows you to have pointer on a pointer and so on.
Passing Pointers to Functions
Passing an argument by reference or by address both enable the passed argument to be
changed in the calling function by the called function.
Return Pointer from functions
C++ allows a function to return a pointer to local variable, static variable and dynamically
allocated memory as well.
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit2/assets/23.html 92 of 278 2/2
Basics of C++, Elementary Data Structures : Arrays, linked lists
8/13/2015 scorm content
Object Oriented Programming C++ Classes and Objects
A class is used to specify the form of an object and it combines data representation and
methods for manipulating that data into one neat package.
The data and functions within a class are called members of the class.
The main purpose of C++ programming is to add object orientation to the C programming
language and classes are the central feature of C++ that supports objectoriented programming
and are often called userdefined types.
Concept:
Class member functions
A member function of a class is a function that has its definition or its prototype within the
class definition like any other variable.
Class access modifiers
A class member can be defined as public, private or protected. By default members would
be assumed as private.
Constructor & destructor
A class constructor is a special function in a class that is called when a new object of the
class is created. A destructor is also a special function which is called when created object
is deleted.
C++ copy constructor
The copy constructor is a constructor which creates an object by initializing it with an
object of the same class, which has been created previously.
C++ friend functions
A friend function is permitted full access to private and protected members of a class.
C++ inline functions
With an inline function, the compiler tries to expand the code in the body of the function in
place of a call to the function.
The this pointer in C++
Every object has a special pointer this which points to the object itself.
Pointer to C++ classes
A pointer to a class is done exactly the same way a pointer to a structure is. In fact a class
is really just a structure with functions in it.
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit2/assets/24.html 93 of 278 1/2
Basics of C++, Elementary Data Structures : Arrays, linked lists
8/13/2015 scorm content
Static members of a class
Both data members and function members of a class can be declared as static.
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit2/assets/24.html 94 of 278 2/2
Basics of C++, Elementary Data Structures : Arrays, linked lists
8/13/2015 scorm content
Object Oriented Programming Encapsulation
Encapsulation is an Object Oriented Programming concept that binds together the data and
functions that manipulate the data, and that keeps both safe from outside interference and
misuse.
Data encapsulation led to the important OOP concept of data hiding.
Data encapsulation is a mechanism of bundling the data, and the functions that use them and
data abstraction is a mechanism of exposing only the interfaces and hiding the implementation
details from the user.
All C++ programs are composed of the following two fundamental elements:
Program statements (code): This is the part of a program that performs actions and they are
called functions.
Program data: The data is the information of the program which affected by the program
functions.
C++ supports the properties of encapsulation and data hiding through the creation of user
defined types, called classes.
We already have studied that a class can contain private, protected and public members.
By default, all items defined in a class are private.
The variables length, breadth, and height are private.
This means that they can be accessed only by other members of the Box class, and not by any
other part of your program. This is one way encapsulation is achieved.
To make parts of a class public (i.e., accessible to other parts of your program), you must
declare them after the public keyword.
All variables or functions defined after the public specifier are accessible by all other functions in
your program.
Making one class a friend of another exposes the implementation details and reduces
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit2/assets/25.html 95 of 278 1/2
Basics of C++, Elementary Data Structures : Arrays, linked lists
8/13/2015 scorm content
encapsulation.
The ideal is to keep as many of the details of each class hidden from all other classes as
possible.
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit2/assets/25.html 96 of 278 2/2
Basics of C++, Elementary Data Structures : Arrays, linked lists
8/13/2015 scorm content
Object Oriented Programming Abstraction
Data abstraction refers to, providing only essential information to the outside world and hiding
their background details, i.e., to represent the needed information in program without presenting
the details.
Data abstraction is a programming (and design) technique that relies on the separation of
interface and implementation.
In C++, we use classes to define our own abstract data types (ADT).
You can use the cout object of class ostream to stream data to standard output.
Let′s take one real life example of a TV, which you can turn on and off, change the channel,
adjust the volume, and add external components such as speakers, VCRs, and DVD players,
BUT you do not know its internal details, that is, you do not know how it receives signals over the
air or through a cable, how it translates them, and finally displays them on the screen.
Thus, we can say a television clearly separates its internal implementation from its external
interface and you can play with its interfaces like the power button, channel changer, and
volume control without having zero knowledge of its internals.
Now, if we talk in terms of C++ Programming, C++ classes provides great level of data
abstraction.
They provide sufficient public methods to the outside world to play with the functionality of the
object and to manipulate object data, i.e., state without actually knowing how class has been
implemented internally.
Access Labels Enforce Abstraction
Members defined with a public label are accessible to all parts of the program.
The dataabstraction view of a type is defined by its public members.
Members defined with a private label are not accessible to code that uses the class.
The private sections hide the implementation from code that uses the type.
There are no restrictions on how often an access label may appear.
Each access label specifies the access level of the succeeding member definitions.
The specified access level remains in effect until the next access label is encountered or the
closing right brace of the class body is seen.
Benefits of Data Abstraction
Class internals are protected from inadvertent userlevel errors, which might corrupt the state of
the object.
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit2/assets/26.html 97 of 278 1/2
Basics of C++, Elementary Data Structures : Arrays, linked lists
8/13/2015 scorm content
The class implementation may evolve over time in response to changing requirements or bug
reports without requiring change in userlevel code.
By defining data members only in the private section of the class, the class author is free to
make changes in the data.
If the implementation changes, only the class code needs to be examined to see what affect the
change may have.
If data are public, then any function that directly accesses the data members of the old
representation might be broken.
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit2/assets/26.html 98 of 278 2/2
Basics of C++, Elementary Data Structures : Arrays, linked lists
8/13/2015 scorm content
Object Oriented Programming Inheritance
A class can be derived from more than one classes, which means it can inherit data and
functions from multiple base classes.
To define a derived class, we use a class derivation list to specify the base class(es).
A class derivation list names one or more base classes and has the form:
class derivedclass: accessspecifier baseclass
Accessspecifier is one of public, protected, or private, and baseclass is the name of a
previously defined class.
If the accessspecifier is not used, then it is private by default.
Access Control and Inheritance
A derived class can access all the nonprivate members of its base class.
Thus baseclass members that should not be accessible to the member functions of derived
classes should be declared private in the base class.
Constructors, destructors and copy constructors of the base class.
Overloaded operators of the base class.
The friend functions of the base class.
Types of Inheritance
When deriving a class from a base class, the base class may be inherited through public,
protected orprivate inheritance. The type of inheritance is specified by the accessspecifier as
explained above.
We hardly use protected or private inheritance, but public inheritance is commonly used.
While using different type of inheritance, following rules are applied:
Public
Public Inheritance: When deriving a class from a public base class, public members of the
base class become public members of the derived class and protected members of the
base class become protected members of the derived class.
A base class′s private members are never accessible directly from a derived class, but
can be accessed through calls to the public and protected members of the base class.
Protected
Protected Inheritance: When deriving from a protected baseclass, public and protected
members of the base class become protected members of the derived class.
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit2/assets/27.html 99 of 278 1/2
Basics of C++, Elementary Data Structures : Arrays, linked lists
8/13/2015 scorm content
Private
Private Inheritance: When deriving from a private baseclass, public and protected
members of the base class become private members of the derived class.
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit2/assets/27.html 100 of 278 2/2
Basics of C++, Elementary Data Structures : Arrays, linked lists
8/13/2015 scorm content
Object Oriented Programming Polymorphism
The word polymorphism means having many forms.
Typically, polymorphism occurs when there is a hierarchy of classes and they are related by
inheritance.
C++ polymorphism means that a call to a member function will cause a different function to be
executed depending on the type of object that invokes the function.
The compiler looks at the contents of the pointer instead of it′s type.
Hence, since addresses of objects of tri and rec classes are stored in *shape the respective
area() function is called.
As you can see, each of the child classes has a separate implementation for the function area().
This is how polymorphism is generally used.
You have different classes with a function of the same name, and even the same parameters,
but with different implementations.
Virtual Function
A virtual function is a function in a base class that is declared using the keyword virtual.
Defining in a base class a virtual function, with another version in a derived class, signals to the
compiler that we don′t want static linkage for this function.
What we do want is the selection of the function to be called at any given point in the program to
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit2/assets/28.html 101 of 278 1/2
Basics of C++, Elementary Data Structures : Arrays, linked lists
8/13/2015 scorm content
be based on the kind of object for which it is called.
This sort of operation is referred to as dynamic linkage, or late binding.
Pure Virtual Functions
It′s possible that you′d want to include a virtual function in a base class so that it may be
redefined in a derived class to suit the objects of that class, but that there is no meaningful
definition you could give for the function in the base class.
We can change the virtual function area() in the base class.
The = 0 tells the compiler that the function has no body and above virtual function will be called
pure virtual function.
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit2/assets/28.html 102 of 278 2/2
Basics of C++, Elementary Data Structures : Arrays, linked lists
8/13/2015 scorm content
Object Oriented Programming Overloading
C++ allows you to specify more than one definition for a function name or an operator in the
same scope, which is called function overloading and operator overloading respectively.
An overloaded declaration is a declaration that had been declared with the same name as a
previously declared declaration in the same scope, except that both declarations have different
arguments and obviously different definition (implementation).
When you call an overloaded function or operator, the compiler determines the most appropriate
definition to use by comparing the argument types you used to call the function or operator with
the parameter types specified in the definitions.
The process of selecting the most appropriate overloaded function or operator is called overload
resolution.
Funtion Overloading in C++
You can have multiple definitions for the same function name in the same scope.
The definition of the function must differ from each other by the types and/or the number of
arguments in the argument list.
You can not overload function declarations that differ only by return type.
Operator Overloading in C++
Overloaded operators are functions with special names the keyword operator followed by the
symbol for the operator being defined.
Like any other function, an overloaded operator has a return type and a parameter list.
Box operator+(const Box&);
Declares the addition operator that can be used to add two Box objects and returns final Box
object.
Most overloaded operators may be defined as ordinary nonmember functions or as class
member functions.
In case we define above function as nonmember function of a class then we would have to pass
two arguments for each operand as follows:
You can redefine or overload most of the builtin operators available in C++.
Thus a programmer can use operators with userdefined types as well.
The concept of operator over loading using a member function.
Here an object is passed as an argument whose properties will be accessed using this object,
the object which will call this operator can be accessed using this operator.
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit2/assets/29.html 103 of 278 1/1
Basics of C++, Elementary Data Structures : Arrays, linked lists
8/13/2015 scorm content
Representation of Array
Array is a data structure that represents a collection of the same types of data.
Declaring Array Variables
Array can be declared by two different methods:
Method 1:
Method 2:
Creating Arrays
Creating an array,
arrayRefVar = new datatype[arraySize];
Example:
myList = new double[10];
myList[0] references the first element in the array.
myList[9] references the last element in the array.
Declaring and Creating in One Step
Creating and declaring the array in one step follows:
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit2/assets/30.html 104 of 278 1/2
Basics of C++, Elementary Data Structures : Arrays, linked lists
8/13/2015 scorm content
Applications
Arrays are used to implement mathematical vectors and matrices, as well as other kinds of
rectangular tables.
Many databases, small and large, consist onedimensional arrays whose elements are records.
Arrays are used to implement other data structures, such as heaps, hash tables, dequeues,
queues, stacks, strings, and VLists.
One or more large arrays are sometimes used to emulate inprogram dynamic memory
allocation, particularly memory pool allocation.
Historically, this has sometimes been the only way to allocate "dynamic memory" portably.
Arrays can be used to determine partial or complete control flow in programs, as a compact
alternative to multiple IF statements.
They are known in this context as control tables and are used in conjunction with a purpose built
interpreter whose control flow is altered according to values contained in the array.
The array may contain subroutine pointers that direct the path of the execution.
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit2/assets/30.html 105 of 278 2/2
Basics of C++, Elementary Data Structures : Arrays, linked lists
8/13/2015 scorm content
Dimensional Arrays
A onedimensional array (or single dimension array) is a type of linear array.
Accessing its elements involves a single subscript which can either represent a row or column
index.
As an example consider the C declaration
int anArrayName[10];
Syntax : datatype an Arrayname[sizeof Array];
In the given example the array can contain 10 elements of any value available to the int type.
In C, the array element indices are 09 inclusive in this case.
For example, the expressions an ArrayName[0] and an ArrayName[9] are the first and last
elements respectively.
For a vector with linear addressing, the element with index i is located at the address B + c × i,
where B is a fixed base address and c a fixed constant, sometimes called the address increment
or stride.
If the valid element indices begin at 0, the constant B is simply the address of the first element of
the array.
For this reason, the C programming language specifies that array indices always begin at 0; and
many programmers will call that element "zeroth" rather than "first".
However, one can choose the index of the first element by an appropriate choice of the base
address B.
For example, if the array has five elements, indexed 1 through 5, and the base address B is
replaced by B + 30c, then the indices of those same elements will be 31 to 35.
If the numbering does not start at 0, the constant B may not be the address of any element.
Multidimensional Arrays
For a twodimensional array, the element with indices i, j would have address B + c • i + d • j,
where the coefficients c and d are the row and column address increments, respectively.
For example: int a[3][2];
This means that array a has 3 rows and 2 columns, and the array is of integer type.
Here we can store 6 elements they are stored linearly but starting from first row linear then
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit2/assets/31.html 106 of 278 1/2
Basics of C++, Elementary Data Structures : Arrays, linked lists
8/13/2015 scorm content
continuing with second row.
This formula requires only k multiplications and k additions, for any array that can fit in
memory.
Moreover, if any coefficient is a fixed power of 2, the multiplication can be replaced by bit
shifting.
The coefficients ck must be chosen so that every valid index tuple maps to the address of a
distinct element.
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit2/assets/31.html 107 of 278 2/2
Basics of C++, Elementary Data Structures : Arrays, linked lists
8/13/2015 scorm content
Search
The search algorithm described next is called a sequential or linear search.
Suppose that you want to determine whether 27 is in the list.
The sequential search works as follows:
First, you compare 27 with list[0]—that is, compare 27 with 35.
Because list[0] 6 ≠ 27, you then compare 27 with list[1] (that is, with 12, the second item in the
list).
Because list[1] 6 ≠ 27, you compare 27 with the next element in the list—that is, compare 27 with
list[2].
Because list[2] = 27, the search stops. This is a successful search.
Let us now search for 10.
As before, the search starts with the first element in the list—that is, at list[0].
This time the search item, which is 10, is compared with every item in the list. Eventually, no
more data is left in the list to compare with the search item.
Suppose that the name of the array containing the list elements is list. The following function
performs a sequential search on a list:
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit2/assets/32.html 108 of 278 1/2
Basics of C++, Elementary Data Structures : Arrays, linked lists
8/13/2015 scorm content
Now that we know how to implement the (sequential) search algorithm, we can give the
definitions of the functions insert and remove.
Recall that the function insert inserts a new item at the end of the list if this item does not exist in
the list and the list is not full.
The function remove removes an item from the list if the list is not empty.
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit2/assets/32.html 109 of 278 2/2
Basics of C++, Elementary Data Structures : Arrays, linked lists
8/13/2015 scorm content
Insert
The function insert inserts a new item in the list.
Because duplicates are not allowed, this function first searches the list to determine whether the
item to be inserted is already in the list.
To determine whether the item to be inserted is already in the list, this function calls the member
function seqSearch, described previously.
If the item to be inserted is not in the list, the new item is inserted at the end of the list and the
length of the list is increased by 1.
Also, the item to be inserted is passed as a parameter to this function.
The function insert uses the function seqSearch to determine whether the Insert Item is already
in the list.
Because the function seqSearch is of O(n), it follows that the function insert is of O(n).
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit2/assets/33.html 110 of 278 1/1
Basics of C++, Elementary Data Structures : Arrays, linked lists
8/13/2015 scorm content
Remove
The function remove deletes an item from the list.
The item to be deleted is passed as a parameter to this function.
To delete the item, the function calls the member function seqSearch to determine whether the
item to be deleted is in the list.
If the item to be deleted is found in the list, the item is removed from the list and the length of the
list is decremented by 1.
If the item to be removed is found in the list, the function seqSearch returns the index of the item
in the list to be deleted.
We can now use the index returned by the function seqSearch, and use the function removeAt
to remove the item from the list.
Therefore, the definition of the function remove is as follows:
The function remove uses the functions seqSearch and removeAt to remove an item from the
list.
Because each of these functions is of O(n) and because they are called is sequence, it
follows that the function remove is of O(n).
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit2/assets/34.html 111 of 278 1/1
Basics of C++, Elementary Data Structures : Arrays, linked lists
8/13/2015 scorm content
Sparse Polynomial Representation and Addition
Polynomial is an expression which is composed of terms, wherein terms are composed of
coefficient and exponent.
This polynomial is composed of four terms with the following sets of coefficient and exponent –
{(4,3), (5,2), (6,1), (9,0)}.
Thus representation of a polynomial using arrays is straightforward.
The subscripts of the array may be considered as exponents and the coefficients may be stored
at an appropriate place referred to by the subscript.
Array representation for the above example is:
Arr 9 6 5 4 coefficients
subscripts 0 1 2 3 exponents
(2 + 3*X + 6*X**2) + (2 X**2) = (4 + 3*X + 5*X**2)
The above representation works fine for the above example, but for polynomials such as 5×6+7,
array representation is considered feasible on account of memory usage, since it results in a
sparse arrangement as follows:
Arr 7 0 0 0 0 0 5
subscripts 0 1 2 3 4 5 6
Sparse matrix representation may be considered for the above matrix as given below:
For addition of two polynomials using arrays, subscriptwise elements may be added to result in
the polynomial containing result of addition of two polynomials.
Example:
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit2/assets/35.html 112 of 278 1/2
Basics of C++, Elementary Data Structures : Arrays, linked lists
8/13/2015 scorm content
Array Representation:
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit2/assets/35.html 113 of 278 2/2
Basics of C++, Elementary Data Structures : Arrays, linked lists
8/13/2015 scorm content
Stack Implementation of Array
Stack is one of the important data structures that every computer programmer should be aware
of.
It follows the simple LIFO (Last In First Out) principle. Implementation of stack can be done in
many ways.
One of the simplest way is using Arrays.
Here an array is initialized to a maximum value first, let′s call it capacity.
As and when we push elements onto the array, its size will get increased.
When the size reaches the capacity, we should ideally double the array size.
Defining the stack class
The stack class is nothing but the array declaration:
Private and public class are declared.
Push operation
The push operation is used to insert the element in the array.
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit2/assets/36.html 114 of 278 1/2
Basics of C++, Elementary Data Structures : Arrays, linked lists
8/13/2015 scorm content
Pop Operation
The pop operation is used to delete the element in the array.
Check the element is empty
If the element is empty we can′t do pop operation.
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit2/assets/36.html 115 of 278 2/2
Basics of C++, Elementary Data Structures : Arrays, linked lists
8/13/2015 scorm content
Queue Implementation using Array
Queue operations are implemented using array of size 5.
Queue operations are,
Enqueue: Insert an element at ‘rear’ end.
Dequeue: Delete element from ‘front’ end.
Enqueue operation in queue
Enqueue is used to insert the elements in the queue.
Dequeue operation in queue
Dequeue operation is used to delete the element in the queue.
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit2/assets/37.html 116 of 278 1/2
Basics of C++, Elementary Data Structures : Arrays, linked lists
8/13/2015 scorm content
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit2/assets/37.html 117 of 278 2/2
Basics of C++, Elementary Data Structures : Arrays, linked lists
8/13/2015 scorm content
Stack using Linked list in C++ and Implementation
Stack is an abstract data type and a data structure which follows "Last In First Out" Principle.
In my previous tutorials I discussed about stack and implementation of the stack using arrays.
We have also seen the advantages of stack Data Structure.
In this post I will be discussing about Implementation of Stack using Linked List and program for
it.
Linked list is also a data structure which is has more advantages over stacks and queues when it
comes to memory.
If you don′t have any idea about linked list I would suggest to read the tutorial for Linkedlist.
Why to Implement stack using Linked list rather than arrays ?
In my previous post about stack implementation using array, the size of the array need to be
fixed to store the values in the stack.
If the stack is full we cannot insert an additional element into the array.
It gives an overflow exception.
But in linkedlist we can increases size at runtime by creating a new node.
So it is better to implement stack data structure using Linkedlist data structure.
The following are the operations to implement stack :
Insertion.
Deletion.
Display elements.
Insertion
Insertion operation refers to Inserting an element into stack.
We create a new node and insert an element into the stack.
To follow the stack principle " Last in first out ".
A node need to be created from the end of the Linkedlist and element need to be inserted into
the node from the end of the linked list .
Deletion
Deletion operation is to delete an element or node from the Linked list.
Deletion can be done by deleting the top most element from the stack as the Last element
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit2/assets/38.html 118 of 278 1/2
Basics of C++, Elementary Data Structures : Arrays, linked lists
8/13/2015 scorm content
inserted is the first element that needs to be deleted as per stack principle.
So the recently inserted element i.e top element must be deleted from the Linked list to perform
as Stack deletion.
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit2/assets/38.html 119 of 278 2/2
Basics of C++, Elementary Data Structures : Arrays, linked lists
8/13/2015 scorm content
Circular Linked List
In a standard queue data structure rebuffering problem occurs for each dequeue operation.
To solve this problem by joining the front and rear ends of a queue to make the queue as a
circular queue Circular queue is a linear data structure.
It follows FIFO principle.
In circular queue the last node is connected back to the first node to make a circle.
Circular linked list fallow the First In First Out principle.
Elements are added at the rear end and the elements are deleted at front end of the queue.
Both the front and the rear pointers points to the beginning of the array.
It is also called as “Ring buffer”.
Items can inserted and deleted from a queue in O(1) time.
Circular Queue can be created in three ways they are
Using single linked list.
Using double linked list.
Using arrays.
Using Single Linked List
It is an extension for the basic single linked list.
In circular linked list Instead of storing a Null value in the last node of a single linked list, store
the address of the 1st node (root) forms a circular linked list.
Using circular linked list it is possible to directly traverse to the first node after reaching the last
node.
Using Double Linked List
In double linked list the right side pointer points to the next node address or the address of first
node and left side pointer points to the previous node address or the address of last node of a
list.
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit2/assets/39.html 120 of 278 1/2
Basics of C++, Elementary Data Structures : Arrays, linked lists
8/13/2015 scorm content
Hence the above list is known as circular double linked list.
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit2/assets/39.html 121 of 278 2/2
Basics of C++, Elementary Data Structures : Arrays, linked lists
8/13/2015 scorm content
Algorithm for Creating Circular Linked List
Step 1) start.
Step 2) create anode with the following fields to store information and the address of the next
node.
Structure node.
begin
int info
pointer to structure node called next.
end
Step 3) create a class called clist with the member variables of pointer to structure nodes called
root, prev, next and the member functions create ( ) to create the circular linked list and display (
) to display the circular linked list.
Step 4) create an object called ‘C’ of clist type.
Step 5) call C. create ( ) member function.
Step 6) call C. display ( ) member function.
Step 7) stop.
Algorithm for Create ( ) Function
Step 1) allocate the memory for newnode
newnode = new (node ).
Step 2) newnode>next=newnode. // circular.
Step 3) Repeat the steps from 4 to 5 until choice = ‘n’.
Step 4) if (root=NULL).
root = prev=newnode // prev is a running pointer which points last node of a list.
else
newnode>next = root
prev>next = newnode
prev = newnode.
Step 5) Read the choice.
Step 6) return.
Algorithm for Display ( ) Function
Step 1) start.
Step 2) declare a variable of pointer to structure node called temp, assign root to
temp
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit2/assets/40.html 122 of 278 1/2
Basics of C++, Elementary Data Structures : Arrays, linked lists
8/13/2015 scorm content
temp = root.
Step 3) display temp>info.
Step 4) temp = temp>next.
Step 5) repeat the steps 6 until temp = root.
Step 6) display temp info.
Step 7) temp=temp>next.
Step 8) return.
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit2/assets/40.html 123 of 278 2/2
Basics of C++, Elementary Data Structures : Arrays, linked lists
8/13/2015 scorm content
Using Array
In arrays the range of a subscript is 0 to n1 where n is the maximum size.
To make the array as a circular array by making the subscript 0 as the next address of the
subscript n1 by using the formula subscript = (subscript +1) % maximum size.
In circular queue the front and rear pointer are updated by using the above formula.
Algorithm for Enqueue operation using array
Step 1. start.
Step 2. if (front == (rear+1)%max)
Print error “circular queue overflow “.
Step 3. else.
{ rear = (rear+1)%max
Q[rear] = element;
If (front == 1 ) f = 0;
}
Step 4. stop.
Algorithm for Dequeue operation using array
Step 1. start.
Step 2. if ((front == rear) && (rear == 1)).
Print error “circular queue underflow “
Step 3. else.
{ element = Q[front]
If (front == rear) front=rear = 1
Else
Front = (front + 1) % max
}
Step 4. stop.
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit2/assets/41.html 124 of 278 1/1
Basics of C++, Elementary Data Structures : Arrays, linked lists
8/13/2015 scorm content
Priority Queues
A priority queue is an abstract data type that captures the idea of a container whose elements
have "priorities" attached to them.
An element of highest priority always appears at the front of the queue.
If that element is removed, the next highest priority element advances to the front.
The C++ standard library defines a class template priority_queue, with the following operations:
Push: Insert an element into the prioity queue.
Top: Return (without removing it) a highest priority element from the priority queue.
Pop: Remove a highest priority element from the priority queue.
Size: Return the number of elements in the priority queue.
Empty: Return true or false according to whether the priority queue is empty or not.
A priority_queue for integers
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit2/assets/42.html 125 of 278 1/5
Basics of C++, Elementary Data Structures : Arrays, linked lists
8/13/2015 scorm content
A priority_ queue with the Smallest Value at the Front Using a
Predicate
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit2/assets/42.html 126 of 278 2/5
Basics of C++, Elementary Data Structures : Arrays, linked lists
8/13/2015 scorm content
priority_queue of int: top, pop, empty()
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit2/assets/42.html 127 of 278 3/5
Basics of C++, Elementary Data Structures : Arrays, linked lists
8/13/2015 scorm content
priority_queue: pop
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit2/assets/42.html 128 of 278 4/5
Basics of C++, Elementary Data Structures : Arrays, linked lists
8/13/2015 scorm content
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit2/assets/42.html 129 of 278 5/5
Basics of C++, Elementary Data Structures : Arrays, linked lists
8/13/2015 scorm content
Application of Stack
The following are the application of stack.
Parsing.
Recursive function.
Calling function.
Expression evaluation.
Expression conversion.
Infix to postfix.
Infix to prefix.
Postfix to Infix.
Prefix to Infix.
Towers of hanoi.
Evaluating a Postfix Expression
Algorithm to Evaluate Postfix Expressions
Initialize an empty stack.
Repeat the following until the end of the expression is encountered:
Get the next token (constant, variable, arithmetic operator) in the postfix expression.
If the token is an operand, push it onto the stack. If it is an operator then do the following:
Pop the top two values from the stack. (If the stack does not contain two items, an error
due to a malformed postfix expression has occurred and evaluation is terminated).
Apply the operator to these two values.
Push the resulting value back onto the stack.
When the end of the expression is encountered, its value is on the top of the stack. In fact, it
must be the only value in the stack and if it is not, an error due to a malformed postfix
expression has occurred.
Solution
We will use a stack to implement a very basic solution which works only for single digit integers.
There is no error handling as well.
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit2/assets/43.html 130 of 278 1/2
Basics of C++, Elementary Data Structures : Arrays, linked lists
8/13/2015 scorm content
Scan the expression from left to right.
If an operand is seen, push it onto stack.
If an operator is seen, pop of top two elements (operands) [ x & y ] from stack and perform z
= x operand y . Push z onto stack.
Repeat steps (2) & (3) till scanning is over.
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit2/assets/43.html 131 of 278 2/2
Basics of C++, Elementary Data Structures : Arrays, linked lists
8/13/2015 scorm content
Pointers What Are Pointers?
A pointer is a variable whose value is the address of another variable.
Like any variable or constant, you must declare a pointer before you can work with it.
The general form of a pointer variable declaration is:
type *varname;
Here, type is the pointer′s base type; it must be a valid C++ type and varname is the name of
the pointer variable.
Some C++ tasks are performed more easily with pointers, and other C++ tasks, such as dynamic
memory allocation, cannot be performed without them.
As you know every variable is a memory location and every memory location has its address
defined which can be accessed using ampersand (&) operator which denotes an address in
memory.
A pointer is a variable whose value is the address of another variable.
Like any variable or constant, you must declare a pointer before you can work with it.
Using Pointers in C++
There are few important operations, which we will do with the pointers very frequently.
We define a pointer variables
Assign the address of a variable to a pointer.
Finally access the value at the address available in the pointer variable.
This is done by using unary operator * that returns the value of the variable located at the
address specified by its operand. Following example makes use of these operations:
When the code is compiled and executed, it produces result something as follows:
Arithmetic Pointer
As you understood pointer is an address which is a numeric value; therefore, you can perform
arithmetic operations on a pointer just as you can a numeric value.
There are four arithmetic operators that can be used on pointers: ++, , +, and .
To understand pointer arithmetic, let us consider that ptr is an integer pointer which points to the
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit2/assets/44.html 132 of 278 1/5
Basics of C++, Elementary Data Structures : Arrays, linked lists
8/13/2015 scorm content
address 1000.
Assuming 32bit integers, let us perform the following arithmetic operation on the pointer.
ptr++
The ptr will point to the location 1004 because each time ptr is incremented, it will point to the
next integer.
This operation will move the pointer to next memory location without impacting actual value at
the memory location.
If ptr points to a character whose address is 1000, then above operation will point to the location
1001 because next character will be available at 1001.
Incrementing a Pointer
We prefer using a pointer in our program instead of an array because the variable pointer can
be incremented, unlike the array name which cannot be incremented because it is a constant
pointer.
The following program increments the variable pointer to access each succeeding element of
the array:
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit2/assets/44.html 133 of 278 2/5
Basics of C++, Elementary Data Structures : Arrays, linked lists
8/13/2015 scorm content
When the above code is compiled and executed, it produces result something as follows:
Pointer Comparisons
Pointers may be compared by using relational operators, such as ==, <, and >. If p1 and p2 point
to variables that are related to each other, such as elements of the same array, then p1 and p2
can be meaningfully compared.
The following program modifies the previous example one by incrementing the variable pointer
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit2/assets/44.html 134 of 278 3/5
Basics of C++, Elementary Data Structures : Arrays, linked lists
8/13/2015 scorm content
so long as the address to which it points is either less than or equal to the address of the last
element of the array, which is &var[MAX 1].
When the above code is compiled and executed, it produces result something as follows:
There may be a situation, when we want to maintain an array, which can store pointers to an int
or char or any other data type available.
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit2/assets/44.html 135 of 278 4/5
Basics of C++, Elementary Data Structures : Arrays, linked lists
8/13/2015 scorm content
Following is the declaration of an array of pointers to an integer:
int *ptr[MAX];
This declares ptr as an array of MAX integer pointers.
Thus, each element in ptr, now holds a pointer to an int value.
Following example makes use of three integers which will be stored in an array of pointers as
follows:
When the code is compiled and executed, it produces the following result:
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit2/assets/44.html 136 of 278 5/5
Basics of C++, Elementary Data Structures : Arrays, linked lists
8/13/2015 scorm content
Linked List
A linked list is a basic data structure where each item contains the information that we need to
get to the next item.
We can store the data in randomly using linked list.
The main advantage of linked lists over arrays is that the links provide us with the capability to
rearrange the item efficiently.
This flexibility is gained at the expense of quick access to any arbitrary item in the list, because
the only way to access to an item in the list is to follow links from the beginning.
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit2/assets/45.html 137 of 278 1/1
Basics of C++, Elementary Data Structures : Arrays, linked lists
8/13/2015 scorm content
Singly Linked List
A linked list is a series of nodes in memory such that:
There is a starting node.
Each node contains a pointer that points to the next or child node.
If a node does not have a child node then its pointer is set to NULL.
Each node contains data, maybe a lot of it.
The linked list also has functions that manage the list by performing additions, deletions,
changing the data of a node, returning the number of nodes, etc., etc.
Singly Linked List Traversal Algorithm
Assume, that we have a list with some nodes.
Traversal is the very basic operation, which presents as a part in almost every operation on a
singlylinked list.
For instance, algorithm may traverse a singlylinked list to find a value, find a position for
insertion, etc.
For a singlylinked list, only forward direction traversal is possible.
Traversal algorithm
Beginning from the head,
Check, if the end of a list hasn′t been reached yet;
Do some actions with the current node, which is specific for particular algorithm;
Current node becomes previous and next node becomes current. Go to the step 1.
SinglyLinked List Addition (insertion) operation
Insertion into a singlylinked list has two special cases.
It′s insertion a new node before the head (to the very beginning of the list) and after the tail (to
the very end of the list).
In any other case, new node is inserted in the middle of the list and so, has a predecessor and
successor in the list.
There is a description of all these cases below.
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit2/assets/46.html 138 of 278 1/4
Basics of C++, Elementary Data Structures : Arrays, linked lists
8/13/2015 scorm content
Empty list case:
When list is empty, which is indicated by (head == NULL)condition, the insertion is quite
simple.
Algorithm sets both head and tail to point to the new node.
Add First
Insertion at first would be done in two cases:
Case 1:
In this case, new node is inserted right before the current head node.
Case 2:
It can be done in two steps:
Update the next link of a new node, to point to the current head node.
Update head link to point to the new node.
Add Last
Insertion in last consist of two cases:
Case 1:
In this case, new node is inserted right after the current tail node.
Case 2:
It can be done in two steps:
Update the next link of the current tail node, to point to the new node.
Update tail link to point to the new node.
General Case
In general case there are two methods to insert the node,
Case 1:
In general case, new node is always inserted between two nodes, which are already in the
list. Head and tail links are not updated in this case.
Case 2:
Such an insert can be done in two steps:
Update link of the "previous" node, to point to the new node.
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit2/assets/46.html 139 of 278 2/4
Basics of C++, Elementary Data Structures : Arrays, linked lists
8/13/2015 scorm content
Update link of the new node, to point to the "next" node.
SinglyLinked List Removal (deletion) Operation
There are four cases, which can occur while removing the node.
These cases are similar to the cases in add operation.
We have the same four situations, but the order of algorithm actions is opposite.
Notice, that removal algorithm includes the disposal of the deleted node, which may be
unnecessary in languages with automatic garbage collection.
List has only one node:
When list has only one node, which is indicated by the condition, that the head points to the
same node as the tail, the removal is quite simple.
Algorithm disposes the node, pointed by head (or tail) and sets both head and tail to NULL.
Remove First
Removing Node in first can be done in two different case:
Case 1:
In this case, first node (current head node) is removed from the list.
Case 2:
It can be done in two steps:
Update head link to point to the node, next to the head.
Dispose removed node.
Remove Last
Removing node in last will be in two cases,
Case 1:
In this case, last node (current tail node) is removed from the list. This operation is a bit more
tricky, than removing the first node, because algorithm should find a node, which is previous
to the tail first.
Case 2:
It can be done in three steps:
Update tail link to point to the node, before the tail. In order to find it, list should be
traversed first, beginning from the head.
Set next link of the new tail to NULL.
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit2/assets/46.html 140 of 278 3/4
Basics of C++, Elementary Data Structures : Arrays, linked lists
8/13/2015 scorm content
Dispose removed node.
General Case
In general removing in middle, can be held in two cases,
In general case, node to be removed is always located between two list nodes. Head and tail
links are not updated in this case.
Such a removal can be done in two steps:
Update next link of the previous node, to point to the next node, relative to the removed
node.
Dispose removed node.
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit2/assets/46.html 141 of 278 4/4
Basics of C++, Elementary Data Structures : Arrays, linked lists
8/13/2015 scorm content
Linked Stacks and Queues: Stack What is Stack?
Stack is a linear data structure which implements data on last in first out criteria.
Here is a c program to implement stack using linked list.
Push:
Push is used to insert operation.
Pop:
Pop is used to delete the element in stack.
Code
Queue
Implement queue using linked list in c program.
Queue is a data structure, that uses First in First out(FIFO) principle.
Queue can be implemented by stack, array and linked list.
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit2/assets/47.html 142 of 278 1/2
Basics of C++, Elementary Data Structures : Arrays, linked lists
8/13/2015 scorm content
Also see c++ program to implement queue using array.
Enqueue:
To add the value in queue.
Dequeue:
Delete the value in queue.
Code
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit2/assets/47.html 143 of 278 2/2
Basics of C++, Elementary Data Structures : Arrays, linked lists
8/13/2015 scorm content
Polynomial Representation and Manipulation using Linked Lists
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
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.
Addition Operation in Polynomial Representation
For adding two polynomials using arrays is straightforward method, since both the arrays may
be added up element wise beginning from 0 to n1, resulting in addition of two polynomials.
Addition of two polynomials using linked list requires comparing the exponents, and wherever
the exponents are found to be same, the coefficients are added up.
For terms with different exponents, the complete term is simply added to the result thereby
making it a part of addition result.
Multiplication Operation in Polynomial Representation
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.
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit2/assets/48.html 144 of 278 1/1
Basics of C++, Elementary Data Structures : Arrays, linked lists
8/13/2015 scorm content
Circular Linked List
Circular linked list is a more complicated linked data structure.
In this the elements can be placed anywhere in the heap memory unlike array which uses
contiguous locations.
Nodes in a linked list are linked together using a next field, which stores the address of the next
node in the next field of the previous node i.e. each node of the list refers to its successor and
the last node points back to the first node unlike singly linked list.
It has a dynamic size, which can be determined only at run time.
Basic Operations
Insert – Inserts a new element at the end of the list.
Delete – Deletes any node from the list.
Find – Finds any node in the list.
Print – Prints the list.
Algorithm
The node of a linked list is a structure with fields data (which stored the value of the node) and
*next (which is a pointer of type node that stores the address of the next node).
Two nodes *start (which always points to the first node of the linked list) and *temp (which is
used to point to the last node of the linked list) are initialized.
Initially temp = start and temp >next = start. Here, we take the first node as a dummy node.
The first node does not contain data, but it used because to avoid handling special cases in
insert and delete functions.
Functions
Insert
This function takes the start node and data to be inserted as arguments.
New node is inserted at the end so, iterate through the list till we encounter the last node.
Then, allocate memory for the new node and put data in it.
Lastly, store the address of the first node (start) in the next field of the new node.
Delete
This function takes the start node (as pointer) and data to be deleted as arguments.
Firstly, go to the node for which the node next to it has to be deleted, If that node points to
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit2/assets/49.html 145 of 278 1/4
Basics of C++, Elementary Data Structures : Arrays, linked lists
8/13/2015 scorm content
NULL (i.e. pointer>next=NULL) then the element to be deleted is not present in the list.
Else, now pointer points to a node and the node next to it has to be removed, declare a
temporary node (temp) which points to the node which has to be removed.
Store the address of the node next to the temporary node in the next field of the node pointer
(pointer>next = temp>next).
Thus, by breaking the link we removed the node which is next to the pointer (which is also
temp).
Because we deleted the node, we no longer require the memory used for it, free() will
reallocate the memory.
Find
This function takes the start node (as pointer) and data value of the node (key) to be found
as arguments.
A pointer start of type node is declared, which points to the head node of the list (node *start
= pointer).
First node is dummy node so, start with the second node.
Iterate through the entire linked list and search for the key.
Until next field of the pointer is equal to start, check if pointer>data = key.
If it is then the key is found else, move to the next node and search (pointer = pointer >
next).
If key is not found return 0, else return 1.
Function takes the start node (as start) and the next node (as pointer) as arguments.
If pointer = start, then there is no element in the list.
Else, print the data value of the node (pointer>data) and move to the next node by
recursively calling the print function with pointer>next sent as an argument.
Performance
The advantage is that we no longer need both a head and tail variable to keep track of the list.
Even if only a single variable is used, both the first and the last list elements can be found in
constant time.
Also, for implementing queues we will only need one pointer namely tail, to locate both head and
tail.
The disadvantage is that the algorithms have become more complicated.
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit2/assets/49.html 146 of 278 2/4
Basics of C++, Elementary Data Structures : Arrays, linked lists
8/13/2015 scorm content
Example
In initially the node value is zero.
After adding value "two" the temp movies one step forward.
Insert(Start,2) A new node with data 2 is inserted and the next field is updated to store the
address of start node.
The next field of previous node is updated to store the address of new node. start temp.
In initially the node value is in "two".
After adding value "six" the temp movies one step forward.
Insert(Start,6) A new node with data 6 is inserted and the next field is updated to store the
address of start node.
The next field of previous node is updated to store the address of new node.
After adding value "one" the temp movies one step forward.
Insert(Start,1) – A new node with data 1 is inserted and the next field is updated to store the
address of start node.
The next field of previous node is updated to store the address of new node.
After adding value "10" the temp movies one step forward.
Insert(Start,10) – A new node with data 6 is inserted and the next field is updated to store the
address of start node.
The next field of previous node is updated to store the address of new node.
After adding value "8" the temp movies one step forward.
Insert(Start,8) A new node with data 6 is inserted and the next field is updated to store the
address of start node.
The next field of previous node is updated to store the address of new node.
Printing the values.
Print(start>next) 2 ,6 ,1 ,10 ,8.
To print start from the first node of the list and move to the next with the help of the address
stored in the next field.
The value 1 is deleted from the circular.
Delete(start,1) A node with data 1 is found and the next field is updated to store the
NULLvalue.
The next field of previous node is updated to store the address of node next to the deleted
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit2/assets/49.html 147 of 278 3/4
Basics of C++, Elementary Data Structures : Arrays, linked lists
8/13/2015 scorm content
node.
The value 10 is found in the circular.
Find(start,10) ‘Element Found’.
Start temp To find, start from the first node of the list and move to the next with the help of
the address stored in the next field.
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit2/assets/49.html 148 of 278 4/4
Basics of C++, Elementary Data Structures : Arrays, linked lists
8/13/2015 scorm content
Doubly Linked Lists
A doubly linked list is a linked list in which every node has a next pointer and a back pointer.
In other words, every node contains the address of the next node (except the last node), and
every node contains the address of the previous node (except the first node).
Operations:
A doubly linked list can be traversed in either direction.
That is, we can traverse the list starting at the first node or, if a pointer to the last node is given,
we can traverse the list starting at the last node.
As before, the typical operations on a doubly linked list are as follows: Initialize the list, destroy
the list, determine whether the list is empty, search the list for a given item, insert an item, delete
an item, and so on.
The following class defines a doubly linked list as an ADT and specifies the basic operations on
a doubly linked list:
Insert – Inserts a new element at the end of the list.
Delete – Deletes any node from the list.
Find – Finds any node in the list.
Print – Prints the list.
Default Constructor
The default constructor initializes the doubly linked list to an empty state.
It sets first and last to NULL and count to 0.
isEmptyList:
This operation returns true if the list is empty; otherwise, it returns false.
The list is empty if the pointer first is NULL.
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit2/assets/50.html 149 of 278 1/4
Basics of C++, Elementary Data Structures : Arrays, linked lists
8/13/2015 scorm content
Destroy the List
This operation deletes all the nodes in the list, leaving the list in an empty state.
We traverse the list starting at the first node and then delete each node.
Furthermore, count is set to 0.
Initialize the List
This operation reinitializes the doubly linked list to an empty state.
This task can be done by using the operation destroy.
The definition of the function initialize List is as follows:
Length of the List
The length of a linked list (that is, how many nodes are in the list) is stored in the variable count.
Therefore, this function returns the value of this variable.
Reverse Print the List
This function outputs the info contained in each node in reverse order.
We traverse the list in reverse order starting from the last node.
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit2/assets/50.html 150 of 278 2/4
Basics of C++, Elementary Data Structures : Arrays, linked lists
8/13/2015 scorm content
Its definition is as follows:
Stacks
A stack is a list of homogenous elements in which the addition and deletion of elements only at
one end, called the top of the stack.
For example, in a cafeteria, the second tray in a stack of trays can be removed only if the first
tray has been removed.
For another example, to get to your favorite computer science book, which is underneath your
math and history books, you must first remove the math and history books.
After removing these books, the computer science book becomes the top book—that is, the top
element of the stack.
A data structure in which the elements are added and removed from one end only; a Last In
First Out (LIFO) data structure.
Now that you know what a stack is, let us see what kinds of operations can be performed on a
stack.
Because new items can be added to the stack, we can perform the add operation, called push,
to add an element onto the stack.
Similarly, because the top item can be retrieved and/or removed from the stack, we can perform
the operation top to retrieve the top element of the stack, and the operation pop to remove the
top element from the stack.
The push, top, and pop operations work as follows: Suppose there are boxes lying on the floor
that need to be stacked on a table.
Queue
A queue is a set of elements of the same type in which the elements are added at one end,
called the back or rear, and deleted from the other end, called the front.
For example, consider a line of customers in a bank, wherein the customers are waiting to
withdraw/deposit money or to conduct some other business.
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit2/assets/50.html 151 of 278 3/4
Basics of C++, Elementary Data Structures : Arrays, linked lists
8/13/2015 scorm content
Each new customer gets in the line at the rear.
Whenever a teller is ready for a new customer, the customer at the front of the line is served.
A data structure in which the elements are added at one end, called the rear, and deleted from
the other end, called the front.
A First In First Out (FIFO) data structure.
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit2/assets/50.html 152 of 278 4/4
UNIT - 3
Abstract Data types Stacks and Queues
Definition of ADT
The word “abstract” refers to the fact that the data and the basic operations defined on it are
being studied independently of how they are implemented.
We think about what can be done with the data, not how it is done.
Abstract data type A data type whose properties (data and operations) are specified
independently of any particular implementation.
The goal in design is to reduce complexity through abstraction.
Solving a problem involves processing data, and an important part of the solution is the careful
organization of the data.
In order to do that, we need to identify:
The collection of data items.
Basic operation that must be performed on them.
Abstract Data Type (ADT): a collection of data items together with the operations on the data.
An ADT consists of a data declaration packaged together with the operations that are
meaningful on the data while embodying the structured principles of encapsulation and data
hiding.
ADT users are NOT concerned with how the task is done but rather what it can do.
An abstract data type is a data declaration packaged together with the operations that are
meaningful for the data type.
We encapsulate the data and the operations on the data, and then hide them from the user.
All references to and manipulation of the data in a data structure are handled through defined
interfaces to the structure.
Let us now define an ADT.
An abstract data type is a data type packaged with the operations that are meaningful for the
data type.
We then encapsulate the data and the operations on the data and hide them from the user.
Abstract data type:
Definition of data.
Definition of operations.
Encapsulation of data and operation.
The term of Data Structure and Abstract Data Type are often used interchangeably.
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit3/assets/2.html 154 of 278 1/2
Abstract Data types Stacks and Queues
8/13/2015 scorm content
However, we use ADT when data is studied at a logical level.
The term data structure refers to a construct in programming language that can be used to store
data.
In computing, we view data from three perspectives.
Application level
View of the data within a particular problem.
Logical level
An abstract view of the data values (the domain) and the set of operations to manipulate
them.
Implementation level
A specific representation of the structure to hold the data items and the coding of the
operations in a programming language.
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit3/assets/2.html 155 of 278 2/2
Abstract Data types Stacks and Queues
8/13/2015 scorm content
Implementation
Computer languages do not provide complex ADT packages.
To create a complex ADT, it is first implemented and kept in a library.
The main purpose of this chapter is to introduce some common userdefined ADTs and their
applications.
However, we also give a brief discussion of each ADT implementation for the interested reader.
We offer the pseudo code algorithms of the implementations as challenging exercises.
An implementation of ADT consists of storage structures to store the data items and algorithms
for basic operation.
An array is a named collection of homogeneous items.
An item′s place within the collection is called an index.
If there is no ordering on the items in the container, we call the container unsorted.
If there is an ordering, we call the container sorted.
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit3/assets/3.html 156 of 278 1/1
Abstract Data types Stacks and Queues
8/13/2015 scorm content
Stack
A stack is a restricted linear list in which all additions and deletions are made at one end, the top.
If we insert a series of data items into a stack and then remove them, the order of the data is
reversed.
This reversing attribute is why stacks are known as last in, first out (LIFO) data structures.
It is an ordered group of homogeneous items of elements.
Elements are added to and removed from the top of the stack (the most recently added items
are at the top of the stack).
The last element to be added is the first to be removed (LIFO:Last In, First Out).
A stack is a list of elements in which an element may be inserted or deleted only at one end,
called TOP of the stack.
The elements are removed in reverse order of that in which they were inserted into the stack.
Operations on Stacks
A stack is an abstract data type in which accesses are made at only one end.
LIFO, which stands for Last In First Out.
The insert is called Push and the delete is called Pop.
There are four basic operations, stack, push, pop and empty, that we define in this chapter.
Push() is the term used to insert/add an element into a stack.
Pop() is the term used to delete/remove an element from a stack.
Other names for stacks are piles and pushdown lists.
There are two ways to represent Stack in memory.
One is using array and other is using linked list.
The push operation
The push operation inserts an item at the top of the stack.
The following shows the format.
Algorithm for push:
PUSH(STACK, TOP, STACKSIZE, ITEM)
[STACK already filled?]
If TOP=STACKSIZE1, then: Print: OVERFLOW / Stack Full, and Return.
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit3/assets/4.html 157 of 278 1/2
Abstract Data types Stacks and Queues
8/13/2015 scorm content
Set TOP:=TOP+1. [Increase TOP by 1.]
Set STACK[TOP]=ITEM. [Insert ITEM in new TOP position.]
RETURN.
To add (push) an element, either:
Increment top and store the element in stk[top], or
Store the element in stk[count] and increment count
Increment TopOfStack by 1.
Set Stack[TopOfStack] = X
The pop operation
The pop operation deletes an item at the top of the stack.
The following shows the format.
Algorithm for push:
POP(STACK, TOP, ITEM)
Stack has an item to be removed.
If top=0
Print: underflow and return
Set item=stack[top]
Set top=top1
Return.
To remove (pop) an element, either:
Get the element from stk[top] and decrement top, or
Decrement count and get the element in stk[count].
Set return value to Stack[TopOfStack]
Decrement TopOfStack by 1.
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit3/assets/4.html 158 of 278 2/2
Abstract Data types Stacks and Queues
8/13/2015 scorm content
Array Implementation
To implement a stack, items are inserted and removed at the same end (called the top).
Efficient array implementation requires that the top of the stack be towards the center of the
array, not fixed at one end.
To use an array to implement a stack, you need both the array itself and an integer.
The integer tells you either:
Which location is currently the top of the stack, or
How many elements are in the stack?
Any list implementation could be used to implement a stack.
Arrays (static: the size of stack is given initially).
Linked lists (dynamic: never become full).
We will explore implementations based on array and linked list.
Let′s see how to use an array to implement a stack first.
Need to declare an array size ahead of time.
Associated with each stack is TopOfStack.
For an empty stack, set TopOfStack to 1.
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit3/assets/5.html 159 of 278 1/1
Abstract Data types Stacks and Queues
8/13/2015 scorm content
Stack Class
Attributes of stack
maxTop: the max size of stack.
top: the index of the top element of stack.
values: point to an array which stores elements of stack.
Operations of Stack
IsEmpty: return true if stack is empty, return false otherwise.
IsFull: return true if stack is full, return false otherwise.
Top: return the element at the top of stack.
Push: add an element to the top of stack.
Pop: delete the element at the top of stack.
DisplayStack: print all the data in the stack.
Initialize Stack
The definition of the function initializeStack is as follows:
Let us consider the initializeStack operation.
Because the value of stackTop indicates whether the stack is empty, we can simply set
stackTop to 0 to initialize the stack.
Empty Stack
The definition of the function isEmptyStack is as follows:
We have seen that the value of stackTop indicates whether the stack is empty.
If stackTop is 0, the stack is empty; otherwise, the stack is not empty.
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit3/assets/6.html 160 of 278 1/2
Abstract Data types Stacks and Queues
8/13/2015 scorm content
Full Stack
The definition of the function isFullStack is as follows:
Next, we consider the operation isFullStack.
It follows that the stack is full if stackTop is equal to maxStackSize.
CopyStack
The definition of the function is as follows:
The function copyStack makes a copy of a stack.
The stack to be copied is passed as a parameter to the function copyStack.
We will, in fact, use this function to implement the copy constructor and overload the
assignment operator.
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit3/assets/6.html 161 of 278 2/2
Abstract Data types Stacks and Queues
8/13/2015 scorm content
Constructor and Destructor
The definitions of the constructor and destructor are as follows:
The functions to implement the constructor and the destructor are straightforward.
The constructor with parameters sets the stack size to the size specified by the user, sets
stackTop to 0, and creates an appropriate array in which to store the stack elements.
If the user does not specify the size of the array in which to store the stack elements, the
constructor uses the default value, which is 100, to create an array of size 100.
The destructor simply deallocates the memory occupied by the array (that is, the stack) and sets
stackTop to 0.
Copy Constructor
The definitions of the copy constructor are as follows:
The copy constructor is called when a stack object is passed as a (value) parameter to a
function.
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit3/assets/7.html 162 of 278 1/2
Abstract Data types Stacks and Queues
8/13/2015 scorm content
It copies the values of the member variables of the actual parameter into the corresponding
member variables of the formal parameter.
Overloading the Assignment Operator(=)
The definition of the function to overload the assignment operator for the class stackType is as
follows:
Recall that for classes with pointer member variables, the assignment operator must be explicitly
overloaded.
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit3/assets/7.html 163 of 278 2/2
Abstract Data types Stacks and Queues
8/13/2015 scorm content
Stack Header File
We will refer to this header file in any program that uses a stack.
Now that you know how to implement the stack operations, you can put the definitions of the
class and the functions to implement the stack operations together to create the stack header
file.
For the sake of completeness, we next describe the header file.
Suppose that the name of the header file containing the definition of the class stackType is
myStack.h.
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit3/assets/8.html 164 of 278 1/1
Abstract Data types Stacks and Queues
8/13/2015 scorm content
Stack ADT
Objects: a finite ordered list with zero or more elements.
Definition:
A list of data items that can only be accessed at one end, called the top of the stack.
Open a header file and name it “ArrayStack.h”.
Write the keyword “class” followed by the name of the class
class ArrayStack { }
Declare Public Operations
Declare member functions for all the public operations that are called for by the ADT.
All member functions after “public:” are accessible by any client in your program wherever there
is an object of this class.
Declare Data Members
Next, decide how to hold the data that the data structure will contain. For example, you could put
it into either an array or a linked list.
Access specifier
All members after “private:” are only accessible to the member functions of this class.
Information hiding
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit3/assets/9.html 165 of 278 1/2
Abstract Data types Stacks and Queues
8/13/2015 scorm content
Data members are always “private” so that the object’s client cannot change the data by
accessing it directly.
Data can be accessed only by using the “public” member functions.
Define the Operations
Define the Operations for implementation process.
Add robustness – use exceptions.
Avoid memory problems.
Implement a copy constructor.
Implement operator=.
Now, decide how to implement the operations.
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit3/assets/9.html 166 of 278 2/2
Abstract Data types Stacks and Queues
8/13/2015 scorm content
Stack Applications
Real life
Pile of books.
Plate trays.
More applications related to computer science
Program execution stack (read more from your text).
Evaluating expressions.
Stack applications can be classified into four broad categories: reversing data, pairing data,
postponing data usage and backtracking steps.
Postfix Expressions Calculator
For example, the expression:
a + b * c
in a postfix expression is:
a b c * +
Scan the expression from left to right.
When an operator is found, back up to get the required number of operands, perform the
operation, and continue.
Algorithm
To simplify the complexity of the function main, we write four functions—evaluateExpression,
evaluateOpr, discardExp, and printResult.
The function evaluateExpression, if possible, evaluates the expression and leaves the result in
the stack.
If the postfix expression is error free, the function printResult outputs the result.
The function evaluateOpr evaluates an operator, and the function discardExp discards the
current expression if there is any error in the expression.
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit3/assets/10.html 167 of 278 1/2
Abstract Data types Stacks and Queues
8/13/2015 scorm content
Function evaluateExpression
The function evaluateExpression evaluates each postfix expression.
Each expression ends with the symbol =.
From this algorithm, it follows that this method has five parameters—a parameter to access the
input file, a parameter to access the output file, a parameter to access the stack, a parameter to
pass a character of the expression, and a parameter to indicate whether there is an error in the
expression.
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit3/assets/10.html 168 of 278 2/2
Abstract Data types Stacks and Queues
8/13/2015 scorm content
STL Class Stack
Stack is an important data structure, the Standard Template Library (STL) provides a class to
implement a stack in a program.
The name of the class defining a stack is stack; the name of the header file containing the
definition of the class stack is stack.
Operations
Size
Returns the actual number of elements in the stack.
Empty
Returns true if the stack is empty, and false otherwise.
Push(item)
Inserts a copy of item into the stack.
Top
Returns the top element of the stack, but does not remove the top element from the stack.
This operation is implemented as a valuereturning function.
Pop
Removes the top element of the stack.
In addition to the operations size, empty, push, top, and pop, the stack container class provides
relational operators to compare two stacks.
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit3/assets/11.html 169 of 278 1/1
Abstract Data types Stacks and Queues
8/13/2015 scorm content
C++ Run Time Stack
The C++ runtime system keeps track of the chain of active functions with a stack.
When a function returns, its frame is popped from the stack and control is passed to the method
on top of the stack.
When a function is called, the runtime system pushes on the stack a frame containing.
Local variables and return value.
Program counter, keeping track of the statement being executed.
Algorithm
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit3/assets/12.html 170 of 278 1/1
Abstract Data types Stacks and Queues
8/13/2015 scorm content
Arraybased Stack
A simple way of implementing the Stack ADT uses an array.
We add elements from left to right.
A variable keeps track of the index of the top element.
The array storing the stack elements may become full.
A push operation will then throw a FullStackException.
Limitation of the arraybased implementation.
Not intrinsic to the Stack ADT.
Algorithm
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit3/assets/13.html 171 of 278 1/1
Abstract Data types Stacks and Queues
8/13/2015 scorm content
Queue
A queue is a first in, first out (FIFO) data structure Items are removed from a queue in the same
order as they were inserted.
Like a stack, a queue is also a list. However, with a queue, insertion is done at one end, while
deletion is performed at the other end.
Accessing the elements of queues follows a First In, First Out (FIFO) order.
Like customers standing in a checkout line in a store, the first customer in is the first
customer served.
Placing an item in a queue is called “insertion or enqueue”, which is done at the end of the
queue called “rear”.
Removing an item from a queue is called “deletion or dequeue”, which is done at the other end
of the queue called “front”.
Some of the applications are : printer queue, keystroke queue, etc.
Queue Operations
initializeQueue—Initializes the queue to an empty state.
isEmptyQueue—Determines whether the queue is empty. If the queue is empty, it returns the
value true; otherwise, it returns the value false.
isFullQueue—Determines whether the queue is full. If the queue is full, it returns the value true;
otherwise, it returns the value false.
front—Returns the front, that is, the first element of the queue. Prior to this operation, the queue
must exist and must not be empty.
back—Returns the last element of the queue. Prior to this operation, the queue must exist and
must not be empty.
addQueue—Adds a new element to the rear of the queue. Prior to this operation, the queue
must exist and must not be full.
deleteQueue—Removes the front element from the queue. Prior to this operation, the queue
must exist and must not be empty.
Basic operations
Primary queue operations: Enqueue and Dequeue.
Like checkout lines in a store, a queue has a front and a rear.
Enqueue
Insert an element at the rear of the queue
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit3/assets/14.html 172 of 278 1/2
Abstract Data types Stacks and Queues
8/13/2015 scorm content
Dequeue
Remove an element from the front of the queue.
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit3/assets/14.html 173 of 278 2/2
Abstract Data types Stacks and Queues
8/13/2015 scorm content
Implementation of Queue
A queue is a first in, first out (FIFO) data structure.
This is accomplished by inserting at one end (the rear) and deleting from the other (the front).
Just as stacks can be implemented as arrays or linked lists, so with queues.
Dynamic queues have the same advantages over static queues as dynamic stacks have over
static stacks.
To insert: put new element in location 4, and set rear to 4.
To delete: take element from location 0, and set front to 1.
There are several different algorithms to implement Enqueue and Dequeue.
Naïve way
When enqueuing, the front index is always fixed and the rear index moves forward in the
array.
When dequeuing, the element at the front the queue is removed. Move all the elements
after it by one position. (Inefficient!!!)
Better way
When an item is enqueued, make the rear index move forward.
When an item is dequeued, the front index moves by one element towards the back of the
queue (thus removing the front item, so no copying to neighboring elements is needed).
Enqueue (ItemType newItem)
Function: Adds newItem to the rear of the queue.
Preconditions: Queue has been initialized and is not full.
Postconditions: newItem is at rear of queue.
Queue Overflow
The condition resulting from trying to add an element onto a full queue.
if(!q.IsFull())
q.Enqueue(item);
Algorithm
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit3/assets/15.html 174 of 278 1/2
Abstract Data types Stacks and Queues
8/13/2015 scorm content
Complexity: O(1)
Dequeue (ItemType& item)
Function: Removes front item from queue and returns it in item.
Preconditions: Queue has been initialized and is not empty.
Postconditions: Front element has been removed from queue and item is a copy of removed
element.
Queue Underflow
The condition resulting from trying to remove an element from an empty queue.
Algorithm
Complexity: O(1)
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit3/assets/15.html 175 of 278 2/2
Abstract Data types Stacks and Queues
8/13/2015 scorm content
Circular Arrays
When an element moves past the end of a circular array, it wraps around to the beginning, e.g.
OOOOO7963 > 4OOOO7963 (after Enqueue(4)).
After Enqueue(4), the rear index moves from 3 to 4.
When a new item is inserted at the rear, the pointer to rear moves upwards.
Similarly, when an item is deleted from the queue the front arrow moves downwards.
After a few insert and delete operations the rear might reach the end of the queue and no more
items can be inserted although the items from the front of the queue have been deleted and
there is space in the queue.
We can treat the array holding the queue elements as circular (joined at the ends).
Elements were added to this queue in the order 11, 22, 33, 44, 55, and will be removed in the
same order.
Use: front = (front + 1) % myQueue.length; and: rear = (rear + 1) % myQueue.length;
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit3/assets/16.html 176 of 278 1/1
Abstract Data types Stacks and Queues
8/13/2015 scorm content
Empty Queue & Full Queue
The queue is empty if count == 0, and the queue is full if count == maxQueueSize.
Empty queue
back = front – 1.
Full queue?
the same!
Reason: n values to represent n+1 states.
If the queue were to become completely full.
If we were then to remove all eight elements, making the queue completely empty.
Algorithm>
Solutions
Use a Boolean variable to say explicitly whether the queue is empty or not.
Make the array of size n+1 and only allow n elements to be stored.
Use a counter of the number of elements in the queue.
Solution #1: Keep an additional variable.
Solution #2: (Slightly more efficient) Keep a gap between elements: consider the queue full when
it has n1 elements.
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit3/assets/17.html 177 of 278 1/1
Abstract Data types Stacks and Queues
8/13/2015 scorm content
Queue Class
Attributes of Queue
front/rear: front/rear index.
counter: number of elements in the queue.
maxSize: capacity of the queue.
values: point to an array which stores elements of the queue.
Operations of Queue
IsEmpty: return true if queue is empty, return false otherwise.
IsFull: return true if queue is full, return false otherwise.
Enqueue: add an element to the rear of queue.
Dequeue: delete the element at the front of queue.
DisplayQueue: print all the data.
Initialize Queue
Initializes queue to empty state.
First element added at the first array position.
Initialize queueFront to zero, queueRear to maxQueueSize one, count to zero.
Queue(int size = 10).
Allocate a queue array of size. By default, size = 10.
Front is set to 0, pointing to the first element of the array.
Rear is set to 1. The queue is empty initially.
The definition of the function initializeQueue is as follows:
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit3/assets/18.html 178 of 278 1/1
Abstract Data types Stacks and Queues
8/13/2015 scorm content
Front & Rear
Front
This operation returns the first element of the queue.
If the queue is nonempty, the element of the queue indicated by the index queueFront is
returned; otherwise, the program terminates.
The definition of the function Front is as follows:
Rear
This operation returns the last element of the queue.
If the queue is nonempty, the element of the queue indicated by the index queueRear is
returned; otherwise, the program terminates.
The definition of the function Rear is as follows:
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit3/assets/19.html 179 of 278 1/1
Abstract Data types Stacks and Queues
8/13/2015 scorm content
Constructor & Destructor
Constructor
To complete the implementation of the queue operations, we next consider the implementation
of the constructor and the destructor.
The constructor gets the maxQueueSize from the user, sets the variable maxQueueSize to the
value specified by the user, and creates an array of size maxQueueSize.
If the user does not specify the queue size, the constructor uses the default value, which is 100,
to create an array of size 100.
The constructor also initializes queueFront and queueRear to indicate that the queue is empty.
Constructor Algorithm
Destructor
The array to store the queue elements is created dynamically.
Therefore, when the queue object goes out of scope, the destructor simply deallocates the
memory occupied by the array that stores the queue elements.
Destructor Algorithm
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit3/assets/20.html 180 of 278 1/1
Abstract Data types Stacks and Queues
8/13/2015 scorm content
Priority Queue
More specialized data structure.
Similar to Queue, having front and rear.
Items are removed from the front.
Items are ordered by key value so that the item with the lowest key (or highest) is always at the
front.
Items are inserted in proper position to maintain the order.
Used in multitasking operating system.
They are generally represented using “heap” data structure.
Insertion runs in O(n) time, deletion in O(1) time.
Queue structure ensures items processed in the order received.
Customers (jobs) with higher priority pushed to the front of the queue.
Implementation
Ordinary linked list.
Keeps items in order from the highest to lowest priority.
Treelike structure.
Very effective.
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit3/assets/21.html 181 of 278 1/1
Abstract Data types Stacks and Queues
8/13/2015 scorm content
Dequeueue
A Dequeueue is a finite sequence of items such that
Given any index, the item in the sequence at that index can be accessed or modified in
constant time.
An insertion or Deletion at the Front or Back of the sequence takes only constant time, on
average.
The Dequeue class is very similar to the vector class.
The Dequeue is an abstract data type that combines the features of a stack and a queue.
The name Dequeue is an abbreviation for doubleended queue.
The C++ standard defines the Dequeue as a fullfledged sequential container that supports
random access.
A Dequeue is a doubleended queue.
Insertions and deletions can occur at either end.
Implementation is similar to that for queues.
Dequeues are not heavily used.
More versatile data structure than stack or queue.
E.g. policybased application (e.g. low priority go to the end, high go to the front).
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit3/assets/22.html 182 of 278 1/1
Abstract Data types Stacks and Queues
8/13/2015 scorm content
Application of Queues: Simulation
Computer Simulation
A technique in which one system models the behavior of another system is called simulation.
Represents objects being studied as data.
Actions implemented with algorithms.
C++ combines data, data operations into a single unit using classes.
Change in simulation results occurs if change in data value or modification of function definitions
occurs.
Queuing systems.
The main goal of the computer simulation is generate results showing the performance of an
existing system and predict performance of a proposed system.
Programming language implements algorithms with functions.
Functions implement object actions.
Objects represented as classes.
Class member variables describe object properties.
Function members describe actions on data.
Queues represent the basic data structure.
Queues of objects are waiting to be served by various servers.
Consist of servers and queues of objects waiting to be served.
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit3/assets/23.html 183 of 278 1/1
Abstract Data types Stacks and Queues
8/13/2015 scorm content
Designing a Queuing System
Object that provides the service.
Object receiving the service .
Time required to serve a customer.
Model system consisting of a list of servers; waiting queue holding the customers to be served.
Number of servers, expected customer arrival time, time between customer arrivals, number of
events affecting system.
Clock implemented as a counter.
Passage of time
Implemented by incrementing counter by one.
Example: run for 100 minutes
Counter starts at one and goes up to 100 using a loop
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit3/assets/24.html 184 of 278 1/1
Abstract Data types Stacks and Queues
8/13/2015 scorm content
Customer
Every customer has a customer number, arrival time, waiting time, transaction time, and
departure time.
If we know the arrival time, waiting time, and transaction time, we can determine the departure
time by adding these three times.
Let us call the class to implement the customer object customerType.
It follows that the class customerType has four member variables: the customerNumber,
arrivalTime, waitingTime, and transactionTime, each of type int.
The basic operations that must be performed on an object of type customerType are as follows:
Set the customer′s number, arrival time, and waiting time;
Increment the waiting time by one clock unit;
Return the waiting time;
Return the arrival time;
Return the transaction time; and return the customer number.
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit3/assets/25.html 185 of 278 1/1
Abstract Data types Stacks and Queues
8/13/2015 scorm content
Server
At any given time unit, the server is either busy serving a customer or is free.
We use a string variable to set the status of the server.
Every server has a timer and because the program might need to know which customer is
served by which server, the server also stores the information of the customer being served.
Thus, three member variables are associated with a server: the status, the transactionTime, and
the currentCustomer.
Some of the basic operations that must be performed on a server are as follows:
Check whether the server is free;
Set the server as free;
Set the server as busy;
Set the transaction time (that is, how long it takes to serve the customer);
Return the remaining transaction time (to determine whether the server should be set to
free);
If the server is busy after each time unit, decrement the transaction time by one time unit;
and so on.
Server List
A server list is a set of servers.
At any given time, a server is either free or busy.
For the customer at the front of the queue, we need to find a server in the list that is free.
If all the servers are busy, the customer must wait until one of the servers becomes free.
Thus, the class that implements a list of servers has two member variables: one to store the
number of servers and one to maintain a list of servers.
Using dynamic arrays, depending on the number of servers specified by the user, a list of
servers is created during program execution.
Some of the operations that must be performed on a server list are as follows:
Return the server number of a free server;
When a customer gets ready to do business and a server is available, set the server to busy;
When the simulation ends, some of the servers might still be busy, so return the number of
busy servers;
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit3/assets/26.html 186 of 278 1/2
Abstract Data types Stacks and Queues
8/13/2015 scorm content
After each time unit, reduce the transactionTime of each busy server by one time unit;
And if the transactionTime of a server becomes zero, set the server to free.
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit3/assets/26.html 187 of 278 2/2
Abstract Data types Stacks and Queues
8/13/2015 scorm content
Waiting Customers Queue
When a customer arrives, he or she goes to the end of the queue.
When a server becomes available, the customer at the front of the queue leaves to conduct the
transaction.
After each time unit, the waiting time of each customer in the queue is incremented by 1.
The ADT queueType designed in this chapter has all the operations needed to implement a
queue, except the operation of incrementing the waiting time of each customer in the queue by
one time unit.
We will derive a class, waitingCustomerQueueType, from the class queueType and add the
additional operations to implement the customer queue.
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit3/assets/27.html 188 of 278 1/1
UNIT - 4
Trees
Introduction
Dynamically organize data so that item insertion, deletion, and lookups are more efficient.
We first introduce some definitions to facilitate our discussion.
Definition: A binary tree, T, is either empty or such that
T has a special node called the root node.
T has two sets of nodes, LT and RT, called the left subtree and right subtree of T,
respectively.
LT and RT are binary trees.
A binary tree can be shown pictorially.
Suppose that T is a binary tree with a root node A.
Let LA denote the left subtree of A and RA denote the right subtree of A.
Now LA and RA are binary trees.
Suppose that B is the root node of LA and C is the root node of RA.
B is called the left child of A; C is called the right child of A.
Furthermore, A is called the parent of B and C.
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit4/assets/2.html 190 of 278 1/1
Trees
8/13/2015 scorm content
Copy Tree
One useful operation on binary trees is to make an identical copy of a binary tree.
A binary tree is a dynamic data structure; that is, memory for its nodes is allocated and de
allocated during program execution.
To make an identical copy of a binary tree, we need to create as many nodes as there are in the
binary tree to be copied.
Moreover, in the copied tree, these nodes must appear in the same order as they are in the
original binary tree.
Given a pointer to the root node of a binary tree, we next describe the function copyTree, which
makes a copy of a given binary tree.
This function is also useful in implementing the copy constructor and overloading the assignment
operator.
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit4/assets/3.html 191 of 278 1/1
Trees
8/13/2015 scorm content
Binary Tree Traversal
The item insertion, deletion, and lookup operations require that the binary tree be traversed.
Thus, the most common operation performed on a binary tree is to traverse the binary tree, or
visit each node of the binary tree.
As you can see from the diagram of a binary tree, the traversal must start at the root node
because there is a pointer to the root node.
In binary tree traversal for each node, we have two choices:
Visit the node first.
Visit the subtrees first.
These choices lead to three different traversals of a binary tree.
Inorder.
Preorder.
Postorder.
Inorder
In an inorder traversal, the binary tree is traversed as follows:
Traverse the left subtree.
Visit the node.
Traverse the right subtree.
Inorder Traversal Pseudocode
This recursive algorithm takes as the input a pointer to a tree and executed inorder traversal
on the tree.
While doing traversal it prints out the key of each node that is visited.
Preorder
In a preorder traversal, the binary tree is traversed as follows:
Visit the node.
Traverse the left subtree.
Traverse the right subtree.
Postorder
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit4/assets/4.html 192 of 278 1/2
Trees
8/13/2015 scorm content
In a postorder traversal, the binary tree is traversed as follows:
Traverse the left subtree.
Traverse the right subtree.
Visit the node.
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit4/assets/4.html 193 of 278 2/2
Trees
8/13/2015 scorm content
Tree Traversal Example
Example 1
Inorder: (left, root, right)
3, 5, 6, 7, 10, 12, 13, 15, 16, 18, 20, 23.
Preorder: (root, left, right)
15, 5, 3, 12, 10, 6, 7, 13, 16, 20, 18, 23.
Postorder: (left, right, root)
3, 7, 6, 10, 13, 12, 5, 18, 23, 20, 16, 15.
Example 2
Given a tree, you are expected to know how to do the in, pre, and postorder traversals.
Example: Write the 3 traversals of the given tree.
Inorder: Chewbacca, Han, Lando, Leia, Luke, Obi, Vader, Yoda.
Preorder: Luke, Han, Chewbacca, Leia, Lando, Vader, Obi, Yoda.
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit4/assets/5.html 194 of 278 1/2
Trees
8/13/2015 scorm content
Postorder: Chewbacca, Lando, Leia, Han, Obi, Yoda, Vader, Luke.
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit4/assets/5.html 195 of 278 2/2
Trees
8/13/2015 scorm content
Sorting Values Using InOrder
The inorder traversal always prints the values in sorted order from smallest to largest.
One application of the inorder traversal is sorting a list.
How long would it take to sort a list?
Each insert operation takes O(h) time.
So doing N inserts would take O(Nh) time.
The inorder traversal is O(N), so building a tree and printing its values in sorted order takes:
O(Nh) + O(N) = O(Nh) time.
Storing Trees Using PreOrder
Suppose
we want
to
transmit
our tree
across the country to another programmer.
Sending the inorder list would tell them the values, but would not communicate how the tree is
built.
Trees are usually stored with the preorder traversal.
Example: All of the tree below have the inorder walk: 1 2 3. But only one of the trees below has
the preorder walk 1 2 3.
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit4/assets/6.html 196 of 278 1/1
Trees
8/13/2015 scorm content
Binary Search Tree: Operations on BST
The following are the operations that are happen on a BST
Searching for a key.
The Maximum and the Minimum.
Insertion.
The Successor and The Predecessor.
Deletion.
Implementing Binary Trees
Let us list various operations that are typically performed on a binary tree:
Determine whether the binary tree is empty.
Search the binary tree for a particular item.
Insert an item in the binary tree.
Delete an item from the binary tree.
Find the height of the binary tree.
Find the number of nodes in the binary tree.
Find the number of leaves in the binary tree.
Traverse the binary tree. Copy the binary tree.
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit4/assets/7.html 197 of 278 1/1
Trees
8/13/2015 scorm content
Binary Search Trees
A special type of binary tree, called a binary search tree.
To visit each node in the binary tree until either the item is found or not.
The entire binary tree because no criteria exist to guide our search.
This case is like an arbitrary linked list where we must start our search at the first node, and
continue looking at each node until either the item is found or the entire list is searched.
Definition: A binary search tree, T, is either empty or the following is true:
T has a special node called the root node.
T has two sets of nodes, LT and RT, called the left subtree and right subtree of T,
respectively.
The key in the root node is larger than every key in the left subtree and smaller than every
key in the right subtree.
LT and RT are binary search trees.
Every binary search tree is a binary tree.
The height of a binary search tree is determined the same way as the height of a binary tree.
Similarly, the operations to find the number of nodes, to find the number of leaves, and to do
inorder, preorder, and postorder traversals of a binary search tree are the same as those for a
binary tree.
Search the binary search tree for a particular item.
Insert an item in the binary search tree.
Delete an item from the binary search tree.
Find the height of the binary search tree.
Find the number of nodes in the binary search tree.
Find the number of leaves in the binary search tree.
Traverse the binary search tree.
Copy the binary search tree.
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit4/assets/8.html 198 of 278 1/1
Trees
8/13/2015 scorm content
Searching for a key
We assume that a key and the subtree in which the key is searched for are given as an input.
We′ll take the full advantage of the BSTproperty.
Suppose we are at a node.
If the node has the key that is being searched for, then the search is over.
Otherwise, the key at the current node is either strictly smaller than the key that is searched for
or strictly greater than the key that is searched for.
If the former is the case, then by the BST property, all the keys in th left subtree are strictly less
than the key that is searched for.
That means that we do not need to search in the left subtree.
Thus, we will examine only the right subtree.
If the latter is the case, by symmetry we will examine only the right subtree.
Here k is the key that is searched for and x is the start node.
BSTSearch(x, k)
1: y ← x
2: while y ≠nil do
3: if key[y] = k then return y
4: else if key[y] < k then y ← right[y]
5: else y ← left[y]
6: return (“NOT FOUND”)
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit4/assets/9.html 199 of 278 1/1
Trees
8/13/2015 scorm content
The Maximum and the Minimum
To find the minimum identify the leftmost node, i.e. the farthest node you can reach by following
only left branches.
To find the maximum identify the rightmost node, i.e. the farthest node you can reach by
following only right branches.
BSTMinimum(x)
1: if x = nil then return (“Empty Tree”)
2: y ← x
3: while left[y] ≠ nil do y ← left[y]
4: return (key[y])
BSTMaximum(x)
1: if x = nil then return (“Empty Tree”)
2: y ← x
3: while right[y] ≠ nil do y ← right[y]
4: return (key[y])
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit4/assets/10.html 200 of 278 1/1
Trees
8/13/2015 scorm content
The Successor and the Predecessor
The successor (respectively, the predecessor) of a key k in a search tree is the smallest
(respectively, the largest) key that belongs to the tree and that is strictly greater than
(respectively, less than) k.
The idea for noding the successor of a given node x.
If x has the right child, then the successor is the minimum in the right subtree of x.
Otherwise, the successor is the parent of the farthest node that can be reached from x by
following only right branches backward.
BSTSuccessor(x)
1: if right[x] ≠ nil then
2: { y ← right[x]
3: while left[y] ≠ nil do y ← left[y]
4: return (y) }
5: else
6: { y ← x
7: while right[p[x]] = x do y ← p[x]
8: if p[x] ≠ nil then return (p[x])
9: else return (“NO SUCCESSOR”) }
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit4/assets/11.html 201 of 278 1/1
Trees
8/13/2015 scorm content
Search
The function search searches the binary search tree for a given item.
If the item is found in the binary search tree, it returns true; otherwise, it returns false.
Because the pointer root points to the root node of the binary search tree.
A pointer, say current, to traverse the binary search tree.
The pointer current is initialized to root.
If the binary search tree is nonempty, we first compare the search item with the info in the
root node.
If they are the same, we stop the search and return true.
Search ends at the node containing the search item; otherwise, the search ends at an empty
subtree.
if root is NULL
Cannot search an empty tree, returns false.
else
{
current = root;
while (current is not NULL and not found)
if (current>info is the same as the search item)
set found to true;
else if(current>info is greater than the search item)
follow the llink of current
else
follow the rlink of current
}
This pseudocode algorithm translates into the following C++ function:
template <class elemType>
bool bSearchTreeType<elemType>::
search(const elemType& searchItem) const
{
binaryTreeNode<elemType> *current;
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit4/assets/12.html 202 of 278 1/1
Trees
8/13/2015 scorm content
Insert
After inserting an item in a binary search tree, the resulting binary tree must also be a binary
search tree.
To insert a new item, first we search the binary search tree and find the place where the new
item is to be inserted.
The search algorithm is similar to the search algorithm of the function search.
Traverse the binary search tree with two pointers.
A pointer, say current, to check the current node and a pointer, say trailCurrent, pointing to the
parent of current.
Duplicate items are not allowed, our search must end at an empty subtree.
Then use the pointer trailCurrent to insert the new item at the proper place.
The item to be inserted, insertItem, is passed as a parameter to the function insert.
template <class elemType>
void bSearchTreeType<elemType>::insert(const elemType& insertItem)
{
binaryTreeNode<elemType> *current; //pointer to traverse the tree
binaryTreeNode<elemType> *trailCurrent; //pointer behind current
binaryTreeNode<elemType> *newNode; //pointer to create the node
newNode = new binaryTreeNode<elemType>;
assert(newNode != NULL);
newNode>info = insertItem;
newNode>llink = NULL;
newNode>rlink = NULL;
if (root == NULL)
root = newNode;
else
{
current = root;
while (current != NULL)
{
trailCurrent = current;
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit4/assets/13.html 203 of 278 1/1
Trees
8/13/2015 scorm content
Delete
As before, first we search the binary search tree to find the node to be deleted.
To help you better understand the delete operation the function to delete an item from the binary
search tree after deleting the desired item (if it exists in the binary search tree), the resulting tree
must be a binary search tree.
The delete operation has four cases, as follows:
Case 1: The node to be deleted has no left and right subtrees; that is, the node to be deleted
is a leaf. For example, the node with info 45 is a leaf.
Case 2: The node to be deleted has no left subtree; that is, the left subtree is empty, but it
has a nonempty right subtree. For example, the left subtree of node with info 40 is empty and
its right subtree is nonempty.
template <class elemType>
void bSearchTreeType<elemType>::deleteFromTree
(binaryTreeNode<elemType>* &p)
{
binaryTreeNode<elemType> *current;//pointer to traverse the tree
binaryTreeNode<elemType> *trailCurrent; //pointer behind current
binaryTreeNode<elemType> *temp; //pointer to delete the node
if (p == NULL)
cerr << "Error: The node to be deleted is NULL." << endl;
else if(p>llink == NULL && p>rlink == NULL)
{
temp = p;
p = NULL;
delete temp;
}
else if(p>llink == NULL)
{
temp = p;
p = temp>rlink;
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit4/assets/14.html 204 of 278 1/1
Trees
8/13/2015 scorm content
Non recursive Binary Tree Traversal Algorithms
Traverse a binary tree using the inorder, preorder, and postorder methods.
Construct a binary tree.
Insert an item in a binary tree.
Delete an item from a binary tree.
The traversal algorithms
Inorder.
Preorder.
Postorder.
Nonrecursive Inorder Traversal
In the inorder traversal of a binary tree, for each node
The left subtree is visited first.
Then the node, and then the right subtree.
It follows that in an inorder traversal, the first node visited is the leftmost node of the binary tree.
For example, in the binary tree in Figure, the leftmost node is the node with info 28.
To get to the leftmost node of the binary tree,
Start by traversing the binary tree at the root node and then follow the left link of each node
until the left link of a node becomes null.
Back up to the parent node, visit the node, and then move to the right node.
Links go in only one direction, to get back to a node.
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit4/assets/15.html 205 of 278 1/4
Trees
8/13/2015 scorm content
The nodes must be backtracked in the order they were traversed.
It follows that while backtracking, the nodes must be visited in a lastin, firstout manner.
This can be done by using a stack.
We therefore, save a pointer to a node in a stack. The general algorithm is as follows:
template <class elemType>
void binaryTreeType<elemType>::nonRecursiveInTraversal() const
{
stackType<binaryTreeNode<elemType>* > stack;
binaryTreeNode<elemType> *current;
current = root;
while ((current != NULL) || (!stack.isEmptyStack()))
if (current != NULL)
{
stack.push(current);
current = current>llink;
}
else
{
current = stack.top();
Nonrecursive Preorder Traversal
In a preorder traversal of a binary tree, for each node,
First the node is visited,
Then the left subtree is visited, and
Then the right subtree is visited.
An inorder traversal, after visiting a node and before moving to the left subtree,
Save a pointer to the node so that after visiting the left subtree,
Visit the right subtree.
The general algorithm is as follows:
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit4/assets/15.html 206 of 278 2/4
Trees
8/13/2015 scorm content
1. current = root; //start the traversal at the root node
2. while (current is not NULL or stack is nonempty)
if (current is not NULL)
{
visit current node;
push current into stack;
current = current>llink;
}
else
{
pop stack into current;
current = current>rlink; //prepare to visit the
//right subtree
}
The following function implements the nonrecursive preorder traversal algorithm:
Nonrecursive Postorder Traversal
In a postorder traversal of a binary tree, for each node,
First the left subtree is visited,
Then the right subtree is visited, and
Then the node is visited.
As in the case of an inorder traversal, in a postorder traversal,
The first node visited is the leftmost node of the binary tree.
For each node the left and right subtrees are visited before visiting the node.
We must indicate to the node whether the left and right subtrees have been visited.
After visiting the left subtree of a node and before visiting the node, wemust visit its right subtree.
Therefore, after returning from a left subtree, we must tell the node that the right subtree needs
to be visited, and after visiting the right subtree we must tell the node that it can now be visited.
The general algorithm is as follows:
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit4/assets/15.html 207 of 278 3/4
Trees
8/13/2015 scorm content
1. current = root; //start the traversal at the root node
2. v = 0;
3. if (current is NULL)
the binary tree is empty
4. if (current is not NULL)
a. push current into stack;
b. push 1 into stack;
c. current = current>llink;
d. while (stack is not empty)
if (current is not NULL and v is 0)
{
push current and 1 into stack;
current = current>llink;
}
else
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit4/assets/15.html 208 of 278 4/4
Trees
8/13/2015 scorm content
Binary Tree Traversal and Functions as Parameters
Suppose that you have stored employee data in a binary search tree, and at the end of the year
pay increases or bonuses are to be awarded to each employee.
This task requires that each node in the binary search tree be visited and that the salary of each
employee be updated.
However, in these traversal algorithms
Inorder,
Preorder, and
Postorder.
Whenever we visited a node, for simplicity and for illustration purposes, we only output the data
contained in each node.
How do we use a traversal algorithm to visit each node and update the data in each node?
One way to do so is to first create another binary search tree in which the data in each node is
the updated data of the original binary search tree, and then destroy the old binary search tree.
In C++, a function name without any parentheses is considered a pointer to the function.
To specify a function as a formal parameter to another function.
We specify the function type, followed by the function name as a pointer, followed by the
parameter types of the function.
The statement in Line 1 declares fParamFunc1 to be a function that takes as a parameter any
void function that has one value parameter of type int.
The statement in Line 2 declares fParamFunc2 to be a function that takes as a parameter any
void function that has one reference parameter of type elemType002E.
We can now rewrite the inorder traversal function of the class binaryTreeType.
Alternatively, we can overload the existing inorder traversal functions.
To further illustrate function overloading, we will overload the inorder traversal functions.
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit4/assets/16.html 209 of 278 1/1
Trees
8/13/2015 scorm content
Representations & Applications
Arrays can be used to represent complete binary trees.
A complete binary tree, all of the depths are full, except perhaps for the deepest.
At the deepest depth, the nodes are as far left as possible.
For example, below is a complete binary tree with 9 nodes; each node contains a character.
In this example, the first 7 nodes completely fill the levels at depth 0 (the root), depth 1 (the root
′s children), and depth 2.
There are 2 nodes at depth 3, and these are as far left as possible.
There are several reasons why the array representation is convenient:
The data from the root always appears in the [0] component of the array.
Suppose that the data for a nonroot appears in component [i] of the array.
Then the data for its parent is always at location [(i1)/2] (using integer division).
Suppose that the data for a node appear in component [i] of the array.
Then its children (if they exist) always have their data at these locations:
Left child at component [2i+1];
Right child at component [2i+2].
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit4/assets/17.html 210 of 278 1/1
Trees
8/13/2015 scorm content
A Class for Binary Tree Nodes
A binary tree can be represented by its individual nodes.
Each node will contain references to its left child and right child.
The node also has at least one instance variable to hold some data.
An entire tree is represented as a reference to the root node.
Preorder Traversal.
void Preorder (BTNode root)
{
// Not all nodes have one or both children.
// Easiest to deal with this once
// Also covers the case fo an empty tree
if (root == null)
return;
// Visit the root, perhaps to print it
System.out.println (root.data);
// Traverse the left subtree
Preorder (root.left);
// Traverse the right subtree
Preorder (root.right);
}
The preorder traversal of the tree above is: A B D E C F H I J G.
Inorder Traversal.
void Inorder (BTNode root)
{
// Not all nodes have one or both children.
// Easiest to deal with this once
// Also covers the case fo an empty tree
if (root == null)
return;
// Traverse the left subtree
Inorder (root.left);
// Visit the root, perhaps to print it
System.out.println (root.data);
// Traverse the right subtree
Inorder (root.right);
}
The inorder traversal of the tree above is: D B E A I H J F C G
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit4/assets/18.html 211 of 278 1/2
Trees
8/13/2015 scorm content
Postorder Traversal.
void Postorder (BTNode root)
{
// Not all nodes have one or both children.
// Easiest to deal with this once
// Also covers the case fo an empty tree
if (root == null)
return;
// Traverse the left subtree Postorder (root.left);
// Traverse the right subtree Postorder (root.right);
// Visit the root, perhaps to print it
System.out.println (root.data);
}
The postorder traversal of the tree above is: D E B I J H F G C A.
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit4/assets/18.html 212 of 278 2/2
Trees
8/13/2015 scorm content
A More General BTNode
For a more general purpose, we can redefine the class BTNode.
Such that each node could hold data that is a Java Object.
This way, we will be able to use BTNode to organize many different types of data into tree
structures (similar to the way we use Node to organize data into linked lists in our previous
assignments).
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit4/assets/19.html 213 of 278 1/1
Trees
8/13/2015 scorm content
Binary Search
For many tasks, we need to arrange things in an order proceeding from smaller to larger.
We can take the advantage of the order to store the elements in the nodes of a binary tree to
maintain a desired order and to find elements easily.
One of this kind of trees is called binary search tree.
A binary search tree has the following 2 characteristics for every node n in the tree:
Every element in n′s left subtree is less or equal to the element in node n.
Every element in n′s right subtree is greater than the element in node n.
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit4/assets/20.html 214 of 278 1/1
Trees
8/13/2015 scorm content
Heaps
A heap is a binary tree where the elements are arranged in a certain order proceeding from
smaller to larger.
In this way, a heap is similar to a binary search tree (discussed previously), but the arrangement
of the elements in a heap follows rules that are different from a binary search tree:
In a heap, the element contained by each node is greater than or equal to the elements of that
node′s children.
The tree is a complete binary tree, so that every level except the deepest must contain as many
nodes as possible; and at the deepest level, all the nodes are as far left as possible.
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit4/assets/21.html 215 of 278 1/1
Trees
8/13/2015 scorm content
Trees Representation
Advantages of linear representation:
Simplicity.
Given the location of the child (say, k), the location of the parent is easy to determine (k / 2).
Disadvantages of linear representation:
Additions and deletions of nodes are inefficient, because of the data movements in the array.
Space is wasted if the binary tree is not complete.
That is, the linear representation is useful if the number of missing nodes is small.
Note that linear representation of a binary tree can be implemented by means of a linked list
instead of an array.
For example, we can use the Positional.
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit4/assets/22.html 216 of 278 1/1
Trees
8/13/2015 scorm content
AVL (HeightBalanced) Trees
The performance of the search algorithm on a binary search tree depends on how the binary
tree is built.
The shape of the binary search tree depends on the data set. If the data set is sorted.
This section describes a special type of binary search tree, called the AVL tree (also called the
heightbalanced tree) in which the resulting binary search is nearly balanced.
AVL trees are due to the mathematicians G. M. Adel´sonVel´skii and E. M. Landis and are so
named in their honor.
The methods of building such binary trees were given by them in 1962.
We begin by defining the following terms.
Definition: A perfectly balanced binary tree is a binary tree such that
The heights of the left and right subtrees of the root are equal.
The left and right subtrees of the root are perfectly balanced binary trees.
Let T be a binary tree and x be a node in T.
If T is perfectly balanced, then from the definition of the perfectly balanced tree, it follows that
the height of the left subtree of x is the same as the height of the right subtree of x.
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit4/assets/23.html 217 of 278 1/1
Trees
8/13/2015 scorm content
Insertion
To insert an item in an AVL tree, first we search the tree and find the place where the new item
is to be inserted.
Because an AVL tree is a binary search tree, to find the place for the new item we can search
the AVL tree using a search algorithm similar to the search algorithm designed for binary search
trees.
If the item to be inserted is already in the tree, the search ends at a nonempty subtree. Because
duplicates are not allowed, in this case we can output an appropriate error message.
Suppose that the item to be inserted is not in the AVL tree.
Then, the search ends at an empty subtree and we insert the item in that subtree.
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit4/assets/24.html 218 of 278 1/1
Trees
8/13/2015 scorm content
Conversion of Forest into Tree
A natural onetoone relationship between the tree or forest binary tree.
A forest or a tree can be uniquely corresponds to a binary tree; the contrary, any binary tree can
be uniquely corresponds to a forest or a tree.
Each node in the tree only up to a leftmost child (the eldest son) and a right neighbor brothers.
According to this relationship it is natural to be able to convert the tree into a corresponding
binary tree.
On each node, in addition to retain their eldest son connection, remove the node connections
with other children.
Binary tree to tree, forest conversion to convert binary tree to tree and forest natural way:
If node x is the left child of parents y, put x′s right child.
The right child of the right child, ..., y connection link, and finally removed the right of all parents
to child connection.
Converted into a binary tree.
To convert a binary tree is as follows:
The tree, plus a connection between all neighboring brothers.
For each node in the tree, just keep it between the first child node with the connection, delete
the connection between it and the other children nodes.
To the axis of the root node of the tree, the tree will rotate clockwise 45 °, so that the
structure structured.
Forest converted to binary
The forest is converted to a binary tree is as follows:
Per tree in the forest is converted into the corresponding binary tree.
A binary tree does not move, beginning from the second binary trees, followed by a binary
tree to the root of the root node of a binary tree as a former right child nodes, when all the
binary tree together, then the resulting Binary Tree is a binary tree from the forest converted.
Binary tree or restore forest.
Binary tree or forest restore process is as follows:
If a node is the left child of its parent, then the right child node, the right child with the right
child ...... both parents of this node with connections to link.
Delete the original binary tree node and the right of all parents of the child node connection.
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit4/assets/25.html 219 of 278 1/2
Trees
8/13/2015 scorm content
Consolidation of (1), the resulting (2) twotree or forest, making it clear hierarchy.
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit4/assets/25.html 220 of 278 2/2
Trees
8/13/2015 scorm content
AVL Tree Rotations
We now describe the reconstruction procedure, called rotating the tree.
There are two types of rotations: left rotation and right rotation. Suppose the rotation occurs at a
node x.
If it is a left rotation, then certain nodes from the right subtree of x move to its left subtree; the
root of the right subtree of x becomes the new root of the reconstructed subtree.
Similarly, if it is a right rotation at x, certain nodes from the left subtree of x move to its right
subtree; the root of the left subtree of x becomes the new root of the reconstructed subtree.
The subtree at node a is still an AVL tree, but the balance criteria is violated at the root node.
We note the following in this tree. Because the tree is a binary search tree,
Every key in subtree T1 is smaller than the key in node a.
Every key in subtree T2 is larger than the key in node a.
Every key in subtree T2 is smaller than the key in node b.
Therefore,
We make T2 (the right subtree of node a) the left subtree of node b.
We make node b the right child of node a.
Node a becomes the root of the reconstructed tree, as shown in Figure.
The dotted rectangle shows that a new item is inserted in the subtree, causing the subtree to
grow in height.
All keys in T3 are smaller than the key in node c.
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit4/assets/26.html 221 of 278 1/2
Trees
8/13/2015 scorm content
All keys in T3 are larger than the key in node b.
All keys in T2 are smaller than the key in node b.
All keys in T2 are larger than the key in node a.
After insertion, the subtrees with root nodes a and b are still AVL trees.
The balance criteria is violated at the root node, c, of the tree.
The balance factors of node c, bf(c) ¼ 1, and node a, bf(a) ¼ 1 are opposite.
Then, the subtree with root node x requires either a single or a double rotation.
Suppose that the balance factor of the node x and the balance factor of the root node of the
higher subtree of x have the same sign, that is, both positive or both negative.
If these balance factors are positive, make a single left rotation at x.
The new item was inserted in the right subtree of x, causing the height of the right subtree
to increase in height, which in turn violated the balance criteria at x.)
If these balance factors are negative, make a single right rotation at x. (Prior to insertion,
the left right subtree of x was higher than its right subtree.
The new item was inserted in the left subtree of x, causing the height of the left subtree to
increase in height, which in turn violated the balance criteria at x.)
Suppose that the balance factor of the node x and the balance factor of the higher subtree of
x are opposite in sign.
To implement both rotations, we next write the C++ functions, balanceFromLeft and
balanceFromRight, which are used to reconstruct the tree at a particular node.
The pointer of the node where reconstruction occurs is passed as a parameter to this function.
These functions use the functions rotateToLeft and rotateToRight to reconstruct the tree, and
also adjust the balance factors of the nodes affected by the reconstruction.
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit4/assets/26.html 222 of 278 2/2
Trees
8/13/2015 scorm content
Deletion from AVL Trees
To delete an item from an AVL tree, first we find the node containing the item to be deleted.
The following four cases arise:
Case 1: The node to be deleted is a leaf.
Case 2: The node to be deleted has no right child, that is, its right subtree is empty.
Case 3: The node to be deleted has no left child, that is, its left subtree is empty.
Case 4: The node to be deleted has a left child and a right child.
Cases 1–3 are easier to handle than Case 4.
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit4/assets/27.html 223 of 278 1/1
Trees
8/13/2015 scorm content
Analysis: AVL Trees
Consider all possible AVL trees of height h.
Let Th be an AVL tree of height h such that Th has the fewest number of nodes.
Let Thl denote the left subtree of Th and Thr denote the right subtree of Th.
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit4/assets/28.html 224 of 278 1/1
Trees
8/13/2015 scorm content
BTrees
The performance of the search depends on the height of the tree.
Btrees in which the leaves are on the same level and are not too far from the root.
Definition: (mway search tree) An mway search tree is a tree in which each node has at most
m children, and if the tree is nonempty.
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit4/assets/29.html 225 of 278 1/1
UNIT - 5
Searching, sorting and Complexity
Selection Sort
Selection sort is one of the O(n 2 ) sorting algorithms, which makes it quite inefficient for sorting
large data volumes.
Selection sort is notable for its programming simplicity and it can over perform other sorts in
certain situations.
The complexity for selection sort is O(n 2 ).
It is in inefficient for sorting large data volumes.
Algorithm
Selection Sort algorithm is quite simple.
Two array will be used for sorting.
One for sorting another for unsorted array.
At every step, algorithm finds minimal element in the unsorted part and adds it to the end of the
sorted one.
When unsorted part becomes empty, algorithm stops.
When algorithm sorts an array, it swaps first element of unsorted part with minimal element and
then it is included to the sorted part.
This implementation of selection sort in not stable.
In case of linked list is sorted, and, instead of swaps, minimal element is linked to the unsorted
part, selection sort is stable.
Example
Let us see an example of sorting an array to make the idea of selection sort clearer:
Example
Sort {5, 1, 12, 5, 16, 2, 12, 14} using selection sort.
The image shows the example for selection sort.
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit5/assets/2.html 227 of 278 1/3
Searching, sorting and Complexity
8/13/2015 scorm content
Finding the smallest value in one array and paste it in another array.
Next swap 5 to 5
Compare 5 and 1
Finding the smallest value
Swap 2 to 12
Compare 2 and 5
16 to 12
swap 16 to 12
swap 16 to 14
Once un sorted array is empty the algorithm stops.
Code snippets
The following code describes flow of steps for selection sort.
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit5/assets/2.html 228 of 278 2/3
Searching, sorting and Complexity
8/13/2015 scorm content
void selectionSort(int arr[], int n) {
int i, j, minIndex, tmp;
for (i = 0; i < n 1; i++)
{
minIndex = i;
for (j = i + 1; j < n; j++)
if (arr[j] < arr[minIndex])
minIndex = j;
if (minIndex != i) {
tmp = arr[i];
arr[i] = arr[minIndex];
arr[minIndex] = tmp;
}
}
In snippets uses array named arr[] to sort the values.
The integer values i, j, minindex, tmp are the variables used for sorting.
1st for loop is used to travel the unsorted values.
Complexity analysis
Selection sort stops, when unsorted part becomes empty.
As we know, on every step number of unsorted elements decreased by one.
Therefore, selection sort makes n steps of outer loop, before stop.
Every step of outer loop requires finding minimum in unsorted part. Summing up, n + (n 1) + (n
2) + ... + 1, results in O(n 2 ) number of comparisons.
Number of swaps may vary from zero (in case of sorted array) to n 1 (in case array was sorted
in reversed order), which results in O(n) number of swaps.
Overall algorithm complexity is O(n 2 ).
That selection sort requires n 1 number of swaps at most, makes it very efficient in situations,
when write operation is significantly more expensive, than read operation.
The worst complexity in selection sort is O(n 2 ).
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit5/assets/2.html 229 of 278 3/3
Searching, sorting and Complexity
8/13/2015 scorm content
Insertion Sort
Insertion sort belongs to the O(n 2 ) sorting algorithms.
Unlike many sorting algorithms with quadratic complexity, it is actually applied in practice for
sorting small arrays of data.
For instance, it is used to improve quick sort routine.
Some sources notice, that people use same algorithm ordering items, for example, hand of
cards.
Algorithm
Array is imaginary divided into two parts sorted one and unsorted one.
At the beginning, sorted part is empty, while unsorted one contains whole array.
At every step, algorithm finds minimal element in the unsorted part and adds it to the end of the
sorted one.
When unsorted part becomes empty, algorithm stops.
When algorithm sorts an array, it swaps first element of unsorted part with minimal element and
then it is included to the sorted part.
This implementation of selection sort in not stable.
In case of linked list is sorted, and, instead of swaps, minimal element is linked to the unsorted
part, selection sort is stable.
Example
Let us see an example of insertion sort routine to make the idea of algorithm clearer.
Example
Sort {7, 5, 2, 16, 4} using insertion sort.
The example explains step by step for selection sort.
For each iteration one number should be sorted.
The iteration should be the number of numbers to sorted.
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit5/assets/3.html 230 of 278 1/4
Searching, sorting and Complexity
8/13/2015 scorm content
The ideas of insertion
The main operation of the algorithm is insertion.
The task is to insert a value into the sorted part of the array.
Let us see the variants of how we can do it.
"Sifting down" using swaps
The simplest way to insert next element into the sorted part is to sift it down, until it occupies
correct position.
Initially the element stays right after the sorted part.
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit5/assets/3.html 231 of 278 2/4
Searching, sorting and Complexity
8/13/2015 scorm content
At each step algorithm compares the element with one before it and, if they stay in reversed
order, swap them. Let us see an illustration.
Shifting Instead of Swapping
It is the most commonly used modification of the insertion sort.
We can modify previous algorithm, so it will write sifted element only to the final correct position.
Let us see an illustration.
Complexity analysis
Insertion sort′s overall complexity is O(n 2 ) on average, regardless of the method of insertion.
On the almost sorted arrays insertion sort shows better performance, up to O(n) in case of
applying insertion sort to a sorted array.
Number of writes is O(n 2 ) on average, but number of comparisons may vary depending on the
insertion algorithm.
It is O(n 2 ) when shifting or swapping methods are used and O(n log n) for binary insertion sort.
From the point of view of practical application, an average complexity of the insertion sort is not
so important.
As it was mentioned above, insertion sort is applied to quite small data sets.
Therefore, first of all, a "practical performance" should be considered.
In practice insertion sort outperforms most of the quadratic sorting algorithms, like selection sort
or bubble sort.
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit5/assets/3.html 232 of 278 3/4
Searching, sorting and Complexity
8/13/2015 scorm content
Code snippets
We show the idea of insertion with shifts in Java implementation and the idea of insertion using
swaps in the C++ code snippet.
The snippets shows how insertion sorting is working.
void insertionSort(int arr[], int length) {
int i, j, tmp;
for (i = 1; i < length; i++) {
j = i;
while (j > 0 && arr[j 1] > arr[j]) {
tmp = arr[j];
arr[j] = arr[j 1];
arr[j 1] = tmp;
j;
}
}
}
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit5/assets/3.html 233 of 278 4/4
Searching, sorting and Complexity
8/13/2015 scorm content
Bubble Sort
Bubble sort is one of the simplest algorithm for sorting.
It is used in practice once in a blue moon and its main application is to make an introduction to
the sorting algorithms.
Bubble sort belongs to O(n2) sorting algorithms, which makes it quite inefficient for sorting large
data volumes.
Bubble sort is stable and adaptive.
Algorithm
Compare each pair of adjacent elements from the beginning of an array and, if they are in
reversed order, swap them.
If at least one swap has been done, repeat step 1.
You can imagine that on every step big bubbles float to the surface and stay there.
At the step, when no bubble moves, sorting stops.
Let us see an example of sorting an array to make the idea of bubble sort clearer.
Example
Sort {5, 1, 12, 5, 16} using bubble sort.
Complexity analysis
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit5/assets/4.html 234 of 278 1/3
Searching, sorting and Complexity
8/13/2015 scorm content
Average and worst case complexity of bubble sort is O(n 2 ).
Also, it makes O(n 2 ) swaps in the worst case.
Bubble sort is adaptive.
It means that for almost sorted array it gives O(n) estimation.
Avoid implementations, which don′t check if the array is already sorted on every step.
This check is necessary, in order to preserve adaptive property.
Turtles and rabbits
One more problem of bubble sort is that its running time badly depends on the initial order of the
elements.
Big elements (rabbits) go up fast, while small ones (turtles) go down very slow.
This problem is solved in the Cocktail sort.
Turtle example
Thought, array {2, 3, 4, 5, 1} is almost sorted, it takes O(n 2 ) iterations to sort an array.
Element {1} is a turtle.
Rabbit example
Array {6, 1, 2, 3, 4, 5} is almost sorted too, but it takes O(n) iterations to sort it.
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit5/assets/4.html 235 of 278 2/3
Searching, sorting and Complexity
8/13/2015 scorm content
Element {6} is a rabbit.
This example demonstrates adaptive property of the bubble sort.
Code snippets
There are several ways to implement the bubble sort.
Notice, that "swaps" check is absolutely necessary, in order to preserve adaptive property.
The code explains the step by step process of bubble sort.
void bubbleSort(int arr[], int n) {
bool swapped = true;
int j = 0;
int tmp;
while (swapped) {
swapped = false;
j++;
for (int i = 0; i < n j; i++) {
if (arr[i] > arr[i + 1]) {
tmp = arr[i];
arr[i] = arr[i + 1];
arr[i + 1] = tmp;
swapped = true;
}
}
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit5/assets/4.html 236 of 278 3/3
Searching, sorting and Complexity
8/13/2015 scorm content
Quicksort
Quicksort is a fast sorting algorithm, which is used not only for educational purposes, but widely
applied in practice.
On the average, it has O(n log n) complexity, making quicksort suitable for sorting big data
volumes.
The idea of the algorithm is quite simple and once you realize it, you can write quicksort as fast
as bubble sort.
It divides the objects into two to for every iteration.
Algorithm
The divideandconquer strategy is used in quick sort.
Below the recursion step is described:
Choose a pivot value
We take the value of the middle element as pivot value, but it can be any value, which is in
range of sorted values, even if it doesn′t present in the array.
Partition
Rearrange elements in such a way, that all elements which are lesser than the pivot go to
the left part of the array and all elements greater than the pivot, go to the right part of the
array.
Values equal to the pivot can stay in any part of the array. Notice, that array may be
divided in nonequal parts.
Sort both parts
Apply quicksort algorithm recursively to the left and the right parts.
Partition algorithm in detail
There are two indices i and j and at the very beginning of the partition algorithm i points to the
first element in the array and j points to the last one.
Then algorithm moves i forward, until an element with value greater or equal to the pivot is
found.
Index j is moved backward, until an element with value lesser or equal to the pivot is found.
If i ≤ j then they are swapped and i steps to the next position (i + 1), j steps to the previous one (j
1).
Algorithm stops, when i becomes greater than j.
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit5/assets/5.html 237 of 278 1/3
Searching, sorting and Complexity
8/13/2015 scorm content
After partition, all values before ith element are less or equal than the pivot and all values after
jth element are greater or equal to the pivot.
Example
Example. Sort {1, 12, 5, 26, 7, 14, 3, 7, 2} using quick sort.
{1, 12, 5, 26, 7, 14, 3, 7, 2}Unsorted Array.
At the beginning 7 is the pivot value.
As per the algorithm the steps moves.
Notice, that we show here only the first recursion step, in order not to make example too
long. But, in fact, {1, 2, 5, 7, 3} and {14, 7, 26, 12} are sorted then recursively.
Complexity analysis
On the average quick sort has O(n log n) complexity, but strong proof of this fact is not trivial and
not presented here. Still, you can find the proof in.
In worst case, quick sort runs O(n 2 ) time, but on the most "practical" data it works just fine and
outperforms other O(n log n) sorting algorithms.
Code snippets
Partition algorithm is important per se, therefore it may be carried out as a separate function.
The code for C++ contains solid function for quick sort, but Java code contains two separate
functions for partition and sort, accordingly.
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit5/assets/5.html 238 of 278 2/3
Searching, sorting and Complexity
8/13/2015 scorm content
The snippets show how quick sort is working.
It should be implemented using C++.
The left and right are the pointers like we said in i and j.
void quickSort(int arr[], int left, int right) {
int i = left, j = right;
int tmp;
int pivot = arr[(left + right) / 2];
/* partition */
while (i <= j) {
while (arr[i] < pivot)
i++;
while (arr[j] > pivot)
j;
if (i <= j) {
tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
i++;
j;
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit5/assets/5.html 239 of 278 3/3
Searching, sorting and Complexity
8/13/2015 scorm content
Merge Sort
In the article we present an algorithm for merging two sorted arrays. One can learn how to
operate with several arrays and master read/write indices.
Also, the algorithm has certain applications in practice, for instance in merge sort.
Merge sort is a recursive algorithm that continually splits a list in half.
If the list is empty or has one item, it is sorted by definition.
If the list has more than one item, we split the list and recursively invoke a merge sort on both
halves.
Once the two halves are sorted, the fundamental operation, called a merge, is performed.
Merging is the process of taking two smaller sorted lists and combining them together into a
single.
Merge Algorithm
Assume, that both arrays are sorted in ascending order and we want resulting array to maintain
the same order.
Algorithm to merge two arrays A[0..m1] and B[0..n1] into an array C[0..m+n1] is as following:
Introduce readindices i, j to traverse arrays A and B, accordingly. Introduce writeindex k to
store position of the first free cell in the resulting array. By default i = j = k = 0.
At each step: if both indices are in range (i < m and j < n), choose minimum of (A[i], B[j]) and
write it to C[k]. Otherwise go to step 4.
Increase k and index of the array, algorithm located minimal value at, by one. Repeat step 2.
Copy the rest values from the array, which index is still in range, to the resulting array.
Example
The figure shows the example for merge sorting.
54, 26, 93 ,17, 77, 31, 44, 55, 20 are the unsorted array.
At the beginning the array would be divided and at the end the array is merged.
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit5/assets/6.html 240 of 278 1/3
Searching, sorting and Complexity
8/13/2015 scorm content
Complexity analysis
Merge algorithm′s time complexity is O(n + m).
Additionally, it requires O(n + m) additional space to store resulting array.
Code snippets
The code snippets shows how merge sort works.
m size of A.
n size of B.
Size of C array must be equal or greater than m + n.
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit5/assets/6.html 241 of 278 2/3
Searching, sorting and Complexity
8/13/2015 scorm content
void merge(int m, int n, int A[], int B[], int C[]) {
int i, j, k;
i = 0;
j = 0;
k = 0;
while (i < m && j < n) {
if (A[i] <= B[j]) {
C[k] = A[i];
i++;
} else {
C[k] = B[j];
j++;
}
k++;
}
if (i < m) {
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit5/assets/6.html 242 of 278 3/3
Searching, sorting and Complexity
8/13/2015 scorm content
Heap Sort
The term binary heap and heap are interchangeable in most cases.
A heap can be thought of as a tree with parent and child. The main difference between a heap
and a binary tree is the heap property.
In order for a data structure to be considered a heap, it must satisfy the following condition
(heap property):
If A and B are elements in the heap and B is a child of A, then key(A) ≤ key(B).
This chapter will refer exclusively to binary heaps, although different types of heaps exist.
We examine the idea laying in the foundation of the heap data structure.
We call it sifting, but you also may meet another terms, like "trickle", "heapify", "bubble" or
"percolate".
Heap Algorithm
Now, let us phrase general algorithm to insert a new element into a heap.
Add a new element to the end of an array.
Sift up the new element, while heap property is broken.
Sifting is done as following: compare node′s value with parent′s value.
If they are in wrong order, swap them.
Example
Step1: Insert 2 into a following heap.
Step2: Insert a new element to the end of the array.
Step3: In the general case, after insertion, heap property near the new node is broken.
Step4: To restore heap property, algorithm sifts up the new element, by swapping it with its
parent.
Step5 : Now heap property is broken at the root node.
Step6: Keep shifting.
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit5/assets/7.html 243 of 278 1/2
Searching, sorting and Complexity
8/13/2015 scorm content
Complexity Analysis
Complexity of the insertion operation is O(h), where h is heap′s height.
Taking into account completeness of the tree, O(h) = O(log n), where n is number of elements in
a heap.
Implementation
The code illustrate the output of Heap sort.
The working principle of heap sort.
Void BinaryMinHeap::insert(int value) is the functon of sorting the heap tree.
void BinaryMinHeap::siftUp(int nodeIndex) {
int parentIndex, tmp;
if (nodeIndex != 0) {
parentIndex = getParentIndex(nodeIndex);
if (data[parentIndex] > data[nodeIndex]) {
tmp = data[parentIndex];
data[parentIndex]= data[nodeIndex];
data[nodeIndex] = tmp;
siftUp(parentIndex);
}
}
}
void BinaryMinHeap::insert(int value) {
if (heapSize == arraySize)
throw string("Heap’s underlying storage is overflow");
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit5/assets/7.html 244 of 278 2/2
Searching, sorting and Complexity
8/13/2015 scorm content
Radix Sort
The radix sort is a noncomparative integer sorting algorithm that sorts data with integer keys by
grouping keys by the individual digits which share the same significant position and value.
A positional notation is required, but because integers can represent strings of characters (e.g.,
names or dates) and specially formatted floating point numbers, radix sort is not limited to
integers.
Radix Sort is a clever and intuitive little sorting algorithm.
Radix Sort puts the elements in order by comparing the digits of the numbers.
The bin sorting approach can be generalized in a technique that is known as radix sorting.
Position by position, either starting from LSB or MSB, group the numbers into buckets.
When you move to next position again reorder them for that position, while keeping the order of
the previous position reorders.
Once all the positions are done, the whole list should be ordered.
Example
The example explains step by step how the radix sort is working.
For every sorting iteration a value should be sorted.
At the end the sorted values are viewed.
Time complexity
Worst case performance is O(kN), k is count of decimal places and N is the input size.
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit5/assets/8.html 245 of 278 1/2
Searching, sorting and Complexity
8/13/2015 scorm content
Note that we don′t take out k.
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit5/assets/8.html 246 of 278 2/2
Searching, sorting and Complexity
8/13/2015 scorm content
Searching
Computer systems are often used to store large amounts of data from which individual records
must be retrieved according to some search criterion.
Thus the efficient storage of data to facilitate fast searching is an important issue.
We shall investigate the performance of some searching algorithms and the data structures
which they use.
Sequential Searching
The most obvious algorithm is to start at the beginning and walk to the end, testing for a match
at each item.
All search routines return a true/false boolean value for success or failure.
The list will be either an array of integers or a linked list of integers with a key.
The found item will be saved in a reference to a pointer for use in client code.
This algorithm has the benefit of simplicity; it is difficult to get wrong, unlike other more
sophisticated solutions.
The code follows the convention.
bool jw_search ( int *list, int size, int key, int*& rec )
{
// Basic sequential search
bool found = false;
int i;
for ( i = 0; i < size; i++ ) {
if ( key == list[i] )
break;
}
if ( i < size ) {
found = true;
rec = &list[i];
}
return found;
The algorithm itself is simple.
A familiar 0 n1 loop to walk over every item in the array, with a test to see if the current item in
the list matches the search key.
The loop can terminate in one of two ways.
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit5/assets/9.html 247 of 278 1/2
Searching, sorting and Complexity
8/13/2015 scorm content
If i reaches the end of the list, the loop condition fails.
If the current item in the list matches the key, the loop is terminated early with a break
statement.
Then the algorithm tests the index variable to see if it is less that size or not.
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit5/assets/9.html 248 of 278 2/2
Searching, sorting and Complexity
8/13/2015 scorm content
Binary Search
To find a value in unsorted array, we should look through elements of an array one by one, until
searched value is found.
In case of searched value is absent from array, we go through all elements.
In average, complexity of such an algorithm is proportional to the length of the array.
Situation changes significantly, when array is sorted.
If we know it, random access capability can be utilized very efficiently to find searched value
quick.
Cost of searching algorithm reduces to binary logarithm of the array length.
For reference, log 2 (1 000 000) ≈ 20.
It means, that in worst case, algorithm makes 20 steps to find a value in sorted array of a million
elements or to say, that it doesn′t present it the array.
Algorithm
The algorithm is quite simple.
It can be done either recursively or iteratively.
Get the middle element;
If the middle element equals to the searched value, the algorithm stops;
Otherwise, two cases are possible:
Searched value is less, than the middle element.
In this case, go to the step 1 for the part of the array, before middle element.
searched value is greater, than the middle element.
In this case, go to the step 1 for the part of the array, after middle element.
Now we should define, when iterations should stop.
First case is when searched element is found.
Second one is when sub array has no elements.
In this case, we can conclude, that searched value doesn′t present in the array.
Example
Find 6 in {1, 5, 6, 18, 19, 25, 46, 78, 102, 114}.
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit5/assets/10.html 249 of 278 1/3
Searching, sorting and Complexity
8/13/2015 scorm content
Step 1 (middle element is 19 > 6): 1 5 6 18 19 25 46 78 102 114.
Step 2 (middle element is 5 < 6): 1 5 6 18 19 25 46 78 102 114.
Step 3 (middle element is 6 == 6): 1 5 6 18 19 25 46 78 102 114.
The example explains how binary search is working.
In binary search it should be in sorted array.
Our example taken is sorted array.
Complexity analysis
Huge advantage of this algorithm is that it′s complexity depends on the array size logarithmically
in worst case.
In practice it means, that algorithm will do at most log 2 (n) iterations, which is a very small
number even for big arrays.
It can be proved very easily.
Indeed, on every step the size of the searched part is reduced by half.
Algorithm stops, when there are no elements to search in.
Binary search algorithm time complexity is O(log 2 (n)).
Therefore, solving following inequality in whole numbers:
n / 2 iterations > 0
resulting in
iterations <= log 2 (n).
It means, that binary search algorithm time complexity is O(log 2 (n)).
Code snippets
You can see iterative for C++ below.
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit5/assets/10.html 250 of 278 2/3
Searching, sorting and Complexity
8/13/2015 scorm content
int binarySearch(int arr[], int value, int left, int right) {
while (left <= right) {
int middle = (left + right) / 2;
if (arr[middle] == value)
return middle;
else if (arr[middle] > value)
right = middle 1;
else
left = middle + 1;
}
return 1;
}
The code describes,
Searches for a value in sorted array.
arr is an array to search in value is searched value.
Left is an index of left boundary.
Right is an index of right boundary.
Returns position of searched value, if it presents in the array.
Or 1, if it is absent.
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit5/assets/10.html 251 of 278 3/3
Searching, sorting and Complexity
8/13/2015 scorm content
Binary search tree
Binary search tree (BST) is a dynamic data structure, which means, that its size is only limited by
amount of free memory in the operating system and number of elements may vary during the
program run.
Main advantage of binary search trees is rapid search, while addition is quite cheap.
Binary search tree is a data structure, which meets the following requirements:
It is a binary tree;
Each node contains a value;
A total order is defined on these values (every two values can be compared with each other);
Left subtree of a node contains only values lesser, than the node′s value;
Right subtree of a node contains only values greater, than the node′s value.
What for binary search trees are used?
Binary search tree is used to construct map data structure.
In practice, data can be often associated with some unique key.
Also, BST can be utilized to construct set data structure, which allows to store an unordered
collection of unique values and make operations with such collections.
Performance of a binary search tree depends of its height.
In order to keep tree balanced and minimize its height, the idea of binary search trees was
advanced in balanced search trees.
Internal Representation
Like any other dynamic data structure, BST requires storing of some additional auxiliary data, in
order to keep its structure.
Each node of binary tree contains the following information:
A value (user′s data);
A link to the left child (auxiliary data);
A link to the right child (auxiliary data).
Depending on the size of user data, memory overhead may vary, but in general it is quite
reasonable.
In some implementations, node may store a link to the parent, but it depends on algorithm,
programmer want to apply to BST.
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit5/assets/11.html 252 of 278 1/2
Searching, sorting and Complexity
8/13/2015 scorm content
For basic operations, like addition, removal and search a link to the parent is not necessary.
It is needed in order to implement iterators.
Code snippets
It is a routine, when the whole structure of BST is put into two classes.
Main class BinarySearchTree is a public interface and BSTNode mean for private use inside the
main class.
This division is necessary, because some operations, like removal, may result in an empty tree,
which means that tree even doesn′t have a root node.
class BSTNode {
private:
int value;
BSTNode* left;
BSTNode* right;
public:
BSTNode(int value) {
this>value = value;
left = NULL;
right = NULL;
}
};
class BinarySearchTree {
private:
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit5/assets/11.html 253 of 278 2/2
Searching, sorting and Complexity
8/13/2015 scorm content
Balanced Binary Tree
The disadvantage of a binary search tree is that its height can be as large as N1.
This means that the time needed to perform insertion and deletion and many other operations
can be O(N) in the worst case.
We want a tree with small height.
A binary tree with N node has height at least Θ(log N).
Thus, our goal is to keep the height of a binary search tree O(log N).
Such trees are called balanced binary search trees.
Examples are AVL tree, redblack tree.
To overcome the problem in binary search tree we need a balancing tree.
Balancing means decreasing the height of the tree.
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit5/assets/12.html 254 of 278 1/1
Searching, sorting and Complexity
8/13/2015 scorm content
AVL tree
Height of a node.
The height of a leaf is 1.
The height of a null pointer is zero.
The height of an internal node is the maximum height of its children plus 1.
Note that this definition of height is different from the one we defined previously.
We defined the height of a leaf as zero previously.
An AVL tree is a binary search tree in which for every node in the tree, the height of the left and
right sub trees differ by at most 1.
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit5/assets/13.html 255 of 278 1/1
Searching, sorting and Complexity
8/13/2015 scorm content
B Tree Searching operation
Searching is similar to searching a binary search tree.
Starting at the root, the tree is recursively traversed from top to bottom.
At each level, the search chooses the child pointer (subtree) whose separation values are on
either side of the search value.
Binary search is typically (but not necessarily) used within nodes to find the separation values
and child tree of interest.
But not necessarily.
B Tree Complexity
At average case the search, insert, delete operation takes O(log n).
Same as average case the worst case also take O(log n).
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit5/assets/14.html 256 of 278 1/1
Searching, sorting and Complexity
8/13/2015 scorm content
Index Searching
In computer science, an inverted index (also referred to as postings file or inverted file) is an
index data structure storing a mapping from content, such as words or numbers, to its locations
in a database file, or in a document or a set of documents.
The purpose of an inverted index is to allow fast full text searches, at a cost of increased
processing when a document is added to the database.
The inverted file may be the database file itself, rather than its index.
It is the most popular data structure used in document retrieval systems, used on a large scale
for example in search engines.
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit5/assets/15.html 257 of 278 1/1
Searching, sorting and Complexity
8/13/2015 scorm content
Search Algorithms
This chapter discusses other search algorithms and analyzes them.
The analysis of algorithms enables programmers to decide which algorithm to use for a specific
application.
In the analysis of an algorithm, the key comparisons refer to comparing the key of the search
item with the key of an item in the list.
Moreover, the number of key comparisons refers to the number of times the key of the item is
compared with the keys of the items in the list.
We designed and implemented the class arrayListType to implement a list and the basic
operations in an array.
Sequential Search
The sequential search on arraybased lists was described in.
The sequential search works the same for both arraybased and linked lists.
The search always starts at the first element in the list and continues until either the item is
found in the list or the entire list is searched.
Because we are interested in the performance of the sequential search, for easy reference and
for the sake of completeness, we give the sequential search algorithm for arraybased lists.
If the search item is found, its index is returned.
If the search is unsuccessful, 1 is returned.
Note that the following sequential search does not require the list elements to be in any
particular order.
Binary Search
We therefore describe another search algorithm, called the binary search, which is very fast.
However, a binary search can be performed only on ordered lists.
We, therefore, assume that the list is ordered. We describe several sorting algorithms.
The binary search algorithm uses the divideandconquer technique to search the list.
First, the search item is compared with the middle element of the list.
If the search item is found, the search terminates.
If the search item is less than the middle element of the list, we restrict the search to the first half
of the list; otherwise, we search the second half of the list.
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit5/assets/16.html 258 of 278 1/2
Searching, sorting and Complexity
8/13/2015 scorm content
Consider the sorted list of length = 12.
Suppose that we want to determine whether 75 is in the list.
Initially, the entire list is the search list.
First, we compare 75 with the middle element in this list, list[5] (which is 39).
Because 75 6¼ list[5] and 75 > list[5], we restrict our search to the list list[6]...list[11].
This process is now repeated on the list list[6]...list[11], which is a list of length = 6.
Because we need to determine the middle element of the list frequently, the binary search
algorithm is typically implemented for arraybased lists.
To determine the middle element of the list, we add the starting index, first, and the ending
index, last, of the search list and then divide by 2 to calculate its index.
That is, mid = (first + last) / 2.
Initially, first = 0 and last = length – 1. The following C++ function implements the binary search
algorithm.
If the item is found in the list, its location is returned; if the search item is not in the list, 1 is
returned.
Number of comparisons for a list of length n
The table shows the comparison of time complexity.
The sequential search is worst than binary search in all successful search same as in un
successful research.
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit5/assets/16.html 259 of 278 2/2
Searching, sorting and Complexity
8/13/2015 scorm content
Hashing
The search algorithm that we now describe, called hashing, also requires the data to be
specially organized.
In hashing, the data is organized with the help of a table, called the hash table, denoted by HT,
and the hash table is stored in an array.
To determine whether a particular item with a key, say X, is in the table, we apply a function h,
called the hash function, to the key X; that is, we compute h(X), read as h of X.
The function h is typically an arithmetic function and h(X) gives the address of the item in the
hash table.
Suppose that the size of the hash table, HT, is m.
Then 0 _ h(X) < m. Thus, to determine whether the item with key X is in the table, we look at the
entry HT[h(X)] in the hash table.
Because the address of an item is computed with the help of a function, it follows that the items
are stored in no particular order.
Before continuing with this discussion, let us consider the following questions:
How do we choose a hash function?
How do we organize the data with the help of the hash table?
A hash function is any function that maps data of arbitrary length to data of a fixed length.
The values returned by a hash function are called hash values, hash codes, hash sums,
checksums or simply hashes.
Recent development of internet payment networks also uses a form of ‘hashing’ for checksums,
and has brought additional attention to the term.
Some Examples
Several hash functions are described in the literature.
Here we describe some of the commonly used hash functions.
MidSquare: In this method, the hash function, h, is computed by squaring the identifier, and
then using the appropriate number of bits from the middle of the square to obtain the bucket
address.
Because the middle bits of a square usually depend on all the characters, it is expected that
different keys will yield different hash addresses with high probability, even if some of the
characters are the same.
Folding: In folding, the key X is partitioned into parts such that all the parts, except possibly the
last parts, are of equal length.
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit5/assets/17.html 260 of 278 1/2
Searching, sorting and Complexity
8/13/2015 scorm content
The parts are then added, in some convenient way, to obtain the hash address.
Division (Modular arithmetic): In this method, the key X is converted into an integer iX.
This integer is then divided by the size of the hash table to get the remainder, giving the address
of X in HT.
That is, (in C++) h(X) ¼ iX % HTSize; Suppose that each key is a string.
The following C++ function uses the division method to compute the address of the key.
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit5/assets/17.html 261 of 278 2/2
Searching, sorting and Complexity
8/13/2015 scorm content
Collision Resolution
The hash function that we choose not only should be easy to compute, but it is most desirable
that the number of collisions is minimized.
However, in reality, collisions are unavoidable because usually a hash function always maps a
larger domain onto a smaller range.
Thus, in hashing, we must include algorithms to handle collisions.
Collision resolution techniques are classified into two categories: open addressing.
In open addressing, the data is stored within the hash table.
In chaining, the data is organized in linked lists and the hash table is an array of pointers to the
linked lists.
Hash collisions are practically unavoidable when hashing a random subset of a large set of
possible keys.
For example, if 2,450 keys are hashed into a million buckets, even with a perfectly uniform
random distribution, according to the birthday problem there is approximately a 95% chance of
at least two of the keys being hashed to the same slot.
Therefore, most hash table implementations have some collision resolution strategy to handle
such events.
Some common strategies are described below.
All these methods require that the keys be stored in the table, together with the associated
values.
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit5/assets/18.html 262 of 278 1/1
Searching, sorting and Complexity
8/13/2015 scorm content
Open Addressing
In open addressing, the data is stored within the hash table.
Therefore, for each key X, h(X) gives the index in the array where the item with key X is likely to
be stored.
Open addressing can be implemented in several ways. Next, we describe some of the common
ways to implement it.
Wellknown probe sequences include:
Linear probing, in which the interval between probes is fixed (usually 1).
Quadratic probing, in which the interval between probes is increased by adding the
successive outputs of a quadratic polynomial to the starting value given by the original hash
computation
Double hashing, in which the interval between probes is computed by another hash function.
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit5/assets/19.html 263 of 278 1/1
Searching, sorting and Complexity
8/13/2015 scorm content
Separate Chaining
In the method known as separate chaining, each bucket is independent, and has some sort of
list of entries with the same index.
The time for hash table operations is the time to find the bucket plus the time for the list
operation.
The technique is also called open hashing or closed addressing.
In a good hash table, each bucket has zero or one entries, and sometimes two or three, but
rarely more than that.
Therefore, structures that are efficient in time and space for these cases are preferred.
Structures that are efficient for a fairly large number of entries are not needed or desirable.
If these cases happen often, the hashing is not working well, and this needs to be fixed.
Idea: Keys hashing to same address are kept in lists attached to that address.
For each table address, a linked list of the records whose keys hash to that address, is built.
This method is useful for highly dynamic situations, where the number of the search keys cannot
be predicted in advance.
Example Records: (each character is a key):
Key: A S E A R C H I N G E X A M P L E
Hash (M = 11) 1 8 5 1 7 3 8 9 3 7 5 2 1 2 5 1 5
Separate chaining:
Each column is a linked list.
Thus we maintain M lists with M list header nodes.
We can use the list search and insert procedures for sequential searching.
Complexity of separate chaining
The time to compute the index of a given key is a constant.
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit5/assets/20.html 264 of 278 1/2
Searching, sorting and Complexity
8/13/2015 scorm content
Then we have to search in a list for the record.
Therefore the time depends on the length of the lists.
It has been shown empirically that on average the list length is N/M (the load factor L), provided
M is prime and we use a function that gives good distribution.
Unsuccessful searches go to the end of some list, hence we have L comparisons.
Successful searches are expected to go half the way down some list.
On average the number of comparisons in successful search is L/2.
Therefore we can say that runtime complexity of separate chaining is O(L).
Note, that what really matters is the load factor rather than the size of the table or the number of
records, taken separately.
How to choose M in separate chaining?
Since the method is used in cases when we cannot predict the number of records in advance,
the choice of M basically depends on other factors such as available memory.
Typically M is chosen relatively small so as not to use up a large area of contiguous memory, but
enough large so that the lists are short for more efficient sequential search.
Recommendations in the literature vary from M to be about one tenth of N the number of the
records to M to be equal (or close to) N.
Other methods of chaining
Keep the lists ordered: useful if there are much more searches than inserts, and if most of the
searches are unsuccessful.
Represent the chains as binary search tree.
Extra effort needed – not efficient.
Advantages
Used when memory is of concern, easily implemented.
Disadvantages
Unevenly distributed keys – long lists and many empty spaces in the table.
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit5/assets/20.html 265 of 278 2/2
Searching, sorting and Complexity
8/13/2015 scorm content
Comparisons of Sorting Algorithm
A sorting algorithm is an algorithm that puts elements of a list in a certain order.
The mostused orders are numerical order and lexico graphical order.
Efficient sorting is important for optimizing the use of other algorithms (such as search and
merge algorithms) which require input data to be in sorted lists; it is also often useful for
canonicalizing data and for producing humanreadable output.
More formally, the output must satisfy two conditions:
The output is in nondecreasing order (each element is no smaller than the previous element
according to the desired total order);
The output is a permutation (reordering) of the input.
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit5/assets/21.html 266 of 278 1/1
UNIT - 6
Graphs
Introduction
A graph is a finite set of nodes with edges between nodes.
For graphs to be computationally useful, they have to be conveniently represented in programs.
There are two computer representations of graphs:
Adjacency matrix.
Adjacency lists.
Adjacency matrix
Definition: An adjacency matrix is a matrix which describes a graph by representing which
vertices are adjacent to which other vertices.
A representation of a directed graph with n vertices using an n × n matrix, where the entry at (i, j)
is 1 if there is an edge from vertex i to vertex j; otherwise the entry is 0.
A weighted graph may be represented using the weight as the entry.
An undirected graph may be represented using the same entry in both (i, j) and (j, i) or using an
upper triangular matrix.
Each cell aij of an adjacency matrix contains 0, if there is an edge between ith and jth vertices,
and 1 otherwise.
Advantages
Adjacency matrix is very convenient to work with.
Add (remove) an edge can be done in O(1) time, the same time is required to check, if there is
an edge between two vertices.
Also it is very simple to program and in all our graph tutorials we are going to work with this kind
of representation.
Disadvantages
Adjacency matrix consumes huge amount of memory for storing big graphs.
All graphs can be divided into two categories, sparse and dense graphs.
Sparse ones contain not much edges (number of edges is much less, that square of number of
vertices, |E| << |V| 2 ).
On the other hand, dense graphs contain number of edges comparable with square of number
of vertices.
Adjacency matrix is optimal for dense graphs, but for sparse ones it is superfluous.
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit6/assets/2.html 268 of 278 1/4
Graphs
8/13/2015 scorm content
Next drawback of the adjacency matrix is that in many algorithms you need to know the edges,
adjacent to the current vertex.
To draw out such an information from the adjacency matrix you have to scan over the
corresponding row, which results in O(|V|) complexity.
For the algorithms like DFS or based on it, use of the adjacency matrix results in overall
complexity of O(|V| 2 ), while it can be reduced to O(|V| + |E|), when using adjacency list.
The last disadvantage, we want to draw you attention to, is that adjacency matrix requires huge
efforts for adding/removing a vertex.
In case, a graph is used for analysis only, it is not necessary, but if you want to construct fully
dynamic structure, using of adjacency matrix make it quite slow for big graphs.
To sum up, adjacency matrix is a good solution for dense graphs, which implies having constant
number of vertices.
The Graph and its Respective Matrix
This is how we compute the matrix for the given graph.
Another Example with Different Scenario
Let looks at yet another example with different scenario.
Find the graph and its respective graph.
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit6/assets/2.html 269 of 278 2/4
Graphs
8/13/2015 scorm content
Vertex without Edges
For vertex which doesn′t have edges.
Adjacency List
This kind of the graph representation is one of the alternatives to adjacency matrix.
It requires less amount of memory and, in particular situations even can outperform adjacency
matrix.
For every vertex adjacency list stores a list of vertices, which are adjacent to current one.
Let us see an example.
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit6/assets/2.html 270 of 278 3/4
Graphs
8/13/2015 scorm content
Advantages
Adjacent list allows us to store graph in more compact form, than adjacency matrix, but the
difference decreasing as a graph becomes denser.
Next advantage is that adjacent list allows to get the list of adjacent vertices in O(1) time, which
is a big advantage for some algorithms.
Disadvantages
Adding/removing an edge to/from adjacent list is not so easy as for adjacency matrix.
It requires, on the average, O(|E| / |V|) time, which may result in cubical complexity for dense
graphs to add all edges.
Check, if there is an edge between two vertices can be done in O(|E| / |V|) when list of adjacent
vertices is unordered or O(log2(|E| / |V|)) when it is sorted.
This operation stays quite cheap.
Adjacent list doesn′t allow us to make an efficient implementation, if dynamically change of
vertices number is required.
Adding new vertex can be done in O(V), but removal results in O(E) complexity.
To sum up, adjacency list is a good solution for sparse graphs and lets us changing number of
vertices more efficiently, than if using an adjacent matrix.
But still there are better solutions to store fully dynamic graphs.
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit6/assets/2.html 271 of 278 4/4
Graphs
8/13/2015 scorm content
Traversal Schemes
Traversing a graph is similar to traversing a binary tree, except that:
A graph might have cycles.
Might not be able to traverse the entire graph from a single vertex.
Most common graph traversal algorithms:
Depth first traversal.
Breadth first traversal.
Depthfirst search
Depthfirst search (DFS) is an algorithm for traversing or searching tree or graph data
structures.
One starts at the root (selecting some arbitrary node as the root in the case of a graph) and
explores as far as possible along each branch before backtracking.
A depthfirst search (DFS) explores a path all the way to a leaf before backtracking and
exploring another path.
For example, after searching A, then B, then D, the search backtracks and tries another path
from B.
Node are explored in the order A B D E H L M N I O P C F G J K Q.
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit6/assets/3.html 272 of 278 1/3
Graphs
8/13/2015 scorm content
N will be found before J.
Depth First Traversal
Depth first traversal at a given node, v:
Mark node v as visited.
Visit the node.
For each vertex u adjacent to v.
If u is not visited start the depth first traversal at u.
DFS follows the following rules
Select an unvisited node x, visit it, and treat as the current node.
Find an unvisited neighbor of the current node, visit it, and make it the new current node;
If the current node has no unvisited neighbors, backtrack to the its parent, and make that parent
the new current node;
Repeat steps 3 and 4 until no more nodes can be visited.
If there are still unvisited nodes, repeat from step 1.
Breadthfirst search
(BFS) is a strategy for searching in a graph when search is limited to essentially two operations:
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit6/assets/3.html 273 of 278 2/3
Graphs
8/13/2015 scorm content
(a) visit and inspect a node of a graph; (b) gain access to visit the nodes that neighbor the
currently visited node.
The BFS begins at a root node and inspects all the neighboring nodes.
Then for each of those neighbor nodes in turn, it inspects their neighbor nodes which were
unvisited, and so on.
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit6/assets/3.html 274 of 278 3/3
Graphs
8/13/2015 scorm content
Spanning Tree: Definition
A tree is a connected undirected graph with no cycles.
It is a spanning tree of a graph G if it spans G (that is, it includes every vertex of G) and is a
subgraph of G (every edge in the tree belongs to G).
A spanning tree of a connected graph G can also be defined as a maximal set of edges of G that
contains no cycle, or as a minimal set of edges that connect all vertices.
Spanning Tree
Suppose you have a connected undirected graph
Connected: every node is reachable from every other node.
Undirected: edges do not have an associated direction.
Then a spanning tree of the graph is a connected subgraph in which there are no cycles.
Total of 16 different spanning trees for the graph below.
Minimum weight spanning tree (MST)
The Minimum Spanning Tree for a given graph is the Spanning Tree of minimum cost for that
graph.
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit6/assets/4.html 275 of 278 1/4
Graphs
8/13/2015 scorm content
On a weighted graph, A MST:
Connects all vertices through edges with least weights.
Has w(T) ≤ w(T′) for every other spanning tree T′ in G.
Adding one edge not in MST will create a cycle.
Finding Minimum Spanning Tree
Algorithms :
Kruskal′s and Prim′s.
AD and CE are the shortest edges, with length 5, and AD has been arbitrarily chosen, so it is
highlighted.
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit6/assets/4.html 276 of 278 2/4
Graphs
8/13/2015 scorm content
CE is now the shortest edge that does not form a cycle, with length 5, so it is highlighted as the
second edge.
The next edge, DF with length 6, is highlighted using much the same method.
The nextshortest edges are AB and BE, both with length 7.
AB is chosen arbitrarily, and is highlighted.
The edge BD has been highlighted in red, because there already exists a path (in green)
between B and D, so it would form a cycle (ABD) if it were chosen.
The process continues to highlight the nextsmallest edge, BE with length 7.
Many more edges are highlighted in red at this stage: BC because it would form the loop BCE,
DE because it would form the loop DEBA, and FE because it would form FEBAD.
Finally, the process finishes with the edge EG of length 9, and the minimum spanning tree is
found.
Another example so closely
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit6/assets/4.html 277 of 278 3/4
Graphs
8/13/2015 scorm content
Edge first
Arrange all edges in a list (L) in nondecreasing order.
Select edges from L, and include that in set T, avoid cycle.
Repeat 3 until T becomes a tree that covers all vertices.
Start form any arbitrary vertex.
Find the edge that has minimum weight form all known vertices.
Stop when the tree covers all vertices.
Page
file:///D:/NIELIT%20PROJECT/Final%20Product/DS/unit6/assets/4.html 278 of 278 4/4