Data Structures: and Algorithms
Data Structures: and Algorithms
DATA STRUCTURES
AND ALGORITHMS
Objectives
Looking ahead in this lecture, well
consider:
Abstract Data Types
Encapsulation
Inheritance
Pointers
Polymorphism
Aspects of Object-Oriented
Solution
Principles of object-oriented programming
Encapsulation: Objects combine data and
operations.
Inheritance: Classes inherit properties
from other classes.
Polymorphism: Objects determine
appropriate operations at execution time.
Encapsulation
Fundamental to object-oriented
programming (OOP) is the notion of an
object
An object is a data structure, combined
with the operations pertinent to that
structure
Most object-oriented languages (OOLs)
define objects through the use of a class
A class is a template which implements
the ADT defining the objects the class
creates
Encapsulation (continued)
The combination of data members and methods in a class is
referred to as data encapsulation
An object, then, can also be defined as the instantiation of a
class, creating an entity that can be used in a program
This concept is a very powerful and useful tool in modern
programming
In non-OOLs, the program code itself is responsible for
determining the associations between data and functions
In contrast, data encapsulation binds the data structure and
its operations together in the class
The program can then focus on the manipulation of these
objects through their associated methods
Encapsulation (continued)
This approach has several advantages:
The strong link between data and operations
better mimics real-world behavior, on which
program models are based
Errors in implementation are confined to the
methods of a particular class in which they
occur, making them easier to detect and
correct
Details of the implementation of the object can
be hidden from other objects to prevent side
effects from occurring
This last point illustrates the principle of
information-hiding
Encapsulation (continued)
These user-accessible components
comprise an objects public interface; the
remaining methods and data are private
Encapsulation (continued)
Information-hiding also means that every
object we use is independent of all other
objects, unless we define methods for
communicating between objects
Even then, the degree to which the objects
interact is precisely defined by the
communication methods, known as
message passing
This is analogous to function calls in
classical programming
An object responds to a message by
Encapsulation (continued)
The class as a creator of objects allows great
freedom to define objects of the same class with
different properties
Default parameters in constructors, combined
with well-crafted methods, allow objects to exhibit
considerable flexibility
Generic classes offer further flexibility by allowing
type parameters to generalize data members and
methods
This allows objects to be modified or replaced by
other objects that are more efficient or better
suited to particular circumstances while the user
interface and message passing remains the same
Inheritance
Inheritance is a technique of reusing existing class
definitions to derive new classes
These new classes (called derived classes or
subclasses or child classes) can inherit the attributes
and behavior of the pre-existing classes (called base
classes or superclasses or parent classes)
This relationship of classes through inheritance forms a
hierarchy, which can be diagrammed
Information hiding can be extended through this
hierarchy by the access the base class allows the
derived class(es)
Derived classes can then add, delete, & modify methods
and data members in their own definitions (known as
overriding)
Inheritance (continued)
The amount of access, and level of
modifications, are controlled by specifying
public, protected, or private in the
derived class header
A derived class with public inheritance
preserves the access classes of the base class
A derived class with protected inheritance
treats public and protected members of the
base class as protected; private members
remain private
Finally, derived classes with private inheritance
treat all members of the base class as private
Inheritance (continued)
Derived classes are also not limited to a single
base class for their inherited attributes
Multiple inheritance is the capability provided
in some OOLs (like C++) that allows a derived
class to inherit from more than one base class
This can create problems if the base classes have
a common ancestor in the inheritance hierarchy
In this situation, the derived class could inherit
multiple copies of the same member, causing
possible errors
This is referred to as the diamond problem, due
to the way the inheritance diagram is formed
Inheritance (continued)
Inheritance (continued)
In this figure the two classes B and C inherit from
A, and D inherits from B and C
The problem occurs if D uses a method defined in
A (and doesnt override it)
If B and C both override it, D could potentially
have two copies with different behaviors, leading
to a compiler error
To avoid this, classes B and C inherit class A as
virtual
This treats A as a direct base class of D, so only
one copy of A is available to inherit, eliminating
the ambiguity
Polymorphism
Polymorphism is the ability, in many OOLs, to
create objects of different types that respond to
method calls having the same name
They differ in that they respond according to
type-specific behavior
Which method is called depends on the time at
which the decision is made about the call
This decision is referred to as binding, and can
occur in different ways
Static binding determines the function call at
compile time
Dynamic binding delays the decision until
run time
Polymorphism (continued)
In C++, dynamic binding can be
implemented by declaring the method
virtual
This allows the method to be selected
based on the value the pointer has instead
of its type
With static binding, a method is chosen
based on the pointers type
This mechanism gives us a very powerful
OOP tool
We can send messages to different objects
Object-Oriented Concepts
Object-oriented analysis and design
(OOAD)
Process for solving problems
Solution
Computer program consisting of system of
interacting classes of objects
Object
Has set of characteristics, behaviors related to
solution
Object-oriented design
Describe solution to problem
Express solution in terms of software objects
Create one or more models of solution
Aspects of Object-Oriented
Solution
Principles of object-oriented programming
Encapsulation: Objects combine data and
operations.
Inheritance: Classes inherit properties
from other classes.
Polymorphism: Objects determine
appropriate operations at execution time.
Cohesion
Each module should perform one welldefined task
Benefits
Coupling
Measure of dependence among modules
Dependence
Sharing data structures or calling each others
methods
Coupling
Benefits of loose coupling in a system
Specifications
Operation Contracts
Documents
How method can be used
What limitations it has
Specify
Purpose of modules
Data flow among modules
Pre-, post-condition, input, output of each
module
Unusual Conditions
Ways to address invalid conditions:
Assume they will not happen
Ignore such situations
Guess at clients intentions
Return value that signals problem
Throw an exception
Abstraction
Separate purpose of a module from its
implementation
Specifications do not indicate how to
implement
Able to use without knowing implementation
Information Hiding
Abstraction helps identify details that
should be hidden from public view
Ensured no other module can tamper with
these hidden details.
Information Hiding
Information Hiding
Designing an ADT
Evolves naturally during the problemsolving process
What data does a problem require?
What operations does a problem require?
Identifying Behaviors
Elements of C++
Introduction
Computer program
Sequence of statements whose objective is to
accomplish a task
Programming
Process of planning and creating a program
Comments
Comments are for the reader, not the
compiler
Two types:
Single line: begin with //
// This is a C++ program.
// Welcome to C++ Programming.
Multiple line: enclosed between /* and */
/*
You can include comments that can
occupy several lines.
*/
Special Symbols
Token: the smallest individual unit of a
program written in any language
C++ tokens include special symbols, word
symbols, and identifiers
Special symbols in C++ include:
Reserved Words
(Keywords)
Reserved word symbols (or keywords):
Cannot be redefined within program
Cannot be used for anything other than their
intended use
Examples:
int
float
double
char
const
void
return
Identifiers
Identifier: the name of something that
appears in a program
Consists of letters, digits, and the underscore
character (_)
Must begin with a letter or underscore
Identifiers (contd.)
Legal identifiers in C++:
first
conversion
payRate
Whitespaces
Every C++ program contains whitespaces
Include blanks, tabs, and newline characters
Data Types
Data type: set of values together with a
set of operations
C++ data types fall into three categories:
Simple data type
Structured data type
Pointers
Arithmetic Operators,
Operator
Precedence, and
Expressions
C++ arithmetic operators:
+ addition
- subtraction
* multiplication
/ division
% modulus (or remainder) operator
Arithmetic Operators,
Operator Precedence, and
Expressions (contd.)
Order of Precedence
All operations inside of () are evaluated
first
*, /, and % are at the same level of
precedence and are evaluated next
+ and have the same level of
precedence and are evaluated last
When operators are on the same level
Performed from left to right (associativity)
3 * 7 - 6 + 2 * 5 / 4 + 6 means
(((3 * 7) 6) + ((2 * 5) / 4 )) + 6
Expressions
Integral expression: all operands are
integers
Yields an integral result
Example: 2 + 3 * 5
Mixed Expressions
Mixed expression:
Has operands of different data types
Contains integers and floating-point
string Type
Programmer-defined type supplied in
ANSI/ISO Standard C++ library
Sequence of zero or more characters
enclosed in double quotation marks
Null (or empty): a string with no characters
Each character has a relative position in
the string
Position of first character is 0
Variables, Assignment
Statements, and Input
Statements
Assignment Statement
The assignment statement takes the form:
Expression is evaluated and its value is
assigned to the variable on the left side
A variable is said to be initialized the first
time a value is placed into it
In C++, = is called the assignment
operator
Assignment Statement
(contd.)
Pre-decrement: --variable
Post-decrement: variable
x = difference
5;
x between
= 5;
What is the
y = ++x;
y = x++;
following?
the
Output
The syntax of cout and << is:
Called an output statement
Output (contd.)
A manipulator is used to format the output
Example: endl causes insertion point to move
to beginning of next line
Output (contd.)
The new line character is '\n'
May appear anywhere in the string
cout << "Hello there.";
cout << "My name is James.";
Output:
Hello there.My name is James.
cout << "Hello there.\n";
cout << "My name is James.";
Output :
Hello there.
My name is James.
Output (contd.)
Preprocessor Directives
C++ has a small number of operations
Many functions and symbols needed to run
a C++ program are provided as collection
of libraries
Every library has a name and is referred to
by a header file
Preprocessor directives are commands
supplied to the preprocessor program
All preprocessor commands begin with #
No semicolon at the end of these
commands
Preprocessor Directives
(contd.)
Syntax to include a header file:
For example:
#include <iostream>
Causes the preprocessor to include the header
file iostream in the program
Use of Blanks
In C++, you use one or more blanks to
separate numbers when data is input
Blanks are also used to separate reserved
words and identifiers from each other and
from other symbols
Blanks must never appear within a
reserved word or identifier
Use of Semicolons,
Brackets, and Commas
All C++ statements end with a semicolon
Also called a statement terminator
Semantics
Semantics: set of rules that gives meaning
to a language
Possible to remove all syntax errors in a
program and still not have it run
Even if it runs, it may still not do what you
meant it to do
Ex: 2 + 3 * 5 and (2 + 3) * 5
are both syntactically correct expressions,
but have different meanings
Naming Identifiers
Identifiers can be self-documenting:
CENTIMETERS_PER_INCH
Prompt Lines
Prompt lines: executable statements that
inform the user what to do
cout << "Please enter a number between 1 and 10 and "
<< "press the return key" << endl;
cin >> num;
Documentation
A well-documented program is easier to
understand and modify
You use comments to document programs
Comments should appear in a program to:
Explain the purpose of the program
Identify who wrote it
Explain the purpose of particular statements
More on Assignment
Statements
Two forms of assignment
Simple and compound
Compound operators provide more concise
notation
Compound assignment
x *= y;
Pointers
A variable defined in a program has two
important attributes
Its content or value (what it stores)
Its location or address (where it is)
Pointers (continued)
Pointers are defined much the same as other variables
They have a type; in this case the type of variable they point
to
They have a user-defined name
The name is preceded by an asterisk (*) to indicate the
variable is a pointer
Pointers (continued)
Fig. 1-1 Changes of values after assignments are made using pointer variables; note that (b) and (c)
show the same situation, and so do (d) and (e), (g) and (h), (i) and (j), (k) and (l), and (m) and (n)
Pointers (continued)
To assign a variables address to a pointer, the
address-of operator (&) is placed before the variable
For pointer p to point to variable i, we write
p = &i;
This pointer is then said to point to that variable
This is shown in figure 1-1(b); a common way to draw
this relationship is shown in figure 1-1(c)
To access the value a pointer points to, we have to
dereference the pointer, using the dereference
operator, an asterisk (*)
So *p refers to the location stored in p, the address of i
Pointers (continued)
This is shown in figure 1.1(d); figures (e) to
(n) show other examples
Pointers (continued)
In addition to variables, pointers can be used to
access dynamically created locations
These are created during runtime using the memory
manager
Two functions are used to handle dynamic memory
To allocate memory, new is used; it returns the address of
the allocated memory, which can be assigned to a pointer
p = new int;
To release the memory pointed at, delete is used
delete p;
Pointers (continued)
One problem can arise when an object is deleted
without modifying the value of the pointer
The pointer still points to the memory location of
the deallocated memory
This creates the dangling reference problem
Attempting to dereference the pointer will cause
an error
To avoid this, after deleting the object, the pointer
should be set to a known address or NULL, which
is equivalent to 0
p = NULL; or p = 0;
Pointers (continued)
The second type of problem that can occur with dynamic
memory usage is the memory leak
This occurs when the same pointer is used in consecutive
allocations, such as:
p = new int;
p = new int;
Since the second allocation occurs without deleting the
first, the memory from the first allocation becomes
inaccessible
Depending on code structure, this leak can accumulate
until no memory is available for further allocation
To avoid this, memory needs to be deallocated when no
longer in use
Pointers (continued)
Pointers and Arrays
Pointers ability to access memory locations
through their addresses provides us with
numerous processing advantages
Typically, arrays in C++ are declared before
they can be used, known as static
declaration
This means the size of the array must be
determined before it is used
This is wasteful if the array is too large, or a
limitation if the array is too small
However, the name of an array is nothing more
than a label for the beginning of the array in
Pointers (continued)
Pointers and Arrays (continued)
For example, an array declared:
int temp[7];
would appear in memory as:
Pointers (continued)
Pointers and Arrays (continued)
In pointer arithmetic, we can add an offset to the base address
of the array: temp + 1, temp + 2, etc. and dereference the
result
So *(temp + 1) is the same as temp[1], *(temp + 2) is
equivalent to temp[2], etc.
And as long as we dont try to change the value of temp, we
can use this alternate approach to access the arrays elements
Now remember that a pointer can be used in the allocation of
memory without a name, through the use of new
This means that we can also declare an array dynamically,
via
int *p; p = new int[n];
As long as the value of n is known when the declaration is
executed, the array can be of arbitrary size
Pointers (continued)
Pointers and Arrays (continued)
Now, a reference to an element of the array is
constructed by adding the elements location to p
and dereferencing, as before
And we can assign other pointers to the array by
simply declaring them and copying the value of p
into the new pointer, if needed
This also allows us to conveniently dispose of an
array when we no longer need it, using:
delete[] p;
The brackets indicate that an array is to be deleted;
p is the pointer to that array
Pointers (continued)
Pointers and Copy Constructors
A potential problem can arise when copying
data from one object to another if one of the
data members is a pointer
The default behavior is to copy the items
member by member
Because the value of a pointer is an address,
this address is copied to the new object
Consequently the new objects pointer points
to the same data as the old objects pointer,
instead of being distinct
To correct this, the user must create a copy
constructor which will copy not only the
Pointers (continued)
Pointers and Copy Constructors (continued)
Fig. 1-2 Illustrating the necessity of using a copy constructor for objects with pointer members
Pointers (continued)
Pointers and Destructors
When a local object goes out of scope, the
memory associated with it is released
Unfortunately, if one of the object members is
a pointer, the pointers memory is released,
leaving the object pointed at inaccessible
To avoid this memory leak, objects that contain
pointers need to have destructors written for
them
A destructor is a code construct that is
automatically called when its associated object
is deleted
It can specify special processing to occur, such
Pointers (continued)
Pointers and Reference Variables
There is a close correspondence between pointers
and reference variables
This is because reference variables are implemented
as constant pointers
Given the declarations:
int n = 5,*p = &n,&r = n;
a change to the value of n via any of the three will be
reflected in the other two
Thus n = 7 or *p = 7, or r = 7 accomplishes the
same result; the value of n is now 7
So we can dereference a pointer, or use a reference
directly to access the original objects value
Pointers (continued)
Pointers and Reference Variables (continued)
We do have to exercise care in declaring pointers, though,
because
int *const
declares a constant pointer to an integer, while
const int *
declares a pointer to a constant integer
The latter can cause errors if we attempt to assign a value
through a dereferenced pointer
Reference variables are valuable in working with functions, as
they allow us to modify the values of arguments
They can also be returned from a function
While pointers can be used instead, they have to be
dereferenced
Pointers (continued)
Pointers and Reference Variables
(continued)
We do have to be careful when we use
references in classes
It is possible to compromise information hiding
if a public method returns a reference to a
private data member
This reference, as an address, allows bypassing
of the protection mechanisms provided in the
class definition
Data corruption can result
Pointers (continued)
Pointers and Functions
The same characteristics of variables value
(or contents) and location (or address) can
also be applied to functions
A functions value is the result it returns, and
its address is the memory location of the
functions body
So we can use a pointer to a function to access
it
Given a function temp, its name, temp, is a
pointer to the function and *temp is the
function itself
Following the dereferenced pointer with an
Input/Output
peek function
Returns next character from the input stream
Does not remove the character from that
stream
In the statement
cin.get(ch);
Input Failure
Things can go wrong during execution
If input data does not match
corresponding variables, program may run
into problems
Trying to read a letter into an int or
double variable will result in an input
failure
If an error occurs when reading data
Input stream enters the fail state
setprecision Manipulator
Syntax:
Outputs decimal numbers with up to n
decimal places
Must include the header file iomanip:
#include <iomanip>
fixed Manipulator
fixed outputs floating-point numbers in a
fixed decimal format
Example: cout << fixed;
Disable by using the stream member function
unsetf
Example: cout.unsetf(ios::fixed);
showpoint Manipulator
showpoint forces output to show the
decimal point and trailing zeros
Examples:
cout << showpoint;
cout << fixed << showpoint;
setw
Outputs the value of an expression in a
specified number of columns
cout << setw(5) << x << endl;
Additional Output
Formatting Tools
Additional formatting tools that give you
more control over your output:
setfill manipulator
left and right manipulators
unsetf manipulator
setfill Manipulator
Output stream variables can use setfill
to fill unused columns with a character
Example:
cout << setfill('#');
Types of Manipulators
Two types of manipulators:
With parameters
Without parameters
Debugging: Understanding
Logic Errors and Debugging
with cout statements
Syntax errors
Reported by the compiler
Logic errors
File Input/Output
File: area in secondary storage to hold info
File I/O is a five-step process
1. Include fstream header
2. Declare file stream variables
3. Associate the file stream variables with the
input/output sources
4. Use the file stream variables with >>, <<, or
other input/output functions
5. Close the files
Control Structures I
(Selection)
Control Structures
A computer can proceed:
In sequence
Selectively (branch): making a choice
Repetitively (iteratively): looping
By calling a function
Relational Operators
(contd.)
Comparing Characters
Expression of char values with relational
operators
Result depends on machines collating
sequence
ASCII character set
One-Way Selection
One-way selection syntax:
Two-Way Selection
Two-way selection syntax:
Order of Precedence
Relational and logical operators are
evaluated from left to right
The associativity is left to right
Order of Precedence
(contd.)
Order of Precedence
(contd.)
Order of Precedence
(contd.)
Order of Precedence
(contd.)
str1
str2
str3
str4
str4
=
=
=
=
=
"Hello";
"Hi";
"Air";
"Bill";
"Big";
18)
"Eligible to vote." << endl;
"No longer a minor." << endl;
Comparing ifelse
Statements with a Series of
if Statements
Comparing ifelse
Statements with if
Statements (contd.)
Short-Circuit Evaluation
Short-circuit evaluation: evaluation of a
logical expression stops as soon as the
value of the expression is known
Example:
(age >= 21) || ( x == 5) //Line 1
(grade == 'A') && (x >= 7) //Line 2
Comparing Floating-Point
Numbers for Equality: A
Precaution
Associativity of Relational
Operators: A Precaution
Associativity of Relational
Operators: A Precaution
(contd.)
num = 5
num = 20
Using Pseudocode to
Develop, Test, and Debug a
Program
Pseudocode, or just pseudo
switch Structures
switch structure: alternate
to if-else
switch (integral) expression
is evaluated first
Value of the expression determines
which corresponding action is taken
Expression is sometimes
called the selector
switch Structures
(contd.)