\(\newcommand{\Java}{\href{http://java.com/en/}{Java}}\)
\(\newcommand{\Python}{\href{https://www.python.org/}{Python}}\)
\(\newcommand{\CPP}{\href{http://www.cplusplus.com/}{C++}}\)
\(\newcommand{\ST}[1]{{\Blue{\textsf{#1}}}}\)
\(\newcommand{\PseudoCode}[1]{{\color{blue}\textsf{#1}}}\)
\(%\newcommand{\subheading}[1]{\textbf{\large\color{aaltodgreen}#1}}\)
\(\newcommand{\subheading}[1]{\large{\usebeamercolor[fg]{frametitle} #1}}\)
\(\newcommand{\Blue}[1]{{\color{flagblue}#1}}\)
\(\newcommand{\Red}[1]{{\color{aaltored}#1}}\)
\(\newcommand{\Emph}[1]{\emph{\color{flagblue}#1}}\)
\(\newcommand{\Engl}[1]{({\em engl.}\ #1)}\)
\(\newcommand{\Pointer}{\raisebox{-1ex}{\huge\ding{43}}\ }\)
\(\newcommand{\Set}[1]{\{#1\}}\)
\(\newcommand{\Setdef}[2]{\{{#1}\mid{#2}\}}\)
\(\newcommand{\PSet}[1]{\mathcal{P}(#1)}\)
\(\newcommand{\Card}[1]{{\vert{#1}\vert}}\)
\(\newcommand{\Tuple}[1]{(#1)}\)
\(\newcommand{\Implies}{\Rightarrow}\)
\(\newcommand{\Reals}{\mathbb{R}}\)
\(\newcommand{\Seq}[1]{(#1)}\)
\(\newcommand{\Arr}[1]{[#1]}\)
\(\newcommand{\Floor}[1]{{\lfloor{#1}\rfloor}}\)
\(\newcommand{\Ceil}[1]{{\lceil{#1}\rceil}}\)
\(\newcommand{\Path}[1]{(#1)}\)
\(%\newcommand{\Lg}{\lg}\)
\(\newcommand{\Lg}{\log_2}\)
\(\newcommand{\BigOh}{O}\)
\(\newcommand{\Oh}[1]{\BigOh(#1)}\)
\(\newcommand{\todo}[1]{\Red{\textbf{TO DO: #1}}}\)
\(\newcommand{\NULL}{\textsf{null}}\)
\(\newcommand{\Insert}{\ensuremath{\textsc{insert}}}\)
\(\newcommand{\Search}{\ensuremath{\textsc{search}}}\)
\(\newcommand{\Delete}{\ensuremath{\textsc{delete}}}\)
\(\newcommand{\Remove}{\ensuremath{\textsc{remove}}}\)
\(\newcommand{\Parent}[1]{\mathop{parent}(#1)}\)
\(\newcommand{\ALengthOf}[1]{{#1}.\textit{length}}\)
\(\newcommand{\TRootOf}[1]{{#1}.\textit{root}}\)
\(\newcommand{\TLChildOf}[1]{{#1}.\textit{leftChild}}\)
\(\newcommand{\TRChildOf}[1]{{#1}.\textit{rightChild}}\)
\(\newcommand{\TNode}{x}\)
\(\newcommand{\TNodeI}{y}\)
\(\newcommand{\TKeyOf}[1]{{#1}.\textit{key}}\)
\(\newcommand{\PEnqueue}[2]{{#1}.\textsf{enqueue}(#2)}\)
\(\newcommand{\PDequeue}[1]{{#1}.\textsf{dequeue}()}\)
\(\newcommand{\Def}{\mathrel{:=}}\)
\(\newcommand{\Eq}{\mathrel{=}}\)
\(\newcommand{\Asgn}{\mathrel{\leftarrow}}\)
\(%\newcommand{\Asgn}{\mathrel{:=}}\)
\(%\)
\(% Heaps\)
\(%\)
\(\newcommand{\Downheap}{\textsc{downheap}}\)
\(\newcommand{\Upheap}{\textsc{upheap}}\)
\(\newcommand{\Makeheap}{\textsc{makeheap}}\)
\(%\)
\(% Dynamic sets\)
\(%\)
\(\newcommand{\SInsert}[1]{\textsc{insert}(#1)}\)
\(\newcommand{\SSearch}[1]{\textsc{search}(#1)}\)
\(\newcommand{\SDelete}[1]{\textsc{delete}(#1)}\)
\(\newcommand{\SMin}{\textsc{min}()}\)
\(\newcommand{\SMax}{\textsc{max}()}\)
\(\newcommand{\SPredecessor}[1]{\textsc{predecessor}(#1)}\)
\(\newcommand{\SSuccessor}[1]{\textsc{successor}(#1)}\)
\(%\)
\(% Union-find\)
\(%\)
\(\newcommand{\UFMS}[1]{\textsc{make-set}(#1)}\)
\(\newcommand{\UFFS}[1]{\textsc{find-set}(#1)}\)
\(\newcommand{\UFCompress}[1]{\textsc{find-and-compress}(#1)}\)
\(\newcommand{\UFUnion}[2]{\textsc{union}(#1,#2)}\)
\(%\)
\(% Graphs\)
\(%\)
\(\newcommand{\Verts}{V}\)
\(\newcommand{\Vtx}{v}\)
\(\newcommand{\VtxA}{v_1}\)
\(\newcommand{\VtxB}{v_2}\)
\(\newcommand{\VertsA}{V_\textup{A}}\)
\(\newcommand{\VertsB}{V_\textup{B}}\)
\(\newcommand{\Edges}{E}\)
\(\newcommand{\Edge}{e}\)
\(\newcommand{\NofV}{\Card{V}}\)
\(\newcommand{\NofE}{\Card{E}}\)
\(\newcommand{\Graph}{G}\)
\(\newcommand{\SCC}{C}\)
\(\newcommand{\GraphSCC}{G^\text{SCC}}\)
\(\newcommand{\VertsSCC}{V^\text{SCC}}\)
\(\newcommand{\EdgesSCC}{E^\text{SCC}}\)
\(\newcommand{\GraphT}{G^\text{T}}\)
\(%\newcommand{\VertsT}{V^\textup{T}}\)
\(\newcommand{\EdgesT}{E^\text{T}}\)
\(%\)
\(% NP-completeness etc\)
\(%\)
\(\newcommand{\Poly}{\textbf{P}}\)
\(\newcommand{\NP}{\textbf{NP}}\)
\(\newcommand{\PSPACE}{\textbf{PSPACE}}\)
\(\newcommand{\EXPTIME}{\textbf{EXPTIME}}\)
\(\newcommand{\Lo}{\mathit{lo}}\)
\(\newcommand{\Hi}{\mathit{hi}}\)
\(\newcommand{\Mid}{\mathit{mid}}\)
Describing algorithms
In an abstract view,
an algorithm can be seen as a method that transforms some input to output.
For instance, a sorting algorithm transforms an array of elements
into another array that contains the same elements but in a sorted order.
In order to communicate algorithms to other people,
we have to describe them in some way.
Of course, one could describe the algorithm
by giving its implementation in some concrete programming language.
However, in many cases,
it can be easier and beneficial to describe an algorithm
As an example, recall the binary search algorithm discussed in the CS-A1120 Programming 2 course.
In the input/output-level abstraction,
the algorithm fulfills the following specification:
Input: a sorted array \(A\) of elements and an element \(e\).
Output: “true” if \(e\) appears in \(A\), “false” otherwise.
In a natural language (English in this case),
we may describe the binary search algorithm
in the following structured way:
Initially, consider the whole array.
If the considered array is empty, return “false”
If the middle element of the array is \(e\), return “true”.
Otherwise, if the middle element is greater than \(e\),
go to step 2 but only consider the subarray from the beginning to (but not including) the middle element.
Otherwise, the middle element is less than \(e\) and we
go to step 2 but consider the subarray from (but not including) the middle element to the end of the array.
In pseudocode, we may describe the binary search algorithm as follows.
The actual search is performed in the recursive helper function search
,
and the currently considered sub-array of \(A\) is indicated
by its start and end indices lo
and hi
.
// Search for the element \(e\) in the sorted array \(A\)
binary-search(\(A\), \(e\)):
return search(\(A\), \(e\), \(1\), \(\ALengthOf{A}\))
// A recursive helper function doing the actual search
search(\(A\), \(e\), \(\Lo\), \(\Hi\)):
if \(\Lo \le \Hi\): // sub-array of size 1 or more?
\(\Mid \Asgn \Lo + \Floor{(\Hi - \Lo) / 2}\)
if \(A[\Mid] \Eq e\): return true
else if \(e < A[\Mid]\): return search(\(A\), \(e\), \(\Lo\), \(\Mid-1\))
else: return search(\(A\), \(e\), \(\Mid+1\), \(\Hi\))
else:
return false
The pseudocode presentation only expresses the essential operations
needed to communicate the algorithm idea —
many details, such as type information, are simply omitted.
Some notes:
As in many programming languages (but not in Scala),
array indexing is denoted with the square brackets.
In many cases, array indexing starts
(i) from \(1\) in pseudocode and in mathematics, but
(ii) from \(0\) in real programming languages.
Take this into account when implementing algorithms from books, wikipedia, scientific articles and so on
to avoid off-by-one errors.
Of course, we may also describe an algorithm by giving
an implementation in some programming language.
For instance,
below is an implementation of the binary search algorithm in Scala.
def binarySearch[T](arr: Array[T], e: T)(using ord: Ordering[T]) =
def inner(lo: Int, hi: Int): Boolean =
if lo <= hi then
val mid = lo + ((hi - lo) / 2)
val cmp = ord.compare(e, arr(mid))
if cmp == 0 then true // e == arr(mid)
else if cmp < 0 then inner(lo, mid-1) // e < arr(mid)
else inner(mid+1, hi) // e > arr(mid)
else
false
inner(0, arr.length-1)
Similarly, the same implementation but in C++11:
#include <functional>
#include <vector>
template<typename T>
bool binarySearch(std::vector<T>& arr, T& e) {
std::function<int(int,int)> inner = [&](int lo, int hi) -> int {
if(lo <= hi) {
const int mid = lo + ((hi - lo) / 2);
if(e == arr[mid])
return true;
else if(e < arr[mid])
return inner(lo, mid-1);
else // e > arr[mid]
return inner(mid+1, hi);
} else
return false;
};
return inner(0, arr.size()-1);
}
These descriptions have the drawback
that a reader who is unfamiliar with the applied programming language
may get lost in language specific details when trying to understand
the core idea of the algorithm.
For instance, in the above Scala code,
is using ord: Ordering[T]
relevant for the algorithm itself?
Similarly,
a reader who is not familiar with C++ may feel lost
when encountering the line
std::function<int(int,int)> inner = [&](int low, int hi) -> int {
.