You are on page 1of 278

data structure through

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 three­step 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 well­defined 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.

Ex: 100n 3  + 30000n => O(n 3 ) 100n 3  + 2n 5 + 30000n => O(n 5 )

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 Log­squared

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

The worst algorithm will contains N 3  and 2 n  cases.

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(n­1)/2 => O(n 2 ).

Colinear points in the plane, ie. 3 points on a straight line: n(n­1)(n­2)/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 Big­Oh 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, …, j­1.

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 Big­Oh Rules

Def:  (Big­Oh)  T(n)  is  O(F(n))  if  there  are  positive  constants  c  and  n0  such  that  T(n)<=  cF(n)
when n >= n0

Def: (Big­Omega) T(n) is Ω(F(n)) if there are positive constant c and n0 such that T(n) >= cF(n)
when n >= n0

Def: (Big­Theta) T(n) is Θ(F(n)) if and only if T(n) = O(F(n)) and T(n) = Ω(F(n))

Def: (Little­Oh) T(n) = o(F(n)) if and only if T(n) = O(F(n)) and T(n) != Θ(F(n))

Any k th  degree polynomial is O(n k).

a n k = O(n k) for any a > 0.

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 Big­Oh.

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

 
Worst­case vs. Average­case

A worst­case bound is a guarantee over all inputs of size N.

In an average­case bound, the running time is measured as an average over all of the possible
inputs of size N.

We will mainly focus on worst­case 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  Big­Oh  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 3­ways 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 3­way 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 2­ways 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 2­way 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

2­ways comparisons binary search is still O(logN)

This is effective than the 3­way 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 Big­Oh 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.

Average­case analysis is almost always much more difficult than worst­case 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 bottom­up 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 re­computing results.

Fibonacci numbers example (top down): Use vector to store results as calculated so they are not
re­calculated

Fibonacci numbers: 0, 1, 1, 2, 3, 5, 8, 13, 21, 24.

f(0) = 0

f(1) = 1

f(n) = f(n­1) + f(n­2) for n ≥ 2

