| Topics | Assignments | Slides | Algorithms | References |
PBM763 Syllabus:
Fall 2020.
Task analysis by week: Concepts, Exercises, Coding, Mathematics.
Disclaimer: All the external links to readings and videos only point to task/topic scope; their purpose is illustrative. They should NOT be considered assignments or part of the class.
Explain the entry point of a program, how it handles input and output, some fundamental data types and their conversions. Introduce the basic steps for its compilation and linking. In the module we stick with the Visual Studio Code possibilities.
Basic examples; whey they posess the main characteristics of an algorithm and how to run them in graphical IDEs (Visual Studio Code, etc).
Describe all kinds of “built in” C++ types; their bitwise structure and how to initialize them.
How to build “derived types” from fundamental types and other derived types.
Introduce the identifiers (fully qualified with namespaces or local); understand the scope of a variable.
This module introduces longer code fragments, builds larger expressions and assignments, explains the structures of loops, branching and switching statements.
Distinguish between declarations and definitions; understand scoping and namespace rules.
Use correct syntax and best practices for conditional statements (3 kinds)
Use correct syntax and best practices for loop statements
Explain the structure of class definition, public, private members, nested classes, constructors and destructors.
Describe struct types as aggregations of (public) data members.
Explain why classes are used differently from types; what changes as we use “single concern” and “encapsulation” principles (i.e. hiding implementation details).
Understand what happens as new class members are instantiated, in which order parent/child objects are instantiated; initializer lists, etc.
Specify the function/method prototypes using public/private/protected, also “const” specifiers.
Create and build C++ sources and headers to reflect the design of your C++ classes.
Define functions with appropriate prototypes (to pass arrays and large objects). Separate concerns go into different files and mutual function calls.
Describe the typical patterns of parameter passing to C++ functions
Some flavors of recursion, their implications on memory use, time efficiency and declaration order in the source files
Here we analyze the algorithms at pseudocode level (making assumptions regarding the cost of data structure library calls). More detailed analysis that takes into account alternatives of implementing the data structures themselves is postponed to other modules.
The module explains the thinking behind keywords “public”, “private”, inheritance – and how this is typically used in writing algorithms and data-structure libraries.
This module discusses just the simplest ADTs.
The module only lists those design patterns that are typically used with data structures. One can certainly write good code without using “Gang of Four” jargon, but it can explain the thinking behind some popular APIs and data structure libraries.
The module explains general techniques to do unit testing and system testing, code inspection, printouts, logging and debugging in order to find bugs in algorithmic software.
Define list and also vector (a.k.a. arraylist) allowing random access. In this and subsequent modules we start with the ADT we want, then show some ways to implement it.
Trees in this course are always assumed to be rooted (one node is root) and ordered (we always know, which is the 1st, 2nd etc. child of the same parent). This module only deals with trees in the most general sense (to store certain hierarchies). Trees with additional structural requirements (with keys ordered for fast search and/or balanced) are called search trees; they will be discussed later.
Unlike more universal structures (binary search trees or hashtables) the data structures may only need to return (or remove) the minimal or maximal element; in this case they are called priority queues. A typical way to implement them is a tree-like structure called a heap.
Finding values by non-integer keys (typically strings) defines the difference between maps and lists. Dictionaries are a variant of maps allowing repeated keys. In this module the ADTs are defined and also their implementations
Binary Search Trees is one possible way to store maps with totally ordered keys. This is an overview chapter that shows the general principles how the search trees can be built and manipulated. Inserting nodes in certain patterns can lead to skinny and inefficient trees; so they need some balancing.
This chapter describes general-purpose sorting algorithms (sorting also appears in STL module and as an illustration to various algorithm paradigms in later modules).
This module explains ways to represent sets and also bags (allowing repetition of elements); their order relations and set-level operations. Element-level operations on sets were explained earlier – in fact, maps and dictionaries can be used for that.
The module explains the most complex data structures covered in this course (undirected and directed graphs); their ADT and some general tasks associated with graphs (such as BFS and DFS traversal). Any weighted graph issues are postponed.
Various general algorithmic ideas can be illustrated on weighted graph optimization problems. This module analyzes source-to-sink (or all-pairs) shortest paths and also the minimum spanning tree (MST) algorithms.
The last module provides a high-level overview of some large classes of algorithmic problems; what algorithms were covered in each one of them and what paradigms were used.
Introduce algorithms that split the problem into subcases and then verify subcases in some order
Algorithm can reduce a problem to a simpler one. We discuss paradigms to solve a problem by stepwise reducing it to a simpler one.
Many algorithmic problems can be solved or “conquered” by subdividing them in parts
Data structure manipulations are often a means to an end. Here we list some application areas that often lead to data structures; and this will help to introduce different algorithm creation paradigms – very general ideas that are behind the algorithm development.
Some algorithms searching for the optimal (cheapest, fastest, etc.) way to complete the task follow the following rule: At every step select the “locally best” alternative and it will eventually lead to the globally best solution. This approach is usually efficient, but for many problem classes this could give a solution that is not the best possible.