EC6301 - Notes
EC6301 - Notes
UNIT I
Syllabus: Overview of C++ – Structures – Class Scope and Accessing Class Members –
Reference Variables – Initialization – Constructors – Destructors – Member Functions
and Classes – Friend Function – Dynamic Memory Allocation – Static Class Members –
Container Classes and Integrators – Proxy Classes – Overloading: Function overloading
and Operator Overloading.
Page 1
EC6301 / OOPS AND DS BE (ECE) III Sem / II Year
An Object is a collection of data members and associated member functions also known
as methods.
Classes
Classes are data types based on which objects are created. Objects with similar properties
and methods are grouped together to form a Class. Thus a Class represent a set of individual
objects. Characteristics of an object are represented in a class as Properties. The actions that can
be performed by objects becomes functions of the class and is referred to as Methods.
For example consider we have a Class of Cars under which Santro Xing, Alto and
WaganRrepresents individual Objects. In this context each Car Object will have its own, Model,
Year of Manufacture, Colour, Top Speed, Engine Power etc., which form Properties of the Car
class and the associated actions i.e., object functions like Start, Move, and Stop form the
Methods of CarClass.
No memory is allocated when a class is created. Memory is allocated only when an object
is created, i.e., when an instance of a class is created.
Inheritance
Inheritance is the process of forming a new class from an existing class or base class. The
base class is also known as parent class or super class. The new class that is formed is called
derived class. Derived class is also known as a child class or sub class. Inheritance helps in
reducing the overall code size of the program, which is an important concept in object-oriented
programming.
Page 2
EC6301 / OOPS AND DS BE (ECE) III Sem / II Year
Data 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.
Data Encapsulation
Data Encapsulation combines data and functions into a single unit called class. When
using Data Encapsulation, data is not accessed directly; it is only accessible through the
functions present inside the class. Data Encapsulation enables the important concept of data
hiding possible.
Polymorphism
Polymorphism allows routines to use variables of different types at different times. An
operator or function can be given different meanings or functions. Polymorphism refers to a
single function or multi-functioning operator performing in different ways.
Overloading
Overloading is one type of Polymorphism. It allows an object to have different meanings,
depending on its context. When an existing operator or function begins to operate on new data
type, or class, it is understood to be overloaded.
Reusability
This term refers to the ability for multiple programmers to use the same written and
debugged existing class of data. This is a time saving device and adds code efficiency to the
language. Additionally, the programmer can incorporate new features to the existing class,
further developing the application and allowing users to achieve increased performance. This
time saving feature optimizes code, helps in gaining secured applications and facilitates easier
maintenance.
Dynamic Binding
Binding refers to the linking of a procedure call to the code. Dynamic binding means that
the code associated with a given procedure call.
Page 3
EC6301 / OOPS AND DS BE (ECE) III Sem / II Year
Message Passing
An object oriented program consists of a set of objects that communicate with each other.
Employee.salary (name)
1.2 STRUCTURES
Structure is the collection of variables of different types under a single name for better
visualization of problem. Arrays is also collection of data but arrays can hold data of only one
type whereas structure can hold data of one or more types.
Defining a structure in C++ programming
The struct keyword defines a structure type followed by an identifier (name of the
structure). Then inside the curly braces, you can declare one or more members (declare variables
inside curly braces) of that structure. For example: struct person {
char name[50];
int age;
float salary;
};
Here a structure person is defined which has three members: name, age and salary.
When a structure is created, no memory is allocated. The structure definition is only the
blueprint for the creating of variables. You can imagine it as a datatype. When you define an
integer as below:
int foo;
The int specifies that, variable foo can hold integer element only. Similarly, structure
definition only specifies that, what property a structure variable holds when it is defined.
Defining a structure variable
Once you declare a structure person as above. You can define a structure variable as:
person bill;
Page 4
EC6301 / OOPS AND DS BE (ECE) III Sem / II Year
Here, a structure variable bill is defined which is of type structure person. When structure
variable is defined, then only the required memory is allocated by the compiler. Considering you
have either 32-bit or 64-bit system, the memory of float is 4 bytes, memory of int is 4 bytes and
memory of char is 1 byte. Hence, 58 bytes of memory is allocated for structure variable bill.
Accessing members of a structure
The members of structure variable are accessed using dot operator. Suppose, you want to
access age of structure variable bill and assign it 50 to it. You can perform this task by using
following code below:
bill.age = 50;
C++ Program to assign data to members of a structure variable and display it
#include <iostream.h>
struct person
{
char name[50];
int age;
float salary;
};
void main()
{
person p1;
cout << "Enter Full name: ";
cin.get(p1.name, 50);
cout << "Enter age: ";
cin >> p1.age;
cout << "Enter salary: ";
cin >> p1.salary;
cout << "\nDisplaying Information." << endl;
cout << "Name: " << p1.name << endl;
cout <<"Age: " << p1.age << endl;
cout << "Salary: " << p1.salary;
Page 5
EC6301 / OOPS AND DS BE (ECE) III Sem / II Year
}
1.3 REFERENCE VARIABLES
A reference variable provides an alias (alternative name) for a previously defined
variable. For example:
float total=100;
float &sum = total;
It means both total and sum are the same variables.
cout<< total;
cout << sum;
Both are going to give the same value, 100. Here the & operator is not the address operator; float
& means a reference to float.
C++ references differ from pointers in several essential ways:
A pointer can be re-assigned any number of times while a reference cannot be reassigned
after binding.
Pointers can point nowhere (NULL), whereas reference always refer to an object.
You can't take the address of a reference like you can with pointers.
Page 6
EC6301 / OOPS AND DS BE (ECE) III Sem / II Year
Function declarations;
public :
Variable declarations;
Function declarations;
};
Example
class student
{
int rno;
int age;
public :
void get(int a,int b);
void put();
};
Creating Objects
Once a class has been declared, we can create variables of that type by using the class
name.
student s;
We may also declare more than one object in one statement.
student s1,s2,s3;
Accessing Class members
The private data of a class can be accessed only through the member functions of that
class.
objectname.functionname(actual arguments);
For example,
The function call statement
s.get(100,12);
s.put();
Page 7
EC6301 / OOPS AND DS BE (ECE) III Sem / II Year
Page 8
EC6301 / OOPS AND DS BE (ECE) III Sem / II Year
int f(int n) {
int z;
...
{ /* block A */
int m;
...
}
Page 9
EC6301 / OOPS AND DS BE (ECE) III Sem / II Year
}
void main()
{
int y;
...
}
variable x is accessible throughout the program, n and z are accessible throughout
function f (but not within function main), and variable m is accessible within block A (but not
accessible anywhere outside block A). Variable y is accessible only within function main. Thus
the scope of variable y is the block for function main, the scope of variable m is block A, and the
scope of variable x is the entire program.
Global and Local Scope
In general, global scope applies to an entire program and local scope is restricted to a
component, such as a function or block, of a program.
Thus x is global in the above code, while n and z are local to function f and m is local to
block A.
Some of the terms that are used for access privileges to identifiers defined in a class
definition are:
public: the identifier is accessible to any code anywhere
protected: the identifier is accessible only within the methods of the class in which it is defined
and in the methods of every subclass
private: the identifier is accessible only within the methods of the class in which it is defined.
The scope levels, in general, within a method of a class are
variables defined in the current block (if any);
variables defined in the enclosing block, if there is an enclosing block; (This is repeated
until the outer block of the method body is reached.)
parameters;
instance variables and class variables;
global variables (if allowed in the language).
For example, in the class definition
Page 10
EC6301 / OOPS AND DS BE (ECE) III Sem / II Year
class foo {
int x, m;
Page 11
EC6301 / OOPS AND DS BE (ECE) III Sem / II Year
public:
A(); //Constructor
};
While defining a constructor you must remember that the name of constructor will be
same as the name of the class, and constructors never have return type.
Constructors can be defined either inside the class definition or outside the class
definition using class name and scope resolution :: operator.
class A
{
int i;
public:
A(); //Constructor declared
};
A::A() //Constructor definition
{
i=1;
}
The constructor functions have some special characteristics:
They should be declared in public section.
They are invoked automatically when the objects are created.
They do not have return types, and they cannot return values.
It has the same name as that of the class to which it belongs.
Types of Constructors
1. Default Constructor
2. Parameterized Constructor
3. Copy Constructor
4. Dynamic Constructor
1. Default Constructor
Default constructor is the constructor which doesn't take any argument. It has no
parameter.
Page 12
EC6301 / OOPS AND DS BE (ECE) III Sem / II Year
Syntax :
class_name ()
{ Constructor Definition }
Example :
class Cube
{
int side;
public:
Cube()
{
side=10;
}
};
void main()
{
Cube c;
cout << c.side;
}
Output : 10
In this case, as soon as the object is created the constructor is called which initializes its
data members.
A default constructor is so important for initialization of object members, that even if we
do not define a constructor explicitly, the compiler will provide a default constructor implicitly.
2. Parameterized Constructor
These are the constructors with parameter. Using this Constructor you can provide
different values to data members of different objects, by passing the appropriate values as
argument.
Example:
class Cube
{
Page 13
EC6301 / OOPS AND DS BE (ECE) III Sem / II Year
int side;
public:
Cube(int x)
{
side=x;
}
};
void main()
{
Cube c1(10);
Cube c2(20);
Cube c3(30);
cout << c1.side;
cout << c2.side;
cout << c3.side;
}
Output : 10 20 30
By using parameterized constructor in above case, we have initialized 3 objects with user
defined values. We can have any number of parameters in a constructor.
3. Copy Constructor
These are special type of Constructors which takes an object as argument, and is used to
copy values of data members of one object into other object.
Example:
class Cube
{
int side;
public:
Cube()
{
side=10;
Page 14
EC6301 / OOPS AND DS BE (ECE) III Sem / II Year
}
};
void main()
{
Cube c;
Cube c1(c);
cout << c.side;
cout<<c1.side;
}
Output: 10 10
4. Dynamic Constructor
This constructor is used to allocate the memory to the objects at the run time.The memory
allocation to objects is allocated with the help of 'new' operator.By using this constructor, we can
dynamically initialize the objects.
Example :
#include <iostream.h>
#include <conio.h>
class Account
{
private:
int account_no;
int balance;
public :
Account(int a,int b)
{
account_no=a;
balance=b;
}
void display()
{
Page 15
EC6301 / OOPS AND DS BE (ECE) III Sem / II Year
1.7 DESTRUCTORS
Destructor is a special class function which destroys the object as soon as the scope of
object ends. The destructor is called automatically by the compiler when the object goes out of
scope.
The syntax for destructor is same as that for the constructor, the class name is used for the name
of destructor, with a tilde ~ sign as prefix to it. Destructors will never have any arguments.
Syntax:
class A
{
Page 16
EC6301 / OOPS AND DS BE (ECE) III Sem / II Year
public:
~A();
};
Example:
class A
{
A()
{
cout << "Constructor called";
}
~A()
{
cout << "Destructor called";
}
};
void main()
{
A obj1; // Constructor Called
int x=1;
if(x)
{
A obj2; // Constructor Called
} // Destructor Called for obj2
} // Destructor called for obj1 Output:
Constructor called
Constructor called
Destructor called
Destructor called
Page 17
EC6301 / OOPS AND DS BE (ECE) III Sem / II Year
Page 18
EC6301 / OOPS AND DS BE (ECE) III Sem / II Year
width = wid;
}
// Note: printWidth() is not a member function of any
class. void printWidth( Box box )
{
/* Because printWidth() is a friend of Box, it can directly access any member of this class
*/ cout << "Width of box : " << box.width <<endl;
}
void main( )
{
Box box;
box.setWidth(10.0);
// Use friend function to print the width.
printWidth( box );
}
When the above code is compiled and executed, it produces the following result:
Width of box : 10
Page 19
EC6301 / OOPS AND DS BE (ECE) III Sem / II Year
If creating an array dynamically, use the same form, but put brackets with a size after the
type:
new int[40]; // dynamically allocates an array of 40 ints
new double[size]; // dynamically allocates an array of size doubles
// note that the size can be a variable
These statements above are not very useful by themselves, because the allocated spaces
have no names! BUT, the new operator returns the starting address of the allocated space, and
this address can be stored in a pointer:
int * p; // declare a pointer p
p = new int; // dynamically allocate an int and load address into p
De-allocation
Deallocation is the "clean-up" of space being used for variables or other data storage.
Compile time variables are automatically deallocated based on their known extent (this is the
same as scope for "automatic" variables). It is the programmer's job to deallocate dynamically
created space
To de-allocate dynamic memory, we use the delete operator
int * ptr = new int; // dynamically created int
delete ptr; // deletes the space that ptr points to
Example
#include <iostream.h>
void main()
{
double * pvalue = NULL; // Pointer initialized with null
pvalue = new double; // Request memory for the variable
*pvalue = 29494.99; // Store value at allocated address
cout<< "Value of pvalue : " << *pvalue<<endl; delete
pvalue; // free up the memory.
}
Page 20
EC6301 / OOPS AND DS BE (ECE) III Sem / II Year
Page 21
EC6301 / OOPS AND DS BE (ECE) III Sem / II Year
{
cout<< “Count : “ << count;
}
};
void main()
{
test t1,t2,t3;
t1.setcode();
t2.setcode();
test :: showcount();
test t3;
t3.setcode();
test :: showcount();
t1.showcode();
t2.showcode();
t3.showcode();
}
Ouput
Count : 2
Count : 3
Object number : 1
Object number : 2
Object number : 3
Page 22
EC6301 / OOPS AND DS BE (ECE) III Sem / II Year
Container
The STL contains many different container classes that can be used in different
situations. Generally speaking, the container classes fall into three basic categories: Sequence
containers, Associative containers, and Container adapters.
Sequence Containers
Sequence contains are container classes that maintain the ordering of elements in the
container. A defining characteristic of sequence containers is that you can choose where to insert
your element by position. The most common example of a sequence container is the array: if you
insert four elements into an array, the elements will be in the exact order you inserted them. The
STL contains 3 sequence containers: vector, deque, and list.
vector class in the STL is a dynamic array capable of growing as needed to contain its
elements. The vector class allows random access to its elements via operator[], and
inserting and removing elements from the end of the vector is generally fast.
The deque class (pronounced “deck”) is a double-ended queue class, implemented as a
dynamic array that can grow from both ends.
A list is a special type of sequence container called a doubly linked list where each
element in the container contains pointers that point at the next and previous elements in
the list. Lists only provide access to the start and end of the list -- there is no random
access provided
Page 23
EC6301 / OOPS AND DS BE (ECE) III Sem / II Year
The following program inserts 6 numbers into a vector and uses the overloaded [] operator to
access them in order to print them.
Example
#include <vector.h>
#include <iostream.h>
void main()
{
vector<int>vect;
for (int nCount=0; nCount< 6; nCount++)
vect.push_back(10 - nCount); // insert at end of array
for (int nIndex=0; nIndex<vect.size(); nIndex++)
cout<<vect[nIndex] << " ";
}
Output
10 9 8 7 6 5
Associative Containers
Associative contains are containers that automatically sort their inputs when those inputs
are inserted into the container. By default, associative containers compare elements using
operator<. A set is a container that stores unique elements, with duplicate elements disallowed.
The elements are sorted according to their values.
A multiset is a set where duplicate elements are allowed.
A map (also called an associative array) is a set where each element is a pair, called a
key/value pair. The key is used for sorting and indexing the data, and must be unique.
The value is the actual data.
A multimap (also called a dictionary) is a map that allows duplicate keys. Real-life
dictionaries are multimaps: the key is the word, and the value is the meaning of the word.
All the keys are sorted in ascending order, and you can look up the value by key. Some
words can have multiple meanings, which is why the dictionary is a multimap rather than
a map.
Page 24
EC6301 / OOPS AND DS BE (ECE) III Sem / II Year
Container Adapters
Container adapters are special predefined containers that are adapted to specific uses. The
interesting part about container adapters is that you can choose which sequence container you
want them to use.
A stack is a container where elements operate in a LIFO (Last In, First Out) context,
where elements are inserted (pushed) and removed (popped) from the end of the
container. Stacks default to using deque as their default sequence container (which seems
odd, since vector seems like a more natural fit), but can use vector or list as well.
A queue is a container where elements operate in a FIFO (First In, First Out) context,
where elements are inserted (pushed) to the back of the container and removed (popped)
from the front. Queues default to using deque, but can also use list.
A priority queue is a type of queue where the elements are kept sorted (via operator<).
When elements are pushed, the element is sorted in the queue. Removing an element
from the front returns the highest priority item in the priority queue.
Iterator
An Iterator is an object that can traverse (iterate over) a container class without the user
having to know how the container is implemented. With many classes (particularly lists and the
associative classes), iterators are the primary way elements of these classes are accessed.
An iterator is best visualized as a pointer to a given element in the container, with a set of
overloaded operators to provide a set of well-defined functions:
* Dereferencing the iterator returns the element that the iterator is currently pointing
at.
++ Moves the iterator to the next element in the container. Most iterators also
provide Operator-- to move to the previous element.
=Assign the iterator to a new position (typically the start or end of the container‟s
elements). To assign the value of the element the iterator is point at, deference the iterator first,
then use the assign operator.
== and != Basic comparison operators to determine if two iterators point to the same element.
To compare the values that two iterators are pointing at, deference the iterators first, and then use
a comparison operator.
Page 25
EC6301 / OOPS AND DS BE (ECE) III Sem / II Year
Each container includes four basic member functions for use with Operator=:
begin() returns an iterator representing the beginning of the elements in the container.
end() returns an iterator representing the element just past the end of the elements.
cbegin() returns a const (read-only) iterator representing the beginning of the elements in
the container.
cend() returns a const (read-only) iterator representing the element just past the end of the
elements.
Finally, all containers provide (at least) two types of iterators:
container::iterator - provides a read/write iterator
container::const_iterator- provides a read-only iterator
//Iterating through a vector
#include <iostream.h>
#include <vector.h>
void main()
{
vector<int>vect;
for (intnCount=0; nCount< 6; nCount++)
vect.push_back(nCount);
vector<int>::const_iterator it; // declare an read-only
iterator it = vect.begin(); // assign it to the start of the vector
while (it != vect.end()) // while it hasn't reach the end
{
cout<< *it << " "; // print the value of the element it points to
it++; // and iterate to the next element
}
cout<<endl;
}
Output
012345
Page 26
EC6301 / OOPS AND DS BE (ECE) III Sem / II Year
Page 27
EC6301 / OOPS AND DS BE (ECE) III Sem / II Year
cout << " drawing image " << m_id << '\n';
}
};
// 1. Design an "extra level of indirection" wrapper class
class Image
{
// 2. The wrapper class holds a pointer to the real
class RealImage *m_the_real_thing;
int m_id;
static int s_next;
public:
Image()
{
m_id = s_next++;
// 3. Initialized to null
m_the_real_thing = 0;
}
~Image()
{
delete m_the_real_thing;
}
void draw()
{
// 4. When a request comes in, the real object is created "on first use"
if (!m_the_real_thing)
m_the_real_thing = new RealImage(m_id);
// 5. The request is always delegated
m_the_real_thing->draw();
}
};
Page 28
EC6301 / OOPS AND DS BE (ECE) III Sem / II Year
int Image::s_next = 1;
void main()
{
Image images[5];
for (int i; true;)
{
cout << "Exit[0], Image[1-5]: ";
cin >> i;
if (i == 0)
break;
images[i - 1].draw();
}
}
Output
Exit[0], Image[1-5]: 2
$$ ctor: 2
drawing image 2
Exit[0], Image[1-5]: 4
$$ ctor: 4
drawing image 4
Exit[0], Image[1-5]: 2
drawing image 2
Exit[0], Image[1-5]: 0
dtor: 4
dtor: 2
Page 29
EC6301 / OOPS AND DS BE (ECE) III Sem / II Year
Page 30
EC6301 / OOPS AND DS BE (ECE) III Sem / II Year
2. Declare the operator function operator op() in the public part of the class. It may be
either a member function or a friend function.
3. Define the operator function to implement the required operations.
Almost any operator can be overloaded in C++. However there are few operator which
cannot be overloaded. Operators that are nor overloaded as follows.
Scope Resolution Operator (::)
size-of Operator
member selector(.)
member pointer selector(*)
ternary operator (?:)
Overloading unary operator
A minus operator when used as a unary, takes just one operand. We know that this
operator changes the sign of an operand when applied to a basic data item.
Example
class sample
{
int a;
int b;
public :
void get(intx,int y)
{
a=x;
b=y;
}
voiddisp()
{
cout<< a << “\n”;
cout<< b;
}
void operator –()
Page 31
EC6301 / OOPS AND DS BE (ECE) III Sem / II Year
{
a = -a;
b = -b;
}
};
void main()
{
sample s;
s.get(10,20);
s.disp();
-s;
s.disp();
}
Output
10 20
-10-20
Overloading binary operator
The same mechanism of unary operator is used to overload a binary operator.
Example
class sample
{
int a;
int b;
public :
sample()
{}
sample(intx,int y)
{
a=x;
b=y;
Page 32
EC6301 / OOPS AND DS BE (ECE) III Sem / II Year
}
sample operator +(sample s)
{
sample t;
t.a=a+s.a;
t.b=b+s.b;
return(t);
}
voiddisp()
{
cout<< a << “\t” << b;
}
};
void main()
{
sample s1,s2,s3;
s1=sample(10,10);
s2=sample(10,10);
s3=s1+s2;
cout<< s1.disp();
cout<< s2.disp();
cout<< s3.disp();
}
Output
10 10
10 10
20 20
Function Overloading
Function overloading allows you to use the same name for different functions, to
perform, either same or different functions in the same class.
Page 33
EC6301 / OOPS AND DS BE (ECE) III Sem / II Year
Function overloading is usually used to enhance the readability of the program. If you
have to perform one single operation but with different number or types of arguments then you
can simply overload the function.
Example
#include<iostream.h>
int sum(int x,int y)
{
return x+y;
}
int sum(int x,int y, int z)
{
return x+y+z;
}
void main()
{
int a=sum(3,4);
cout<< a;
int b=sum(3,4,5);
cout<< b;
}
Output
7
12
Page 34
EC6301 / OOPS AND DS BE (ECE) III Sem / II Year
UNIT II
Syllabus: Base Classes and Derived Classes – Protected Members – Casting Class pointers and
Member Functions – Overriding – Public, Protected and Private Inheritance – Constructors and
Destructors in derived Classes – Implicit Derived – Class Object To Base – Class Object
Conversion – Composition Vs. Inheritance – Virtual functions – This Pointer – Abstract Base
Classes and Concrete Classes – Virtual Destructors – Dynamic Binding.
Page 35
EC6301 / OOPS AND DS BE (ECE) III Sem / II Year
Single Inheritance
A derived class with only one base class, is called single inheritance.
Example
#include<iostream.h>
#include<conio.h>
class A
{
public:
int a;
int b;
public:
void get()
{
cout<< “Enter the value of a and b”;
cin>> a >> b;
}
};
class B: public A
{
public:
int c;
public:
void add()
{
c = a + b;
cout<< “Sum=” << c;
}
};
void main()
Page 36
EC6301 / OOPS AND DS BE (ECE) III Sem / II Year
{
B b;
b.get();
b.add();
getch();
}
Output
Enter the value of a and b : 4 5
Sum = 9
Multiple inheritance
Deriving a class from more than one direct base class is called multiple inheritance.
Example
#include<iostream.h>
#include<conio.h>
class A
{
public:
int a;
public:
void geta()
{
cout<< “Enter the value of a ”;
cin>> a;
}
};
class B
{
public:
Page 37
EC6301 / OOPS AND DS BE (ECE) III Sem / II Year
int b;
public:
void getb()
{
cout<< “Enter the value of a ”;
cin>> b;
}
};
Page 38
EC6301 / OOPS AND DS BE (ECE) III Sem / II Year
Output
Enter the value of a : 4
Enter the value of b : 5
Sum = 9
Multilevel Inheritance
Deriving a class from another derived class is known as multilevel inheritance.
Example
#include<iostream.h>
#include<conio.h>
class A
{
public:
int a;
public:
void geta()
{
cout<< “Enter the value of a ”;
cin>> a;
}
};
class B : public A
{
public:
int b;
public:
void getb()
{
cout<< “Enter the value of a ”;
cin>> b;
Page 39
EC6301 / OOPS AND DS BE (ECE) III Sem / II Year
}
};
class C: public B
{
public:
int c;
public:
void add()
{
c = a + b;
cout<< “Sum=” << c;
}
};
void main()
{
C c;
c.geta();
c.getb();
c.add();
getch();
}
Output
Enter the value of a : 4
Enter the value of b : 5
Sum = 9
Hierarchical inheritance
Hierarchical inheritance is the process of deriving two or more classes from only one
base class.
Page 40
EC6301 / OOPS AND DS BE (ECE) III Sem / II Year
Example
#include<iostream.h>
#include<conio.h>
class A //Base Class
{
public:
int a,b;
void getnumber()
{
cout<<"\n\nEnter Number :::\t";
cin>>a;
}
};
class B : public A //Derived Class 1
{
public:
void square()
{
getnumber(); //Call Base class property
cout<<"\n\n\tSquare of the number :::\t"<<(a*a);
cout<<"\n\n\t----------------------------------------------------";
}
};
class C :public A //Derived Class 2
{
public:
void cube()
{
getnumber(); //Call Base class property
cout<<"\n\n\tCube of the number :::\t"<<(a*a*a);
Page 41
EC6301 / OOPS AND DS BE (ECE) III Sem / II Year
}
};
void main()
{
B b1; //b1 is object of Derived class 1
b1.square(); //call member function of class B
C c1; //c1 is object of Derived class 2
c1.cube(); //call member function of class C
getch();
}
Output
Enter Number ::: 2
Square of the number :::4
Enter Number ::: 3
Cube of the number :::9
Hybrid Inheritance
Hybrid Inheritance is a method where one or more types of inheritance are combined
together.
Example
#include<iostream.h>
class student
{
char name[10];
intrno;
public:
void getdata()
{
cout<<"\n Enter the name : ";
cin>> name;
cout<<" Enter rollno : ";
Page 42
EC6301 / OOPS AND DS BE (ECE) III Sem / II Year
cin>>rno;
}
void putdata()
{
cout<<"\n\tName = "<<name;
cout<<"\n\tRollno = "<<rno<<endl;
}
};
class test:public virtual student
{
protected:
float mark1, mark2;
public:
void getmarks()
{
cout<<" Enter Mark 1 : ";
cin>>mark1;
cout<<" Enter Mark 2 : ";
cin>>mark2;
}
void putmarks()
{
cout<<"\tMark1 = "<<mark1<<endl;
cout<<"\tMark2 ="<<mark2<<endl;
}
};
class sports:public virtual student
{
protected:
float score;
Page 43
EC6301 / OOPS AND DS BE (ECE) III Sem / II Year
public:
void getscore()
{
cout<<" Enter the score in sports:";
cin>>score;
}
Void putscore()
{
cout<<"\tScore = "<<score<<endl;
}
};
class result:public test,public sports
{
float total;
public:
void display()
{
total=mark1+mark2+score;
putdata();
putmarks();
putscore();
cout<<"\tTotal = "<<total<<endl;
}
};
void main()
{
clrscr();
result r;
r.getdata();
r.getmarks();
Page 44
EC6301 / OOPS AND DS BE (ECE) III Sem / II Year
r.getscore();
cout<<"\n\t\t Result ";
r.display();
getch();
}
Output
Enter the name : Sam
Enter rollno : 36
Enter Mark 1 : 92
Enter Mark 2 : 93
Enter the score in sports: 99
Result
Name = Sam
Rollno = 36
Mark1 = 92
Mark2 = 93
Score = 99
Total = 284
Virtual Base Class
Grandparent
Parent 1 Parent 2
Child
Page 45
EC6301 / OOPS AND DS BE (ECE) III Sem / II Year
Inheritance by the child might pose some problems. All the public and protected members of
„grandparent‟ are inherited into „child‟ twice, first via „parent1‟ again via „parent2‟. This means
child would have duplicate sets of the members inherited from „grandparent‟. This
introduces ambiguity and should be avoided.
The duplication of inherited members due to these multiple paths can be avoided by
making the common base class as virtual base class while declaring the direct or intermediate
base classes which is shown as follow:
class A //grandparent
{
………….
………….
………….
};
class B1 : virtual public A //parent1
{
………….
………….
………….
};
class B2 : virtual public A //parent2
{
………….
………….
………….
};
class C : public B1,public B2 //child
{
…………. // only one copy of A
…………. // will be inherited
………….
Page 46
EC6301 / OOPS AND DS BE (ECE) III Sem / II Year
};
When a class is made a virtual base class, C++ takes necessary care to see that only one
copy of that class is inherited, regardless of how many inheritance path exist between the virtual
base class and a derived class.
public:
// public members go
here protected:
// protected members go here
private:
// private members go here
};
The public members
A public member is accessible from anywhere outside the class but within a program.
You can set and get the value of public variables without any member function as shown in the
following example:
#include <iostream.h>
class Line
{
public:
double length;
Page 47
EC6301 / OOPS AND DS BE (ECE) III Sem / II Year
Page 48
EC6301 / OOPS AND DS BE (ECE) III Sem / II Year
By default all the members of a class would be private, for example in the following class
width is a private member, which means until you label a member, it will be assumed a private
member:
class Box
{
double width;
public:
double length;
void setWidth( double wid );
double getWidth( void );
};
Practically, we define data in private section and related functions in public section so
that they can be called from outside of the class as shown in the following program. #include
<iostream.h>
class Box
{
public:
double length;
void setWidth( double wid );
double getWidth( void );
private:
double width;
};
// Member functions definitions
double Box::getWidth(void)
{
return width ;
}
void Box::setWidth( double wid )
{
Page 49
EC6301 / OOPS AND DS BE (ECE) III Sem / II Year
width = wid;
}
// Main function for the
program void main( )
{
Box box;
// set box length without member function
box.length = 10.0; // OK: because length is public
cout << "Length of box : " << box.length <<endl;
// set box width without member function
// box.width = 10.0; // Error: because width is private
box.setWidth(10.0); // Use member function to set it.
cout << "Width of box : " << box.getWidth() <<endl;
}
When the above code is compiled and executed, it produces the following result:
Length of box : 10
Width of box : 10
The protected members
A protected member variable or function is very similar to a private member but it
provided one additional benefit that they can be accessed in child classes which are called
derived classes.
Following example is similar to above example and here width member will be accessible by any
member function of its derived class SmallBox.
#include <iostream.h>
class Box
{
protected:
double width;
};
class SmallBox:Box // SmallBox is the derived class.
Page 50
EC6301 / OOPS AND DS BE (ECE) III Sem / II Year
{
public:
void setSmallWidth( double wid );
double getSmallWidth( void );
};
// Member functions of child class
double SmallBox::getSmallWidth(void)
{
return width ;
}
void SmallBox::setSmallWidth( double wid )
{
width = wid;
}
// Main function for the program
void main( )
{
SmallBox box;
// set box width using member function
box.setSmallWidth(5.0);
cout << "Width of box : "<< box.getSmallWidth() << endl;
}
When the above code is compiled and executed, it produces the following result:
Width of box : 5
Page 51
EC6301 / OOPS AND DS BE (ECE) III Sem / II Year
Page 52
EC6301 / OOPS AND DS BE (ECE) III Sem / II Year
Public Inheritance
#include<iostream.h>
#include<conio.h>
class A
{
public:
int a;
int b;
public:
void get()
{
cout<< “Enter the value of a and b”;
cin>> a >> b;
}
};
class B: public A
{
public:
int c;
public:
void add()
{
c = a + b;
cout<< “Sum=” << c;
}
};
void main()
{
B b;
b.get();
Page 53
EC6301 / OOPS AND DS BE (ECE) III Sem / II Year
b.add();
getch();
}
Output
Enter the value of a and b : 4 5
Sum = 9
Private Inheritance
#include<iostream.h>
#include<conio.h>
class A
{
public:
int a;
int b;
public:
void get()
{
cout<< “Enter the value of a and b”;
cin>> a >> b;
}
};
class B: private A
{
public:
int c;
public:
void add()
{
c = a + b;
cout<< “Sum=” << c;
Page 54
EC6301 / OOPS AND DS BE (ECE) III Sem / II Year
}
};
void main()
{
B b;
b.get();
b.add();
getch();
}
Output
Enter the value of a and b : 4 5
Sum = 9
Protected Inheritance
#include<iostream.h>
#include<conio.h>
class A
{
public:
int a;
int b;
public:
void get()
{
cout<< “Enter the value of a and b”;
cin>> a >> b;
}
};
class B: protected A
{
public:
Page 55
EC6301 / OOPS AND DS BE (ECE) III Sem / II Year
int c;
public:
void add()
{
c = a + b;
cout<< “Sum=” << c;
}
};
void main()
{
B b;
b.get();
b.add();
getch();
}
Output
Enter the value of a and b : 4 5
Sum = 9
2.4 OVERRIDING
If base class and derived class have member functions with same name and arguments
or if you create an object of derived class and write code to access that member function then,
the member function in derived class is only invoked, i.e., the member function of derived class
overrides the member function of base class. This feature in C++ programming is known as
function overriding.
Page 56
EC6301 / OOPS AND DS BE (ECE) III Sem / II Year
Page 57
EC6301 / OOPS AND DS BE (ECE) III Sem / II Year
Page 58
EC6301 / OOPS AND DS BE (ECE) III Sem / II Year
{
int a;
public :
sample(int a)
{
this->a=a;
}
voiddisp()
{
cout<< “A=” << a;
cout<< this;
}
};
void main()
{
sample s(2);
s.disp();
}
Output
A=2
Page 59
EC6301 / OOPS AND DS BE (ECE) III Sem / II Year
implements the concept of virtual function as a simple member function, like all member
functions of the class.
Properties of Virtual Functions
Virtual Functions are resolved during run-time or dynamic binding. Virtual functions are
also simple member functions. The main difference between a non-virtual C++ member function
and a virtual member function is in the way they are both resolved. A non-virtual C++ member
function is resolved during compile time or static binding. Virtual Functions are resolved during
run-time or dynamic binding. Virtual functions are member functions of a class. Virtual
functions are declared with the keyword virtual. Virtual function takes a different functionality in
the derived class.
Example
#include<iostream.h>
#include<conio.h>
class base
{
public:
virtual void show()
{
cout<<"\n Base class show:";
}
void display()
{
cout<<"\n Base class display:" ;
}
};
class drive : public base
{
public:
void display()
{
Page 60
EC6301 / OOPS AND DS BE (ECE) III Sem / II Year
Page 61
EC6301 / OOPS AND DS BE (ECE) III Sem / II Year
Page 62
EC6301 / OOPS AND DS BE (ECE) III Sem / II Year
Page 63
EC6301 / OOPS AND DS BE (ECE) III Sem / II Year
Page 64
EC6301 / OOPS AND DS BE (ECE) III Sem / II Year
Page 65
EC6301 / OOPS AND DS BE (ECE) III Sem / II Year
Concrete c(s);
c. printContent();
}
#include< iostream.h>
class Base
{
public:
Base()
{
cout<<"Constructing Base";
}
// this is a destructor:
~Base()
{
cout<<"Destroying Base";
}
};
class Derive: public Base
{
public:
Derive()
Page 66
EC6301 / OOPS AND DS BE (ECE) III Sem / II Year
{
cout<<"Constructing Derive";
}
~Derive(){ cout<<"Destroying Derive";}
};
void main()
{
Base *basePtr = new Derive();
delete basePtr;
}
Constructing Base
Constructing Derive
Destroying Base
Based on the output above, we can see that the constructors get called in the appropriate
order when we create the Derive class object pointer in the main function. But there is a major
problem with the code above: the destructor for the "Derive" class does not get called at all when
we delete „basePtr‟.
So, how can we fix this problem? we can make the base class destructor virtual, and that
will ensure that the destructor for any class that derives from Base (in our case, its the "Derive"
class) will be called.
]
Example with a Virtual Destructor
So, the only thing we will need to change is the destructor in the Base class and here‟s
what it will look like:
class Base
{
Page 67
EC6301 / OOPS AND DS BE (ECE) III Sem / II Year
public:
Base(){ cout<<"Constructing Base";}
Now, with that change, the output after running the code above will be:
Constructing Base
Constructing Derive
Destroying Derive
Destroying Base
Note that the derived class destructor will be called before the base class. One important
design paradigm of class design is that if a class has one or more virtual functions, then that class
should also have a virtual destructor.
Page 68
EC6301 / OOPS AND DS BE (ECE) III Sem / II Year
Page 69
EC6301 / OOPS AND DS BE (ECE) III Sem / II Year
Page 70
EC6301 / OOPS AND DS BE (ECE) III Sem / II Year
public:
void rollup() const {}
void rolldown() const {}
};
class Door {
public:
Window window;
void open() const {}
void close() const {}
};
class Car {
public:
Engine engine;
Wheel wheel[4];
Door left, right; // 2-door
};
void main() {
Car car;
car.left.window.rollup();
car.wheel[0].inflate(72);
}
Inheritance is a way to form new classes (instances of which are called objects) using
classes that have already been defined. One class can use features from another class to extend
its functionality (an “Is a” relationship) i.e., a Car is a Automobile.
Page 71
EC6301 / OOPS AND DS BE (ECE) III Sem / II Year
pointer is a type of pointer that points to a function instead of a variable. The function that a
function pointer points to can be called by using the function call operator (()) on the pointer. For
example, the following code calls the Add() function:
#include<iostream.h>
#include<conio.h>
int Add(int nX, int nY)
{
return nX + nY;
}
int main()
{
clrscr();
// Create a function pointer and make it point to the Add
function int (*pFcn)(int, int) = Add;
cout << pFcn(5, 3) << endl; // add 5 + 3
return 0;
}
Calling a function via a function pointer is also known as an indirect function call. The
following calculator program is functionally identical to the calculator example above, except it
uses a function pointer instead of a direct function call:
#include <iostream.h>
#include<conio.h>
int Add(int nX, int nY)
{
return nX + nY;
}
int Subtract(int nX, int nY)
{
return nX - nY;
}
Page 72
EC6301 / OOPS AND DS BE (ECE) III Sem / II Year
Page 73
EC6301 / OOPS AND DS BE (ECE) III Sem / II Year
}
In this example, instead of calling the Add(), Subtract(), or Multiply() function directly,
we‟ve instead set pFcn to point at the function we wish to call. Then we call the function through
the pointer. The compiler is unable to use early binding to resolve the function call pFcn(nX, nY)
because it cannot tell which function pFcn will be pointing to at compile time!
Page 74
EC6301 / OOPS AND DS BE (ECE) III Sem / II Year
play(sq);
Upcasting allows us to treat a derived type as though it were its base type. Here the
assumption is "You're a Shape, I know you can move(), draw(), and shrink( ) yourself, do it, and
take care of the details correctly." Thus, the objects of all the classes are passed to the function
shape.
class Parent {
public:
void sleep() {}
};
class Child: public Parent {
public:
void gotoSchool(){}
};
int main( )
{
Parent parent;
Child child;
// upcast - implicit type cast allowed
Parent *pParent = &child;
// downcast - explicit type case
required Child *pChild = (Child *)
&parent; pParent -> sleep();
pChild -> gotoSchool();
return 0;
}
A Child object is a Parent object in that it inherits all the data members and member
functions of a Parent object. So, anything that we can do to a Parent object, we can do to a Child
object. Therefore, a function designed to handle a Parent pointer (reference) can perform the
same acts on a Child object without any problems. The same idea applies if we pass a pointer
Page 75
EC6301 / OOPS AND DS BE (ECE) III Sem / II Year
Page 76
EC6301 / OOPS AND DS BE (ECE) III Sem / II Year
Page 77
EC6301 / OOPS AND DS BE (ECE) III Sem / II Year
UNIT III
LINEAR DATA STRUCTURES
Syllabus: Abstract Data Types (ADTs) – List ADT – array-based implementation – linked list
implementation –– singly linked lists –Polynomial Manipulation - Stack ADT – Queue ADT -
Evaluating arithmetic expressions.
Page 78
EC6301 / OOPS AND DS BE (ECE) III Sem / II Year
Non Linear Data structure don‟t have a linear relationship between its adjacent elements.
Each node may point to several nodes. But in linear data structure, each node has a link which
points to another node.
Ex : Tree , Graph
Abstract Data Type (ADT)
A data type that is defined entirely by a set of operations is referred to as an ADT. An
ADT is a combination of interface and implementation. The interface defines the logical
properties of an ADT and especially the signature of its operations.
The implementation defines the representation of the data structure and the algorithm that
implements the operations.
Linear Data Structures
There are two methods by which we can construct a linear data structure. They are,
Method 1: By using a sequence of memory locations. These are implemented using arrays.
Method 2: By using pointers or links. These are implemented using linked lists.
The different types of linear data structures are:
Lists
The list can be implemented using arrays and pointers.
Stacks
The stacks can be implemented using arrays and linked lists.
Queues
The queue can be implemented using arrays and linked lists.
Non-Linear Data Structures
Non-linear data structure don‟t have a linear relationship between its adjacent elements.
Each node may point to several nodes. But in linear data structure ,each node has a link which
points to another node.
Example
Tree, Graph.
Tree
A tree is a non-linear data structure that may point to one (or) more nodes at a time.
Page 79
EC6301 / OOPS AND DS BE (ECE) III Sem / II Year
Graph
A graph is similar to tree except that it has no hierarchical relationship between its adjacent
elements.
Page 80
EC6301 / OOPS AND DS BE (ECE) III Sem / II Year
#include<stdio.h>
#include<conio.h>
#define MAX 20 //maximum no of elements in the list
//user defined datatypes
struct list
{
int list[MAX];
int element; //new element to be inserted
int pos; //position of the element to be inserted or deleted
int length; //total no of elements
}l;
enum boolean { true, false };
typedef enum boolean boolean;
void main()
{
int ch;
int element;
int pos;
l.length = 0;
while(1)
{
ch = menu();
switch (ch)
{
case 1:
l.length = 0;
create();
break;
case 2:
if (islistfull() != true)
Page 81
EC6301 / OOPS AND DS BE (ECE) III Sem / II Year
{
printf("\tEnter the New element : ");
scanf("%d", &element);
printf("\tEnter the Position : ");
scanf("%d", &pos);
insert(element, pos);
}
else
{
printf("\tList if Full. Cannot insert");
printf("\nPress any key to continue...");
getch();
}
break;
case 3:
if (islistempty() != true)
{
printf("Enter the position of element to be deleted : ");
scanf("%d", &pos);
delet(pos);
}
else
{
printf("List is Empty.");
printf("\nPress any key to continue...");
getch();
}
break;
case 4:
printf("No of elements in the list is %d", l.length);
Page 82
EC6301 / OOPS AND DS BE (ECE) III Sem / II Year
Page 83
EC6301 / OOPS AND DS BE (ECE) III Sem / II Year
Page 84
EC6301 / OOPS AND DS BE (ECE) III Sem / II Year
int i;
if (pos == 0)
{
printf("\n\nCannot insert at zeroth position");
getch();
return;
}
if (pos-1 > l.length)
{
printf("\n\nOnly %d elements exit. Cannot insert at %d postion", l.length, pos);
printf("\nPress any key to continue...");
getch();
}
else
{
for (i=l.length; i>=pos-1; i--)
{
l.list[i+1] = l.list[i];
}
l.list[pos-1] = element;
l.length++;
}
}
/* function to delete the element at given position */
void delet(int pos)
{
int i;
Page 85
EC6301 / OOPS AND DS BE (ECE) III Sem / II Year
if(pos == 0)
{
printf("\n\nCannot delete at zeroth position");
getch();
return;
}
if (pos > l.length)
{
printf("\n\nOnly %d elements exit. Cannot delete", l.length,
pos); printf("\nPress any key to continue..."); getch();
return;
}
for (i=pos-1; i<l.length; i++)
{
l.list[i] = l.list[i+1];
}
l.length--;
}
/* function to find the position of the given element, if exists */
void find(int element)
{
int i;
int flag = 1;
for (i=0; i<l.length; i++)
{
if(l.list[i] == element)
{
printf ("%d exists at %d position",element, i+1);
flag = 0;
Page 86
EC6301 / OOPS AND DS BE (ECE) III Sem / II Year
Page 87
EC6301 / OOPS AND DS BE (ECE) III Sem / II Year
A Linked list is a collection of elements called nodes, each of which stores two items
called info and link. Info is an element of the list and a link is a pointer to the next element. The
linked list is also called a chain.
The different types of Linked lists are,
Singly linked list.
Doubly linked list
Circularly linked list
Singly Linked Lists
A singly linked list is a linked list in which each node contains only one link pointing to
the next node in the list.
In a singly linked list, the first node always pointed by a pointer called HEAD. If the link
of the node points to NULL, then that indicates the end of the list.
Operations of Singly Linked List
The following operations that can be performed on a singly linked list are,
Count the number of elements.
Add an element at the beginning of the list.
Add an element at the end of the list.
Insert an element at the specified position in the list.
Delete an element from the list.
Search x in the list.
Display all the elements of the list.
Example for insertion of an element
Initially the linked list consists of only one element 10.
10 NULL
head
Page 88
EC6301 / OOPS AND DS BE (ECE) III Sem / II Year
Next if we want to insert another element 20 into the linked list,then store the address of 20 in
the link part of 10.
10 20 NULL
head
Next if we want to insert another element 30 into the linked list,then store the address of 30 in
the link part of 20.
10 20 30 NULL
head
Example for deletion of an element
Now if we want to delete 20 from the linked list, just store the address of 30 in the link part of
10.
10 20 30 NULL
head
10 30 NULL
head
/* C++ Program to Implement Singly Linked List */
#include<iostream.h>
#include<stdlib.h>
/* Node Declaration */
struct node
{
int info;
struct node *next;
}*start;
/* Class Declaration */
class single_llist
Page 89
EC6301 / OOPS AND DS BE (ECE) III Sem / II Year
{
public:
node* create_node(int);
void insert_begin();
void insert_pos();
void insert_last();
void delete_pos();
void sort();
void search();
void update();
void reverse();
void display();
single_llist()
{
start =NULL;
}
};
/* Main :contains menu */
void main()
{
int choice, nodes, element, position, i;
single_llist sl;
start =NULL;
while(1)
{
cout<<endl<<"---------------------------------"<<endl;
cout<<endl<<"Operations on singly linked list"<<endl;
cout<<endl<<"---------------------------------"<<endl;
cout<<"1.Insert Node at beginning"<<endl;
cout<<"2.Insert node at last"<<endl;
Page 90
EC6301 / OOPS AND DS BE (ECE) III Sem / II Year
Page 91
EC6301 / OOPS AND DS BE (ECE) III Sem / II Year
cout<<endl;
break;
case5:
cout<<"Delete a particular node: "<<endl;
sl.delete_pos();
break;
case6:
cout<<"Update Node Value:"<<endl;
sl.update();
cout<<endl;
break;
case7:
cout<<"Search element in Link List: "<<endl;
sl.search();
cout<<endl;
break;
case8:
cout<<"Display elements of link list"<<endl;
sl.display();
cout<<endl;
break;
case9:
cout<<"Reverse elements of Link List"<<endl;
sl.reverse();
cout<<endl;
break;
case10:
cout<<"Exiting..."<<endl;
exit(1);
break;
Page 92
EC6301 / OOPS AND DS BE (ECE) III Sem / II Year
default:
cout<<"Wrong choice"<<endl;
}
}
}
/* Creating Node */
node *single_llist::create_node(int value)
{
struct node *temp, *s;
temp =new(struct node);
if(temp ==NULL)
{
cout<<"Memory not allocated "<<endl;
return0;
}
else
{
temp->info = value;
temp->next =NULL;
return temp;
}
}
/* Inserting element in beginning */
void single_llist::insert_begin()
{
int value;
cout<<"Enter the value to be inserted: ";
cin>>value;
struct node *temp, *p;
temp = create_node(value);
Page 93
EC6301 / OOPS AND DS BE (ECE) III Sem / II Year
if(start ==NULL)
{
start = temp;
start->next =NULL;
}
else
{
p = start;
start = temp;
start->next = p;
}
cout<<"Element Inserted at beginning"<<endl;
}
/* Inserting Node at last */
void single_llist::insert_last()
{
int value;
cout<<"Enter the value to be inserted: ";
cin>>value;
struct node *temp, *s;
temp = create_node(value);
s = start;
while(s->next !=NULL)
{
s = snext;
}
temp->next =NULL;
s->next = temp;
cout<<"Element Inserted at last"<<endl;
}
Page 94
EC6301 / OOPS AND DS BE (ECE) III Sem / II Year
Page 95
EC6301 / OOPS AND DS BE (ECE) III Sem / II Year
}
elseif(pos >1&& pos <= counter)
{
s = start;
for(i =1; i < pos; i++)
{
ptr = s;
s = s->next;
}
ptr->next = temp;
temp->next = s;
}
else
{
cout<<"Positon out of range"<<endl;
}
}
/* Sorting Link List */
void single_llist::sort()
{
struct node *ptr, *s;
int value;
if(start ==NULL)
{
cout<<"The List is empty"<<endl;
return;
}
ptr = start;
while(ptr !=NULL)
{
Page 96
EC6301 / OOPS AND DS BE (ECE) III Sem / II Year
Page 97
EC6301 / OOPS AND DS BE (ECE) III Sem / II Year
{
while(s !=NULL)
{
s = s->next;
counter++;
}
if(pos >0&& pos <= counter)
{
s = start;
for(i =1;i < pos;i++)
{
ptr = s;
s = s->next;
}
ptr->next = s->next;
}
else
{
cout<<"Position out of range"<<endl;
}
free(s);
cout<<"Element Deleted"<<endl;
}
}
/* Update a given Node */
void single_llist::update()
{
int value, pos, i;
if(start ==NULL)
{
Page 98
EC6301 / OOPS AND DS BE (ECE) III Sem / II Year
cout<<"List is empty"<<endl;
return;
}
cout<<"Enter the node postion to be updated: ";
cin>>pos;
cout<<"Enter the new value: ";
cin>>value;
struct node *s, *ptr;
s = start;
if(pos ==1)
{
start->info = value;
}
else
{
for(i =0;i < pos -1;i++)
{
if(s ==NULL)
{
cout<<"There are less than "<<pos<<" elements";
return;
}
s = s->next;
}
s->info = value;
}
cout<<"Node Updated"<<endl;
}
/* Searching an element */
void single_llist::search()
Page 99
EC6301 / OOPS AND DS BE (ECE) III Sem / II Year
{
int value, pos =0;
bool flag =false;
if(start ==NULL)
{
cout<<"List is empty"<<endl;
return;
}
cout<<"Enter the value to be searched: ";
cin>>value;
struct node *s;
s = start;
while(s !=NULL)
{
pos++;
if(s->info == value)
{
flag =true;
cout<<"Element "<<value<<" is found at position "<<pos<<endl;
}
s = s->next;
}
if(!flag)
cout<<"Element "<<value<<" not found in the list"<<endl;
}
/* Reverse Link List */
void single_llist::reverse()
{
struct node *ptr1, *ptr2, *ptr3;
if(start ==NULL)
Page 100
EC6301 / OOPS AND DS BE (ECE) III Sem / II Year
{
cout<<"List is empty"<<endl;
return;
}
if(start->next ==NULL)
{
return;
}
ptr1 = start;
ptr2 = ptr1->next;
ptr3 = ptr2->next;
ptr1->next =NULL;
ptr2->next = ptr1;
while(ptr3 !=NULL)
{
ptr1 = ptr2;
ptr2 = ptr3;
ptr3 = ptr3->next;
ptr2->next = ptr1;
}
start = ptr2;
}
/* Display Elements of a link list */
void single_llist::display()
{
struct node *temp;
if(start ==NULL)
{
cout<<"The List is Empty"<<endl;
return;
Page 101
EC6301 / OOPS AND DS BE (ECE) III Sem / II Year
}
temp = start;
cout<<"Elements of list are: "<<endl;
while(temp !=NULL)
{
cout<<temp->info<<"->";
temp = temp->next;
}
cout<<"NULL"<<endl;
}
APPLICATION OF LIST
POLYNOMIAL MANIPULATION
Polynomial addition, multiplication (8th degree polynomials) using arrays:
//Addition of Two Polynomial
#include <iostream.h>
#include <iomanip.h>
#include <conio.h>
struct poly{
int coeff;
int pow;
poly *next;
};
class add2poly
{
poly *poly1, *poly2, *poly3;
public:
add2poly(){poly1=poly2=poly3=NULL;}
void addpoly();
void display();
Page 102
EC6301 / OOPS AND DS BE (ECE) III Sem / II Year
};
void add2poly :: addpoly(){
int i,p;
poly *newl=NULL,*end=NULL;
cout<<"Enter highest power for x\n";
cin>>p;
//Read first poly
cout<<"\nFirst Polynomial\n";
for(i=p;i>=0;i--)
{
newl=new poly;
newl->pow=p;
cout<<"Enter Co-efficient for degree"<<i<<":: ";
cin>>newl->coeff;
newl->next=NULL;
if(poly1==NULL)
poly1=newl;
else
end->next=newl;
end=newl;
}
//Read Second poly
cout<<"\n\nSecond Polynomial\n";
end=NULL;
for(i=p;i>=0;i--)
{
newl=new poly;
newl->pow=p;
cout<<"Enter Co-efficient for degree"<<i<<":: ";
cin>>newl->coeff;
Page 103
EC6301 / OOPS AND DS BE (ECE) III Sem / II Year
newl->next=NULL;
if(poly2==NULL)
poly2=newl;
else
end->next=newl;
end=newl;
}
//Addition Logic
poly *p1=poly1,*p2=poly2;
end=NULL;
while(p1 !=NULL && p2!=NULL){
if(p1->pow == p2->pow){
newl=new poly;
newl->pow=p--;
newl->coeff=p1->coeff + p2->coeff;
newl->next=NULL;
if(poly3==NULL)
poly3=newl;
else
end->next=newl;
end=newl;
}
p1=p1->next;
p2=p2->next;
}
}
void add2poly :: display(){
poly *t=poly3;
cout<<"\n\nAnswer after addition is : ";
while(t!=NULL){
Page 104
EC6301 / OOPS AND DS BE (ECE) III Sem / II Year
cout.setf(ios::showpos);
cout<<t->coeff;
cout.unsetf(ios::showpos);
cout<<"X"<<t->pow;
t=t->next;
}
}
void main(){
clrscr();
add2poly obj;
obj.addpoly();
obj.display();
getch();
}
//Multiplication of 2 polynomials
#include <iostream.h>
class poly
{
private:
struct polynode
{
float coeff ;
intexp;
polynode*link ;
}*p ;
public:
poly();
void poly_append (float c, int e );
void display_poly();
Page 105
EC6301 / OOPS AND DS BE (ECE) III Sem / II Year
Page 106
EC6301 / OOPS AND DS BE (ECE) III Sem / II Year
polynode*temp = p ;
int f =0;
while( temp !=NULL)
{
if( f !=0)
{
if( temp -> coeff >0)
cout<<" + ";
else
cout<<" ";
}
if( temp ->exp!=0)
cout<< temp -> coeff <<"x^"<< temp ->exp;
else
cout<< temp -> coeff ;
temp= temp -> link ;
f =1;
}
}
void poly ::poly_multiply( poly &p1, poly &p2 )
{
polynode*temp1, *temp2 ;
float coeff1, exp1 ;
temp1 =p1.p;
temp2 =p2.p;
if( temp1 ==NULL&& temp2 ==NULL)
return;
if( temp1 ==NULL)
p =p2.p;
else
Page 107
EC6301 / OOPS AND DS BE (ECE) III Sem / II Year
{
if( temp2 ==NULL)
p =temp1 ;
else {
while( temp1 !=NULL)
{
while( temp2 !=NULL)
{
coeff1 = temp1 -> coeff * temp2 ->coeff ;
exp1 = temp1 ->exp+ temp2 ->exp;
temp2 = temp2 ->link ;
padd( coeff1, exp1 );
}
temp2 =p2.p;
temp1 = temp1 ->link ;
}
}
}
}
void poly ::padd(float c, int e )
{
polynode*r, *temp ;
temp= p ;
if( temp ==NULL|| c > temp ->exp)
{
r =newpolynode ;
r-> coeff = c ;
r->exp= e ;
if( p ==NULL)
{
Page 108
EC6301 / OOPS AND DS BE (ECE) III Sem / II Year
Page 109
EC6301 / OOPS AND DS BE (ECE) III Sem / II Year
Page 110
EC6301 / OOPS AND DS BE (ECE) III Sem / II Year
p3.poly_multiply( p1, p2 );
cout<<"\nResultant polynomial: "<< endl ;
p3.display_poly();
}
Logic
3 2
Polynomial A: 3x +2x +x+1
3
Polynomial B: 5x +7x
Step 1:
3 2
3x 2x x 1 A
i
3
5x 7x B
j
3
8x C
k
Step 2:
3 2
3x 2x x 1 A
i
3
5x 7x B
j
3 2
8x 2x C
k
Step 3:
3 2
3x 2x x 1 A
Page 111
EC6301 / OOPS AND DS BE (ECE) III Sem / II Year
i
3
5x 7x B
j
3 2
8x 2x 8x C
k
Step 4:
3 2
3x 2x x 1
i
3
5x 7x
j
3 2
8x 2x 8x 1
Page 112
EC6301 / OOPS AND DS BE (ECE) III Sem / II Year
Page 113
EC6301 / OOPS AND DS BE (ECE) III Sem / II Year
If arrays are used for implementing the stacks, it would be very easy to manage the
stacks.
However, the problem with an array is that we are required to declare the size of the array
before using it in a program.
This means the size of the stack should be fixed. We can declare the array with a
maximum size large enough to manage a stack.
As result, the stack can grow or shrink within the space reserved for it.
Pop operation
On deletion of elements the stack shrinks at the same end, as the elements at the top get removed.
Page 114
EC6301 / OOPS AND DS BE (ECE) III Sem / II Year
#include<iostream.h>
#include<conio.h>
#include<stdlib.h>
class stack
{
int stk[5];
int top;
public:
stack()
{
top=-1;
}
void push(int x)
{
if(top >4)
{
cout<<"stack over flow";
return;
}
stk[++top]=x;
cout<<"inserted"<<x;
}
void pop()
{
Page 115
EC6301 / OOPS AND DS BE (ECE) III Sem / II Year
if(top <0)
{
cout<<"stack under flow";
return;
}
cout<<"deleted"<<stk[top--];
}
void display()
{
if(top<0)
{
cout<<" stack empty";
return;
}
for(int i=top;i>=0;i--)
cout<<stk[i]<<" ";
}
};
main()
{
int ch;
stack st;
while(1)
{
cout<<"\n1.push 2.pop 3.display 4.exit\nEnter ur choice";
cin>> ch;
switch(ch)
{
case1:cout<<"enter the element";
Page 116
EC6301 / OOPS AND DS BE (ECE) III Sem / II Year
cin>> ch;
st.push(ch);
break;
case2: st.pop();break;
case3: st.display();break;
case4:exit(0);
}
}
return(0);
}
Implementation of Stack ADT using Linked Lists
The stack can be implemented by using the singly linked list. This type of the
representation has more advantage than representing stack using array.They are,
It is not necessary to specify the no of elements to be stored in a stack during its
declaration. (memory is allocated dynamically at run time when an element is added to
the stack).
Insertion and deletion can be handled easily and efficiently.
Linked list representation of stack can grow and shrink in size without wasting the
memory space depending upon the insertion and deletion that occurs in the list.
Initially, when the stack is empty, top points to NULL. When an element is added using the
push operation, top is made to point to the latest element whichever is added.
Push operation
Create a temporary node and store the value of x in the data part of the node.
Now make link part of temp point to Top and then top point to Temp. That will make the
new node as the topmost element in the stack.
Page 117
EC6301 / OOPS AND DS BE (ECE) III Sem / II Year
Pop operation
The data in the topmost node of the stack is first stored in a variable called item.
Then a temporary pointer is created to point to top. The top is now safely moved to the
next node below it in the stack.
Temp node is deleted and the item is returned.
#include<iostream.h>
#include<conio.h>
#include<stdlib.h>
class node
{
public:
class node *next;
int data;
};
class stack :public node
{
Page 118
EC6301 / OOPS AND DS BE (ECE) III Sem / II Year
node *head;
int tos;
public:
stack()
{
tos=-1;
}
void push(int x)
{
if(tos <0)
{
head =new node;
head->next=NULL;
head->data=x;
tos ++;
}
else
{
node *temp,*temp1;
temp=head;
if(tos >=4)
{
cout<<"stack over flow";
return;
}
tos++;
while(temp->next !=NULL)
temp=temp->next;
temp1=new node;
temp->next=temp1;
Page 119
EC6301 / OOPS AND DS BE (ECE) III Sem / II Year
temp1->next=NULL;
temp1->data=x;
}
}
void display()
{
node *temp;
temp=head;
if(tos <0)
{
cout<<" stack under flow";
return;
}
while(temp !=NULL)
{
cout<<temp->data<<" ";
temp=temp->next;
}
}
void pop()
{
node *temp;
temp=head;
if( tos <0)
{
cout<<"stack under flow";
return;
}
tos--;
while(temp->next->next!=NULL)
Page 120
EC6301 / OOPS AND DS BE (ECE) III Sem / II Year
{
temp=temp->next;
}
temp->next=NULL;
}
};
main()
{
stack s1;
int ch;
while(1)
{
cout<<"\n1.PUSH\n2.POP\n3.DISPLAY\n4.EXIT\n enter ur choice:";
cin>> ch;
switch(ch)
{
case1:cout<<"\n enter a element";
cin>> ch;
s1.push(ch);
break;
case2: s1.pop();break;
case3: s1.display();
break;
case4:exit(0);
}
}
return(0);
}
Applications of Stack ADT
Some of the applications of the stack include,
Page 121
EC6301 / OOPS AND DS BE (ECE) III Sem / II Year
Towers of Hanoi
Reversing the String
Recursion using stack
Evaluation of Arithmetic Expressions
Towers of Hanoi
Towers of Hanoi is a gaming puzzle.
Invented by French Mathematician Edouard Lucas in1883.
The objective of this puzzle is to transfer the entire disks from Tower1 to Tower3 using
Tower2.
The rules to be followed in moving the disks from tower1 to tower3 using tower2.
Only one disc can be moved at a time.
Only the top disc on any tower can be moved to any other tower.
A larger disc cannot be placed on a smaller disc.
It can be implemented using recursion. To move the largest disc to the bottom of tower3.
We move the remaining n-1 disks to tower2 and then move the largest disc to tower 3.
This process is continue until to place the entire disc in towerr3 in order.
Since, disc are moved from each tower in a LIFO manner each tower may be considered
as stack.
The least no of moves required to solve the problem according to our algorithm is given
by O(N)= 2N-1.
The time complexity is measured in no of movements.
Reversing the String
Main characteristics of the stack are reversing the order of its contents.
The tasks can be accomplished by pushing each character until the end of the string.
Now, the individual characters are popped off from the stack.
Since the last character pushed into the stack would be the first character to be popped off
from the stack.
The string will come off in the reverse order.
Page 122
EC6301 / OOPS AND DS BE (ECE) III Sem / II Year
Since, the individual character are moved from the stack in a LIFO manner, the stack
operation is implemented.
For example,The input string is Kumar. The output string is ramuk.
Recursion Using Stack:
Recursion is a process by which a function calls itself repeatedly until some specified
condition has been satisfied.
When a recursive program is executed, the recursive function calls are not executed
immediately.
They are placed on a stack (LIFO) until the condition that terminates the recursive
function.
The function calls are then executed in reverse order, as they are popped off the stack.
For example,
#include<stdio.h>
#include<conio.h>
void main()
{
int num,fac;
cout<<”Enter the no”;
cin>>num;
fac=fact(num);
printf(“The factorial val %d is”,fac);
}
int fact(int x)
{
if(x<=1)
return 1;
else
return (x*fact(x-1));
}
Evaluation of Arithmetic Expression
Page 123
EC6301 / OOPS AND DS BE (ECE) III Sem / II Year
Page 124
EC6301 / OOPS AND DS BE (ECE) III Sem / II Year
Fully, parenthesize the expression starting from left to right. (During parenthesizing the
operators having higher precedence are the first parenthesized)
Move the operators one by one to their right such that each operator replaces their
corresponding right parenthesize.
The part of the expression, which has been converted into postfix, is to be treated as
single operand.
Once, the expression is converted into postfix form remove all the paranthesis.
For example,
The infix expression is,
3 + 8 * 4 / 2 – (8 -3)
3+8*4/2–83-
3+84*/2–83–
3+84*2/ –83–
384*2/+-83–
384*2/+83--
The postfix expression is,3 8 4 * 2 / + 8 3 - -
Rules to be followed during infix to prefix conversion
Fully, parenthesize the expression starting from left to right. (During parenthesizing the
operators having higher precedence are the first parenthesized).
Move the operators one by one to their right such that each operator replaces their
corresponding right parenthesis.
The part of the expression, which has been converted into postfix, is to be treated as
single operand.
Once, the expression is converted into postfix form remove all the paranthesis.
3 + 8 * 4 / 2 - (8 - 3)
3+8*4/2 --83
+ *84/2 --83
+ /*842 --83
+3/*842 --83
+ 3/*842-83
Page 125
EC6301 / OOPS AND DS BE (ECE) III Sem / II Year
Page 126
EC6301 / OOPS AND DS BE (ECE) III Sem / II Year
Page 127
EC6301 / OOPS AND DS BE (ECE) III Sem / II Year
Deletion Insertion
Front Rear
Representation of Queue
Example
A Reservation Counter
Jobs in a printer
A queue of ready jobs waiting for the processor.
Basic Operations of Queue ADT
The basic operations that can be done on a queue are,
Enqueue()
Dequeue()
Enqueue()
An enqueue() operation adds a new element in a queue.
This process is carried out by incrementing the rear end and adding a new element at the
rear end position.
The syntax for inserting a new element into a queue is,
o Enqueue(Q,X) (or) Insert(Q,X)
The element 'X' inserted into a queue 'Q'.
Dequeue()
A dequeue() operation removes the first element from the queue.
A dequeue() operation is carried out by incrementing the front end and deleting the first
element at the front end position.
The syntax for removing a first element from the queue.
o Dequeue(Q) (or) Delete(Q)
Here, the first element is removed from the queue.
Types of Queue ADT
There are different types of queue.
Linear Queue
Circular Queue
Page 128
EC6301 / OOPS AND DS BE (ECE) III Sem / II Year
Deque
Linear Queue
A queue is referred to as the linear queue.
The queue has two ends such as front end and rear end.
The rear end is where we insert the elements and the front end is where we delete the
elements.
In a linear queue, we can traverse in only one direction.
In a linear queue if the front pointer is in first position, and the rear pointer is in the last
position then the queue is said to be fully occupied.
Initially, the front and rear ends are at the same position(Initialized to -1.)
When we insert the elements, the rear pointer moves one by one until the last index
position is reached.(the front pointer doesn't change.)
When we delete the elements, the front pointer moves one by one until the rear pointer is
reached.(the rear pointer doesn't change.)
If the front and rear pointer positions are initialized to -1, then the queue is said to be
empty.
Circular Queue
Circular Queue is another form of a linear queue in which the last position is connected to
the first position of the list.
It is similar to linear queue has two ends such as front and rear ends.
The rear end is where we insert the elements and front end is where we delete the
elements.
In a circular queue we can traverse in only one direction.
Initially, front and rear ends are at the same position.
When we insert an element, the rear pointer moves one by one until the front end is
reached.(front end doesn't change.)
If the next position of the rear is front, then the queue is said to be fully occupied.
When we delete an element, the front pointer moves one by one until the rear end is
reached.
If the front end reaches the rear end, then the queue is said to be empty.
Page 129
EC6301 / OOPS AND DS BE (ECE) III Sem / II Year
Represent
ation Of Deque
Implementation of Queue ADT
A queue can be implemented in two ways.
Array Implementation of Linear Queue.
Linked list Implementation Of linear Queue.
Page 130
EC6301 / OOPS AND DS BE (ECE) III Sem / II Year
Page 131
EC6301 / OOPS AND DS BE (ECE) III Sem / II Year
Dequeue( )
The dequeue ( ) operation deletes the element from the front of the queue.
Before deleting and element, it is checked if the queue is empty. If not the element
pointed by front is deleted from the queue and front is now made to point to the next
element in the queue.
Page 132
EC6301 / OOPS AND DS BE (ECE) III Sem / II Year
front=rear=-1;
return;
}
queue1[++rear]=x;
cout<<"inserted"<<x;
}
void delet()
{
if(front==rear)
{
cout<<"queue under flow";
return;
}
cout<<"deleted"<<queue1[++front];
}
void display()
{
if(rear==front)
{
cout<<" queue empty";
return;
}
for(int i=front+1;i<=rear;i++)
cout<<queue1[i]<<" ";
}
};
main()
{
int ch;
queue qu;
Page 133
EC6301 / OOPS AND DS BE (ECE) III Sem / II Year
while(1)
{
cout<<"\n1.insert 2.delet 3.display 4.exit\nEnter ur choice";
cin>> ch;
switch(ch)
{
case1:cout<<"enter the element";
cin>> ch;
qu.insert(ch);
break;
case2: qu.delet();break;
case3: qu.display();break;
case4:exit(0);
}
}
return(0);
}
Linked list implementation of queue
Queue can be represented using a linked list.
Linked lists do not have any restrictions on the number of elements it can hold.
Space for the elements in a linked list is allocated dynamically; hence it can grow as long
as there is enough memory available for dynamic allocation.
The queue represented using linked list would be represented as shown. The front pointer
points to the front of the queue and rear pointer points to the rear of the queue.
This representation has more advantages than representing queue using arrays.
The advantages are,
Page 134
EC6301 / OOPS AND DS BE (ECE) III Sem / II Year
Dequeue Operation
The dequeue( ) operation deletes the first element from the front end of the queue.
Initially it is checked, if the queue is empty. If it is not empty, then return the value in the node
pointed by front, and moves the front pointer to the next node.
#include<iostream.h>
#include<conio.h>
#include<stdlib.h>
class node
{
public:
class node *next;
int data;
};
class queue :public node
{
Page 135
EC6301 / OOPS AND DS BE (ECE) III Sem / II Year
node *head;
int front,rare;
public:
queue()
{
front=-1;
rare=-1;
}
void push(int x)
{
if(rare <0)
{
head =new node;
head->next=NULL;
head->data=x;
rare ++;
}
else
{
node *temp,*temp1;
temp=head;
if(rare >=4)
{
cout<<"queue over flow";
return;
}
rare++;
while(temp->next !=NULL)
temp=temp->next;
temp1=new node;
Page 136
EC6301 / OOPS AND DS BE (ECE) III Sem / II Year
temp->next=temp1;
temp1->next=NULL;
temp1->data=x;
}}
void display()
{
node *temp;
temp=head;
if(rare <0)
{
cout<<" queue under flow";
return;
}
while(temp !=NULL)
{
cout<<temp->data<<" ";
temp=temp->next;
}
}
void pop()
{
node *temp;
temp=head;
if( rare <0)
{
cout<<"queue under flow";
return;
}
if(front == rare)
Page 137
EC6301 / OOPS AND DS BE (ECE) III Sem / II Year
{
front = rare =-1;
head=NULL;
return;
}
front++;
head=head->next;
}
};
main()
{
queue s1;
int ch;
while(1)
{
cout<<"\n1.PUSH\n2.POP\n3.DISPLAY\n4.EXIT\n enter ru choice:";
cin>> ch;
switch(ch)
{
case1:
cout<<"\n enter a element";
cin>> ch;
s1.push(ch);break;
case2: s1.pop();break;
case3: s1.display();break;
case4:exit(0);
}
}
return(0);
Page 138
EC6301 / OOPS AND DS BE (ECE) III Sem / II Year
}
Applications Of Queue Adt
The applications of the queue such as,
Priority Queue
Scheduling Algorithms
Priority queue
A priority queue is a collection of elements in which the elements are added to the end
and the high priority element is deleted.
In a priority queue, each and every element containing the key referred as the priority for
the elements.
The operations performed in a queue are similar to the queue except that the insertion and
deletion elements made in it.
Elements can be inserted in any order, but are arranged in order of their priority value in
the queue.
The elements are deleted from the queue in the order of their priority.
The elements with the same priority are given equal importance and processed
accordingly.
The priority queue can be implemented in the following ways.
Ordered List Implementation of Priority Queue
Heap Implementation of Priority Queue
Applications of Priority Queue
Modeling of systems. Where the keys might correspond to event times, to be processed in
chronological order.
CPU scheduling in computer systems, where the keys might correspond to priorities
indicating which processes are to be served first.
Numerical computations, where the keys might be computational errors indicating that
the largest should be dealt with first.
Page 139
EC6301 / OOPS AND DS BE (ECE) III Sem / II Year
UNIT IV
NON LINEAR DATA STRUCTURES
Syllabus: Trees – Binary Trees – Binary tree representation and traversals – Application of trees:
Set representation and Union-Find operations – Graph and its representations – Graph Traversals
– Representation of Graphs – Breadth-first search – Depth-first search – Connected components.
Children
The nodes branching from a particular node X are called children of its parent.
Siblings
Children of the same parent are said to be siblings.
Degree of tree
Degree of the tree is the maximum of the degree of the nodes in the tree.
Page 140
EC6301 / OOPS AND DS BE (ECE) III Sem / II Year
Ancestors
Ancestors of a node are all the nodes along the path from root to that node. Hence root is
ancestor of all the nodes in the tree.
Level
Level of a node is defined by letting root at level one. If a node is at level L, then its
children are at level L + 1.
Height or depth
The height or depth of a tree is defined to be the maximum level of any node in the tree.
Climbing
The process of traversing the tree from the leaf to the root is called climbing the tree.
Descending
The process of traversing the tree from the root to the leaf is called descending the tree.
Right child
The node present to the right of the parent node is called the right child.
C
Complete binary tree
A binary tree in which every non leaf node has exactly two children not necessarily to
be on the same level.
A
B C
D E F G
H I
J K
Page 142
EC6301 / OOPS AND DS BE (ECE) III Sem / II Year
B C
D E
F G
Page 143
EC6301 / OOPS AND DS BE (ECE) III Sem / II Year
A B C D E F G
1 2 3 4 5 6 7
C D
A B C D
1 2 3 4 5 6 7
Linked Representation Of Binary Trees
In linked representation of binary trees, instead of arrays, pointers are used to connect the
various nodes of the tree. Hence each node of the binary tree consists of three parts namely, the
info, left and right. The info part stores the data, left part stores the address of the left child and
the right part stores the address of the right child. Logically the binary tree in linked form can be
represented as shown.
Page 144
EC6301 / OOPS AND DS BE (ECE) III Sem / II Year
Page 145
EC6301 / OOPS AND DS BE (ECE) III Sem / II Year
INORDER(left(temp))
End if
Print info(temp)
If right(temp) ≠ NULL
INORDER(right(temp))
End if
End INORDER
Postorder Traversal
Traverse the left subtree of N in postorder.
Traverse the right subtree of N in postorder.
Process the root N.
Algorithm ( Postorder)
POSTORDER( ROOT )
Temp = ROOT
If temp = NULL
Return
End if
If left(temp) ≠ NULL
POSTORDER(left(temp))
End if
If right(temp) ≠ NULL
POSTORDER(right(temp))
End if
Print info(temp)
End POSTORDER
Page 146
EC6301 / OOPS AND DS BE (ECE) III Sem / II Year
Example
Pre-order: F, B, A, D, C, E, G, I, H
In-order: A, B, C, D, E, F, G, H, I
Page 147
EC6301 / OOPS AND DS BE (ECE) III Sem / II Year
Post-order: A, C, E, D, B, H, I, G, F
Page 148
EC6301 / OOPS AND DS BE (ECE) III Sem / II Year
hasElt optimizes on hasElt on a plain binary tree: if the element you‟re looking for is not
in the root, the search recurs on only one of the left subtree (if the element to find is
smaller than that in the root) or the right subtree (if the element to find is larger than that
in the root).
addElt always inserts new elements at a leaf in the tree. It starts from the root, moving to
the left or right subtree as needed to maintain the invariant. When it hits a empty tree,
addElt replaces it with a new node with the data to add and two empty subtrees.
remElt traverses the BST until it finds the node with the element to remove at the root. If
the node has no children, remElt returns the empty tree. If the node has only one child,
remElt replaces it with its child node. If the node has two children, remElt replaces the
value in the node with either the largest element in the left subtree or the smallest element
in the right subtree; remElt then removes the moved node value from its subtree.
Union-Find Operations
Operations supported
Union( x, y ) - Performs a union o f the sets containing two elements x and y.
Find( x ) - Returns a pointer to the set Returns a pointer to the set containing element x.
Example applications
Electrical cable/internet connectivity network
Cities connected by roads
Cities belonging to the same country
Algorithm
function MakeSet(x)
x.parent := x
function Find(x)
if x.parent == x
return x
else
return Find(x.parent)
function Union(x, y)
xRoot := Find(x)
Page 149
EC6301 / OOPS AND DS BE (ECE) III Sem / II Year
yRoot := Find(y)
xRoot.parent := yRoot
B C
Undirected Graph
If the edge in a graph is not directionally oriented, then it is called undirected graph.
B C
Path
It is a sequence of vertices w1, w2…..wn such that (wi, wi+1) ε V for 1≤i≤N.
Page 150
EC6301 / OOPS AND DS BE (ECE) III Sem / II Year
Path length
It is the number of edges present in the path, which is equal to N-1 , where N is the
number of vertices.
1 2
3 4
2 3
Path: 1 2 3 1
Acyclic graph
A directed graph is said to be acyclic when there is no cyclic path in it. It is also called
DAG (Directed Acyclic graph).
Complete graph
A graph is said to be complete graph in which there is an edge between every pair of
vertices.
Page 151
EC6301 / OOPS AND DS BE (ECE) III Sem / II Year
B C
Strongly Connected
In a digraph, if there is a path from every vertex to every other vertex is called strongly
connected. Otherwise it is said to be weakly connected graph.
A A
B C B C
Disjoint
A graph is said to be disjoint, if it is not connected.
A D
B C E
Degree
The degree of a vertex is the number of arcs or edges incident to it.
Page 152
EC6301 / OOPS AND DS BE (ECE) III Sem / II Year
Indegree
The indegree is the numbers of arcs are entering into the vertex.
Outdegree
The outdegree of a vertex is the number of arcs exiting (or leaving) from the vertex.
A B
C D
Degree of D = 4
Indegree of D is 3
Outdegree of D is 1
Representation
Adjacency Matrix
Having mapped the vertices to integers, one simple representation for the graph uses
an adjacency matrix. Using a |V| x |V| matrix of booleans, we set aij = true if an edge
connects i and j. Edges can be undirected, in which case if aij = true, then aji = true also,
or directed, in which aij != aji, unless there are two edges, one in either direction,
between i and j. The diagonal elements, aii, may be either ignored or, in cases such as state
machines, where the presence or absence of a connection from a node to itself is relevant, set to
true or false as required.
When space is a problem, bit maps can be used for the adjacency matrix. In this case, an
ADT for the adjacency matrix improves the clarity of your code immensely by hiding the bit
twiddling that this space saving requires. In undirected graphs, only one half of the matrix needs
to be stored. If the graph is dense, i.e most of the nodes are connected by edges, then
the O(|V|2) cost of initializing an adjacency matrix is matched by the cost of inputting and
Page 153
EC6301 / OOPS AND DS BE (ECE) III Sem / II Year
setting the edges. However, if the graph is sparse, ie |E| is closer to |V|, then an adjacency list
representation may be more efficient.
Adjacency List Representation
Adjacency lists are lists of nodes that are connected to a given node. For each node, a
linked list of nodes connected to it can be set up. Adding an edge to a graph will generate two
entries in adjacency lists - one in the lists for each of its extremities. Following is an example
undirected graph with 5 vertices.
Page 154
EC6301 / OOPS AND DS BE (ECE) III Sem / II Year
Page 155
EC6301 / OOPS AND DS BE (ECE) III Sem / II Year
visited [ w ] = 1
end if
end repeat
if Queue is empty
return
end if
delete u from Queue
End while
End BFS
Page 156
EC6301 / OOPS AND DS BE (ECE) III Sem / II Year
Page 157
EC6301 / OOPS AND DS BE (ECE) III Sem / II Year
Rules
Select an unvisited node V, visit it. It‟s level is called the current level.
Find unvisited neighbors of the current node, visit it and make it the current node.
If more than one unvisited neighbors then resolve the tie by following the alphabetical
order.
If the current node has no unvisited neighbors, backtrack to its parent and make it new
current node.
Repeat from step 2 and 3 until no more nodes can be visited.
Repeat from step 1 for the remaining nodes.
Algorithm
Algorithm DFT ( G , n )
Begin
repeat for i=1 to n
visited[i] = 0
end repeat
repeat for i=1 to n
if visited[i] = 0
DFS(i)
end if
end repeat
end
Algorithm DFS ( v)
u=v
visited [ v ] = 1
repeat for each vertex w adjacent from v
if visited [w] = 0
DFS( w )
end if
End
Page 158
EC6301 / OOPS AND DS BE (ECE) III Sem / II Year
Page 159
EC6301 / OOPS AND DS BE (ECE) III Sem / II Year
Page 160
EC6301 / OOPS AND DS BE (ECE) III Sem / II Year
Page 161
EC6301 / OOPS AND DS BE (ECE) III Sem / II Year
recursive DFS for adjacent vertices of a vertex, push the vertex to stack.
2)Reverse directionsof all arcs toobtain the transpose graph.
3) One by one pop a vertex from S while S is not empty. Let the popped vertex be „v‟. Take v as
source and do DFS .The DFS starting from v prints strongly connected component of v.
Working
The above algorithm is DFS based. It does DFS two times. DFS of a graph produces a
single tree if all vertices are reachable from the DFS starting point. Otherwise DFS produces a
forest. So DFS of a graph with only one SCC always produces a tree. The important point to note
is DFS may produce a tree or a forest when there are more than one SCCs depending upon the
chosen starting point. For example, in the above diagram, if we start DFS from vertices 0 or 1 or
2, we get a tree as output. And if we start from 3 or 4, we get a forest.
To find and print all SCCs, we would want to start DFS from vertex 4 (which is a sink
vertex), then move to 3 which is sink in the remaining set (set excluding 4) and finally any of the
remaining vertices (0, 1, 2).Unfortunately, there is no direct way for getting this sequence.
However, if we do a DFS of graph and store vertices according to their finish times, we make
sure that the finish time of a vertex that connects to other SCCs (other that its own SCC), will
always be greater than finish time of vertices in the other SCC.
For example, in DFS of above example graph, finish time of 0 is always greater than 3
and 4 (irrespective of the sequence of vertices considered for DFS). And finish time of 3 is
always greater than 4. DFS doesn‟t guarantee about other vertices, for example finish times of 1
and 2 may be smaller or greater than 3 and 4 depending upon the sequence of vertices considered
for DFS. So to use this property, we do DFS traversal of complete graph and push every finished
vertex to a stack. In stack, 3 always appears after 4, and 0 appear after both 3 and 4. In the next
step, we reverse the graph. Consider the graph of SCCs. In the reversed graph, the edges that
connect two components are reversed. So the SCC {0, 1, 2} becomes sink and the SCC {4}
becomes source. In stack, we always have 0 before 3 and 4. So if we do a DFS of the reversed
graph using sequence of vertices in stack, we process vertices from sink to source. Print SCCs
one by one.
Page 162
EC6301 / OOPS AND DS BE (ECE) III Sem / II Year
UNIT V
SORTING AND SEARCHING
Syllabus: Sorting algorithms: Insertion sort - Quick sort – Merge sort – Searching: Linear
search – Binary search.
5.1 SORTING
Sorting is an operation of arranging data, in some given order such as increasing (or)
decreasing with numerical data (or) alphabetically with character data.Sorting methods can be
characterized into two categories:
Internal sorting
External sorting
Internal Sorting
Internal sorting methods are the methods that can be used when the list to be sorted is
small enough so that the entire sort can be carried out in main memory.The key principles of
internal sorting is that all the data items to be stored are retained in the main memory and random
access in the memory space can be efficiently used to sort the data items.The various internal
sorting techniques are:
Bubble sort
Selection sort
Insertion sort
Shell sort
Quick sort
External Sorting
External sorting methods are the methods to be used when the list to be sorted is large
and cannot be accommodated entirely in the main memory. In this case, some of data is present
in the main memory and some is kept in auxiliary memory such as hard disk, floppy disk, tape
etc.
The key principle of external sorting is to move data from secondary storage to main
memory in large blocks for ordering the data.The various external sorting methods are:
Page 163
EC6301 / OOPS AND DS BE (ECE) III Sem / II Year
Merge sort
Tape sort
Page 164
EC6301 / OOPS AND DS BE (ECE) III Sem / II Year
a[j]=a[j-1];
else
break;
}
a[j]=temp;
}
cout << "The Sorted List is :";
for(i=0;i<n;i++)
cout << a[i] << "\t";
getch();
}
Example
Advantages
Sorts the list faster when the list has less number of elements.
Efficient in cases where a new element has to be inserted into a sorted list.
Disadvantages
Very slow for large value of n.
Poor performance if the list is in almost reverse order.
Page 165
EC6301 / OOPS AND DS BE (ECE) III Sem / II Year
Page 166
EC6301 / OOPS AND DS BE (ECE) III Sem / II Year
getch();
}
void mergesplit(int a[],int first,int last)
{
int mid;
if(first < last)
{
mid=(first+last)/2;
mergesplit(a,first,mid);
mergesplit(a,mid+1,last);
merge(a,first,mid,mid+1,last);
}
}
void merge(int a[],int f1,int l1,int f2,int l2)
{
int i,j,k=0;
i=f1;
j=f2;
while(i <= l1 && j <= l2)
{
if(a[i] < a[j])
b[k]=a[i++];
else
b[k]=a[j++];
k++;
}
while(i <= l1)
b[k++]=a[i++];
while(j <= l2)
b[k++]=a[j++];
Page 167
EC6301 / OOPS AND DS BE (ECE) III Sem / II Year
i=f1;
j=0;
while(i <= l2 && j < k)
a[i++]=b[j++];
}
Example
Advantages
Very useful for sorting bigger lists.
Applicable for external sorting also.
Disadvantages
Needs a temporary array every time, for sorting the new list.
Page 168
EC6301 / OOPS AND DS BE (ECE) III Sem / II Year
The main idea of the quick sort is to divide the initial unsorted list into two parts, such
that the every element in the first list is less than all the elements present in the second list.The
procedure is repeated recursively for both the parts, upto relatively short sequence which can be
sorted until the sequences reduces to length one.The first step of the algorithm requires choosing
a pivot value that will be used to divide large and small numbers.
The first element of list is chosen as a pivot value.Once, the pivot value has been
selected, all the elements smaller than the pivot are placed towards the beginning of the set and
all the elements larger than the pivot are placed at the right.This process essentially sets the pivot
value in the correct place each time.Each side of the pivot is then quick sorted.
The quick sort algorithm reduces the unnecessary swaps and moves an item a great
distance in one move.The median-of-three portioning method is used to select the pivot. In this
method, three elements are randomly chosen and the median of these three values is chosen as
the pivot element.
Principle
A pivot item near the middle of the list is chosen, and the items on either side are moved
so that the data items on one side of the pivot element are smaller than the pivot element where
as those on the other side are larger.
The middle (or) the pivot element is now in its correct position. This procedure is then
applied recursively to the 2 parts of the list, on either side of the pivot element until the whole list
is sorted.
Program
#include<iostream.h>
#include<conio.h>
int i,j,n,pivot,a[20];
void quick(int a[],int left,int right);
void swap(int a[],int i,int j);
main()
{
int i,n,a[20];
cout << "Enter the limit";
Page 169
EC6301 / OOPS AND DS BE (ECE) III Sem / II Year
cin >> n;
cout << "Enter the elements";
for(i=0;i<n;i++)
cin >> a[i];
quick(a,0,n-1);
cout << "Sorted List is:";
for(i=0;i<n;i++)
cout << a[i];
getch();
}
void quick(int a[],int first,int last)
{
if(first < last)
{
pivot=a[first];
i=first;
j=last;
while(i < j)
{
while(a[i] <= pivot && i < last)
i++;
while(a[j] >= pivot && j > first)
j--;
if(i < j)
swap(a,i,j);
}
swap(a,first,j);
quick(a,first,j-1);
quick(a,j+1,last);
}
Page 170
EC6301 / OOPS AND DS BE (ECE) III Sem / II Year
}
void swap(int a[],int i,int j)
{
int t;
t=a[i];
a[i]=a[j];
a[j]=t;
}
Example
45 28 90 1 46 39 33 87
i/pivot j
Increment i till the element pointed by i is less than pivot. Decrement j till the element
pointed by j is greater than the pivot element.
45 28 90 1 46 39 33 87
pivot i j
45 28 33 1 46 39 90 87
pivot i j
Now, swap the elements pointed by i and j.
45 28 33 1 39 46 90 87
Pivot i j
45 28 33 1 39 46 90 87
Pivot j i
Page 171
EC6301 / OOPS AND DS BE (ECE) III Sem / II Year
Once, i and j crosses swap the element pointed by j and pivot and fix the position of the
pivot element.
39 28 33 1 45 46 90 87
Consider the elements left to pivot element as one sub array and the elements right to the
pivot as another sub array. Apply quick sort to the sub arrays separately.
39 28 33 1 45 46 90 87
Pivot/i j
39 28 33 1 45 46 90 87
Pivot j/i
If i and j stops at same position, swap the element pointed by j and pivot and fix the
position of the pivot element.
1 28 33 39 45 46 90 87
Apply quick sort to the list left to 39.
1 28 33 39 45 46 90 87
Pivot/i j
1 28 33 39 45 46 90 87
Pivot/j i
Once, i and j crosses swap the element pointed by j and pivot and fix the position of the
pivot element.
1 28 33 39 45 46 90 87
Page 172
EC6301 / OOPS AND DS BE (ECE) III Sem / II Year
1 28 33 39 45 46 90 87
Pivot/i
j
1 28 33 39 45 46 90 87
Pivot/j i
Once, i and j crosses swap the element pointed by j and pivot and fix the position of the
pivot element.
1 28 33 39 45 46 90 87
Pivot/i
j
1 28 33 39 45 46 90 87
Pivot
i/j
If i and j stops at same position, swap the element pointed by j and pivot and fix the
position of the pivot element.
1 28 33 39 45 46 87 90
Page 173
EC6301 / OOPS AND DS BE (ECE) III Sem / II Year
Advantages
Faster than any other commonly used sorting algorithm. It has a best average case
behavior.
Reduces complexity.
Disadvantages
As it uses recursion, stack space consumption is high.
5.5 SEARCHING
Searching is the process which is used to find the location of a target element among a
list of elements. It is used in situation where we want to find whether a particular item is present
in a list or not. For eg, in a given voter list of a colony, a person may search his name to ascertain
whether he is a valid voter or not. There are two types of searching namely,
Linear search
Binary search
5.6 SEQUENTIAL / LINEAR SEARCH
A list can be searched sequentially wherein the search for the data item starts from the
beginning and continues till the end of the list. This simple method of search is known as linear
search. It has the following characteristics:
The search is linear.
The search starts from the first element and continues in a sequential fashion from
element to element till the desired element is found.
In the worst case, a total number of N steps need to be taken for a list of size N.
Thus, the linear search is slow and to some extent inefficient.
Program
#include<iostream.h>
#include<conio.h>
void main()
{
clrscr();
Page 174
EC6301 / OOPS AND DS BE (ECE) III Sem / II Year
int a[100],i,n,item,s=0;
cout<<"\n------------ LINEAR SEARCH ------------ \n\n";
cout<<"Enter No. of Elements=";
cin>>n;
cout<<"\nEnter Elements=\n";
for(i=1;i<=n;i++)
{
cin>>a[i];
}
cout<<"\nEnter Element you want to Search=";
cin>>item;
for(i=1;i<=n;i++) //Array Elements Comparison with Item
{
if(a[i]==item)
{
cout<<"\nData is Found at Location : "<<i;
s=1;
break;
}
}
f(s==0)
{
cout<<"Data is Not Found";
}
getch();
}
Page 175
EC6301 / OOPS AND DS BE (ECE) III Sem / II Year
beg=1;
end=n;
Page 176
EC6301 / OOPS AND DS BE (ECE) III Sem / II Year
Page 177
EC6301 / OOPS AND DS BE (ECE) III Sem / II Year
Page 178