CSS 343: Notes from Lecture 14 (DRAFT)
Guest Lecture
Graph problems:
-
Euler circuit: start at some vertex, visit every
edge
once (possibly passing through vertices multiple times)
-
every vertex must have even degree
-
O(|E|) algorithm
-
Hamiltonian circuit: visit every vertex
-
best-known algorithm requires exponential time
P, NP, and NP-completeness:
-
P is the class of problems that have polynomial-time solutions
-
NP is the a class of problems that have polynomial-time
solutions on a nondeterministic machine (NP = "Nondeterministic
Polynomial time")
-
non-deterministic machines are theoretical models of
computation
-
a non-deterministic machine may be simulated
deterministically using backtracking
-
deterministic simulation requires exponential time
-
typically, these problems involve some exponential number of
possibilities, each of which could be checked in polynomial
time
-
exponential time algorithms are considered
intractable
-
NP-complete problems: all problems in NP can be reduced (via
polynomial-time reduction) to an NP-complete problem
-
proving the first NP-complete problems was a breakthrough
-
to prove that some problem Q is NP-complete, show that
it is in NP and show that some NP-complete problem can
be reduced to problem Q
-
this is similar to how we proved that the Priority queue
is O(log N) because a better solution would imply a
better-than O(N log N) solution to sorting (which is
proven to be O(N log N))
-
it is unknown (an open question) whether there exist
polynomial-time solutions for NP-complete problems (if so,
P=NP, otherwise P!=NP)
-
if a problem is shown to be NP-complete, we look for
heuristic or approximate solutions that give good-enough
results for some applications
-
there are many problems known to be NP-complete
-
finding a Hamiltonian circuit is NP-complete
Administrivia
-
Textbooks are in stock (own these books!):
-
The Mythical Man Month, Fred Brooks
-
The C++ Standard Library: A Tutorial and Reference (2nd
Edition), Nicolai M. Josuttis
Assignment 2 has been marked.
-
results were disappointing
-
Tuesday evening after class, let's do a hackathon: code 2-3 tree
insert from scratch (for no extra credit)—for as long as
it takes
-
final exam will have at least two whiteboard-style
implementation questions
-
Code, Code, Code!
More on C++ (cont.)
Our Story So Far...
-
C++ is a multi-paradigm language
-
designed to support large-scale systms development
-
references act like Java-style objects
-
can't assign them (can modify fields)
-
can't be NULL
-
otherwise, references are just syntactic sugar over pointers
-
references were introduced to C++ to allow for operator
overloading with LVALUES, e.g.
operator=
,
and for call-by-reference semantics in function calls
-
do not return a reference (or pointer) to a function-local
object because the object disappears out from under you
as soon as the function returns
-
a large part of programing is resource management (memory, open
files, etc.)
-
Java uses garbage collection
-
Python uses reference counting
-
C++ can implement reference counting, e.g.
std::shared_ptr
-
garbage collection cannot be implemented in C++ without
breaking low-level code
-
manual control over resource management has advantages and
disadvantages
-
one advantage is that it allows performance
optimizations for special cases
-
static vs. nonstatic members: for non-virtual functions the
difference is syntactic sugar:
class SomeClass {
public:
static void static_func(SomeClass& something, SomeType args);
void nonstatic_func(SomeType args);
};
SomeClass thing;
thing.nonstatic_func(arg);
SomeClass::static_func(thing, arg);
-
it is generally bad form to privide public data members because
it makes the program less flexible
-
e.g. suppose you have the following
class Inflexible {
public:
//...
string color;
};
Class Flexible {
public:
//...
string& color() {return color_;}
private:
string color_;
};
and you decide to change the way you want to represent
colors in your program:
Class Flexible {
public:
//...
string& color() {return color_map[color_];}
private:
enum Colors;
static map<Colors, string> color_map;
Colors color_;
};
None of your client code would have to be modified!
Abstract Data Types vs. Concrete Data Types
An ADT is all about the interface; a concrete type is all about
the implementation.
C++ has the equivalent of Java-style interfaces in the form of
abstract base classes.
Core OO Principles
While object orientation has many associations, the three core
concepts are:
-
encapsulation
-
inheritance
-
polymorphism
Encapsulation
Namespaces provide another form of encapsulation.
using namespace std
: bad practice?
-
defeats the purpose of having a separate namespace
-
on the other hand, putting
std::
everywhere clutters the code
Conclusion: Your Mileage May Vary
Never put
using namespace std;
into a header file. This could introduce a
surprising
state change into your client's code.
The basic encapsulation is, of course the
class
.
public
and
private
provide a mechanism for separating interface and implementation.
Nonstatic members have an implicit parameter, a pointer to the
object which is accessed via
this
.
Direct access to a data member
foo_
is identical to access via the pointer,
this->foo_
.
Inheritance and Polymorphism