int fib(int n) {
  if (n <= 1) return n;   // stopping conditions    
      else   return fib(n­1) + fib(n­2);  // 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(n­1, fibList) + fibDyn(n­2, 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 all­pairs 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) sub­problems.

Sub­instances are combined to obtain sub­instances 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 sub­problems.

Principle of optimality

The  optimal  solution  to  any  nontrivial  instance  of  a  problem  is  a  combination  of  optimal
solutions to some of its sub­instances.

Memorization (for overlapping sub­problems)

Avoid calculating the same thing twice,

Usually by keeping a table of know results that fills up as sub­instances 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 sub­problem.

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 sub­problems.

Compute the value of an optimal solution in a bottom­up fashion.

Compute in a bottom­up 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  worst­case  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  big­O  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 running­time 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.

Sub­linear time

An algorithm is said to run in sub­linear 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  sub­linear  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  1­bit  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
sub­linear 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.

Sub­linear 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 sub­linear time algorithm.

Sub­linear 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  content­addressable  memory.  This  concept  of  linear  time  is  used  in  string
matching algorithms such as the Boyer­Moore 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  n­sized
array one by one. Since the insert operation on a self­balancing 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: In­place merge sort, O(n log 2  n)

Sub­quadratic 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  comparison­based  sorting  algorithms  are  quadratic,  but  more
advanced algorithms can be found that are subquadratic.

No general­purpose sorts run in linear time, but the change from quadratic to sub­quadratic 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  non­deterministic
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  1­sided  error  on  a
probabilistic Turing machine in polynomial time.

BPP:  The  complexity  class  of  decision  problems  that  can  be  solved  with  2­sided  error  on  a
probabilistic Turing machine in polynomial time.

BQP:  The  complexity  class  of  decision  problems  that  can  be  solved  with  2­sided  error  on  a
quantum Turing machine in polynomial time.

P  is  the  smallest  time­complexity  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  n­bit
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  NP­complete  problem  is
currently known to run in polynomial time.

Quasi­polynomial Time

Quasi­polynomial 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 quasi­polynomial time algorithm is 2 O((log n)

The  best­known  classical  algorithm  for  integer  factorization,  the  general  number  field  sieve,
which runs in time about is not quasi­polynomial 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  quasi­polynomial  time  algorithms  is  equal  to  1,  we  get  a
polynomial time algorithm, and if it is less than 1, we get a sub­linear time algorithm.

Quasi­polynomial  time  algorithms  typically  arise  in  reductions  from  an  NP­hard  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 quasi­polynomial 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
polynomial­time algorithms.

All the best­known algorithms for NP­complete problems like 3SAT etc. take exponential time.

Indeed,  it  is  conjectured  for  many  natural  NP­complete  problems  that  they  do  not  have  sub­
exponential time algorithms.

Here "sub­exponential time" is taken to mean the second definition presented above.

This conjecture (for the k­SAT problem) is known as the exponential time hypothesis.

Since it is conjectured that NP­complete problems do not have quasi­polynomial time algorithms,
some  in  approximability  results  in  the  field  of  approximation  algorithms  make  the  assumption
that NP­complete problems do not have quasi­polynomial 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

Sub­exponential Time

The term sub­exponential 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 sub­exponential time algorithms are somewhat more tractable
than those that only have exponential algorithms.

The  precise  definition  of  "sub­exponential"  is  not  generally  agreed  upon,  and  we  list  the  two
most widely used ones below.

Sub­exponential Time ­ First Definition

A problem is said to be sub­exponential time solvable if it can be solved in running times whose
logarithms grow smaller than any given polynomial.

More precisely, a problem is in sub­exponential 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 sub­exponential 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.

Sub­exponential Time ­ Second Definition

Sub­exponential time as running times in 2 o(n).

This definition allows larger running times than the first definition of sub­exponential time.

An  example  of  such  a  sub­exponential  time  algorithm  is  the  best­known  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  best­known  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 sub­exponential 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 sub­exponential 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.

Sometimes,  exponential  time  is  used  to  refer  to


algorithms that have T(n) = 2 O(n), where the exponent is
at most a linear function of n. This gives rise to the complexity
class E.

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 2­EXPTIME.

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.

Low­level 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  block­structured  when  it  has  a  syntax  for  enclosing  structures
between  bracketed  keywords,  such  as  an  if­statement  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.

High­level  programming  languages  that  originally  lacked  programming  structures,  such  as


FORTRAN, COBOL, and BASIC, now have them.

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).

Re­coding 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
compile­time as opposed to run­time.

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  a  statically  typed,  compiled,  general­purpose,  case­sensitive,  free­form  programming


language that supports procedural, object­oriented, and generic programming.

C++  is  regarded  as  a  middle­level  language,  as  it  comprises  a  combination  of  both  high­level
and low­level 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 single­line comment available
in C++.

Single­line 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 case­sensitive 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  three­character  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 single­line and multi­line 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 built­in 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 enum­name { list of names } var­list;

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 enum­name 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 case­sensitive.

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
user­defined  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  left­hand  side  of  an  assignment.  Numeric
literals are rvalues and so may not be assigned and can not appear on the left­hand side.

Following is a valid statement:

Lvalue: An expression that is an lvalue may appear as either the left­hand or right­hand side
of an assignment.

Rvalue: An expression that is an rvalue may appear on the right­ but not left­hand 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 life­time 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,
Floating­Point 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.

Floating­point Literals

A  floating­point  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  life­time  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
life­time 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 de­numerator.

(%) 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  non­zero,  then  condition  becomes
true.

(||) Called Logical OR Operator. If any of the two operands is non­zero, 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 comma­separated 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  un­buffered  standard  error  stream  and  the  buffered
standard error stream, respectively.

This  file  declares  services  useful  for  performing  formatted  I/O  with  so­called  parameterized
stream manipulators, such as setw and setprecision.

This file declares services for user­controlled 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 built­in 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 new­line 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 un­buffered 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 sub­routine 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 built­in 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
function­ending 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  fixed­size  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:

Multi­dimensional 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
two­dimensional 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 *var­name;

Here, type is the pointer′s base type; it must be a valid C++ type and var­name 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 object­oriented programming
and are often called user­defined 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 data­abstraction 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 user­level 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 user­level 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 derived­class: access­specifier base­class

Access­specifier  is  one  of  public,  protected,  or  private,  and  base­class  is  the  name  of  a
previously defined class.

If the access­specifier is not used, then it is private by default.

Access Control and Inheritance

A derived class can access all the non­private members of its base class.

Thus  base­class  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  access­specifier  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  non­member  functions  or  as  class
member functions.

In case we define above function as non­member 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 built­in operators available in C++.

Thus a programmer can use operators with user­defined 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 one­dimensional 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  in­program  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 one­dimensional 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 0­9 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  two­dimensional  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.

More generally, in a k­dimensional array, the address of an element with indices i 1 , i 2 , …, i k is

B + c 1  • i 1  + c 2  • i 2  + … + c k • i k.

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.

The above array will be stored as a 11 , a 12 , a 13 , a 21 , a 22 , a 23 .

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.

An example of a polynomial is: 4x 3 +5x 2 +6x+9.

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, subscript­wise 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 re­buffering 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 n­1 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 n­1 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 *var­name;

Here, type is the pointer′s base type; it must be a valid C++ type and var­name 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 32­bit 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
singly­linked list.

For  instance,  algorithm  may  traverse  a  singly­linked  list  to  find  a  value,  find  a  position  for
insertion, etc.

For a singly­linked 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.

Singly­Linked List ­ Addition (insertion) operation

Insertion into a singly­linked 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.

Singly­Linked 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

P(x) = 4x 3 +6x 2 +7x+9

A polynomial thus may be represented using arrays or linked lists.

Array representation assumes that the exponents of the given expression are arranged from 0
to the highest value (degree), which is represented by the subscript of the array beginning with
0.

The coefficients of the respective exponent are placed at an appropriate index in the array.

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 n­1, 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.

Print

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

Page 153 of 278


Abstract Data types Stacks and Queues
8/13/2015 scorm content

 
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  user­defined  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 push­down 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=STACKSIZE­1, 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=top­1

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 value­returning 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++ run­time 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 run­time 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

 
Array­based 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 array­based 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  check­out  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 check­out 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 n­1 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 double­ended queue.

The  C++  standard  defines  the  Dequeue  as  a  full­fledged  sequential  container  that  supports
random access.

A Dequeue is a double­ended 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. policy­based 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

Page 189 of 278


Trees
8/13/2015 scorm content

 
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

In­order: (left, root, right)

3, 5, 6, 7, 10, 12, 13, 15, 16, 18, 20, 23.

Pre­order: (root, left, right)

15, 5, 3, 12, 10, 6, 7, 13, 16, 20, 18, 23.

Post­order: (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 post­order traversals.

Example: Write the 3 traversals of the given tree.

In­order: Chewbacca, Han, Lando, Leia, Luke, Obi, Vader, Yoda.

Pre­order: 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

Post­order: 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 In­Order

The in­order traversal always prints the values in sorted order from smallest to largest.

One application of the in­order 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  in­order  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 Pre­Order

Suppose
we  want
to
transmit
our  tree
across the country to another programmer.

Sending the in­order list would tell them the values, but would not communicate how the tree is
built.

Trees are usually stored with the pre­order traversal.

Example: All of the tree below have the in­order walk: 1 2 3. But only one of the trees below has
the pre­order 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 BST­property.

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.

BST­Search(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.

BST­Minimum(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]) 

BST­Maximum(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.

BST­Successor(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 last­in, first­out 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 [(i­1)/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.

Pre­order 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 pre­order traversal of the tree above is: A B D E C F H I J G.

In­order 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 in­order 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

Post­order 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 post­order 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 (Height­Balanced) 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
height­balanced tree) in which the resulting binary search is nearly balanced.

AVL trees are due to the mathematicians G. M. Adel´son­Vel´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 one­to­one 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) two­tree 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

 
B­Trees

The performance of the search depends on the height of the tree.

B­trees in which the leaves are on the same level and are not too far from the root.

Definition: (m­way search tree) An m­way 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

Page 226 of 278


Searching, sorting and Complexity
8/13/2015 scorm content

 
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 divide­and­conquer 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 non­equal 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 i­th element are less or equal than the pivot and all values after
j­th 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..m­1] and B[0..n­1] into an array C[0..m+n­1] is as following:

Introduce read­indices i, j to traverse arrays A and B, accordingly. Introduce write­index 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 non­comparative 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 re­order them for that position, while keeping the order of
the previous position re­orders.

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 ­ n­1 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 N­1.

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, red­black 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

Search O(log n) O(log n)

Insert O(log n) O(log n)

Delete O(log n) O(log n)

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 array­based lists was described in.

The sequential search works the same for both array­based 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 array­based 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 divide­and­conquer 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 array­based 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.

Mid­Square:  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.

Well­known 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 most­used 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 human­readable 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

Page 267 of 278


Graphs
8/13/2015 scorm content

 
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 i­th and j­th 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.

Depth­first search

Depth­first  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  depth­first  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.

Breadth­first 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 next­shortest 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 next­smallest 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 non­decreasing 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

You might also like