Maps and iterators

This commit is contained in:
Antti H S Laaksonen 2016-12-31 15:31:37 +02:00
parent d7ca9e76fe
commit 2f9a1d8bac
1 changed files with 116 additions and 124 deletions

View File

@ -256,83 +256,80 @@ cout << s.count(5) << "\n"; // 2
\index{map@\texttt{map}} \index{map@\texttt{map}}
\index{unordered\_map@\texttt{unordered\_map}} \index{unordered\_map@\texttt{unordered\_map}}
\key{Hakemisto} on taulukon yleistys, A \key{map} is a generalized array
joka sisältää kokoelman avain-arvo-pareja. that consists of key-value-pairs.
Siinä missä taulukon avaimet ovat aina peräkkäiset While the keys in a regular array are always
kokonaisluvut $0,1,\ldots,n-1$, the successive integers $0,1,\ldots,n-1$,
missä $n$ on taulukon koko, where $n$ is the size of the array,
hakemiston avaimet voivat the keys in a map can be of any data type and
olla mitä tahansa tyyppiä they don't have to be successive values.
eikä niiden tarvitse olla peräkkäin.
C++ sisältää kaksi toteutusta hakemistolle C++ contains two map implementations that
samaan tapaan kuin joukolle. correspond to the set implementations:
Rakenne the structure
\texttt{map} perustuu \texttt{map} is based on a balanced
tasapainoiseen binääripuuhun ja sen binary tree and accessing an element
alkioiden käsittely vie aikaa $O(\log n)$, takes $O(\log n)$ time,
kun taas rakenne while the structure
\texttt{unordered\_map} perustuu \texttt{unordered\_map} uses a hash map
hajautustauluun ja sen alkioiden and accessing an element takes $O(1)$ time on average.
käsittely vie keskimäärin aikaa $O(1)$.
Seuraava koodi toteuttaa hakemiston, The following code creates a map
jossa avaimet ovat merkkijonoja ja where the keys are strings and the values are integers:
arvot ovat kokonaislukuja:
\begin{lstlisting} \begin{lstlisting}
map<string,int> m; map<string,int> m;
m["apina"] = 4; m["monkey"] = 4;
m["banaani"] = 3; m["banana"] = 3;
m["cembalo"] = 9; m["harpsichord"] = 9;
cout << m["banaani"] << "\n"; // 3 cout << m["banana"] << "\n"; // 3
\end{lstlisting} \end{lstlisting}
Jos hakemistosta hakee avainta, If a value of a key is requested
jota ei ole siinä, but the map doesn't contain it,
avain lisätään hakemistoon the key is automatically added to the map with
automaattisesti oletusarvolla. a default value.
Esimerkiksi seuraavassa koodissa For example, in the following code,
hakemistoon ilmestyy avain ''aybabtu'', the key ''aybabtu'' with value 0
jonka arvona on 0: is added to the map.
\begin{lstlisting} \begin{lstlisting}
map<string,int> m; map<string,int> m;
cout << m["aybabtu"] << "\n"; // 0 cout << m["aybabtu"] << "\n"; // 0
\end{lstlisting} \end{lstlisting}
Funktiolla \texttt{count} voi The function \texttt{count} determines
tutkia, esiintyykö avain hakemistossa: if a key exists in the map:
\begin{lstlisting} \begin{lstlisting}
if (m.count("aybabtu")) { if (m.count("aybabtu")) {
cout << "avain on hakemistossa"; cout << "key exists in the map";
} }
\end{lstlisting} \end{lstlisting}
Seuraava koodi listaa hakemiston The following code prints all keys and values
kaikki avaimet ja arvot: in the map:
\begin{lstlisting} \begin{lstlisting}
for (auto x : m) { for (auto x : m) {
cout << x.first << " " << x.second << "\n"; cout << x.first << " " << x.second << "\n";
} }
\end{lstlisting} \end{lstlisting}
\section{Iteraattorit ja välit} \section{Iterators and ranges}
\index{iteraattori@iteraattori} \index{iterator}
Monet C++:n standardikirjaston funktiot Many functions in the C++ standard library
käsittelevät tietorakenteiden iteraattoreita are given iterators to data structures,
ja niiden määrittelemiä välejä. and iterators often correspond to ranges.
\key{Iteraattori} on muuttuja, An \key{iterator} is a variable that points
joka osoittaa tiettyyn tietorakenteen alkioon. to an element in a data structure.
Usein tarvittavat iteraattorit ovat \texttt{begin} Often used iterators are \texttt{begin}
ja \texttt{end}, jotka rajaavat välin, and \texttt{end} that define a range that contains
joka sisältää kaikki tietorakenteen alkiot. all elements in a data structure.
Iteraattori \texttt{begin} osoittaa The iterator \texttt{begin} points to
tietorakenteen ensimmäiseen alkioon, the first element in the data structure,
kun taas iteraattori \texttt{end} osoittaa and the iterator \texttt{end} points to
tietorakenteen viimeisen alkion jälkeiseen kohtaan. the position \emph{after} the last element.
Tilanne on siis tällainen: The situation looks as follows:
\begin{center} \begin{center}
\begin{tabular}{llllllllll} \begin{tabular}{llllllllll}
@ -342,23 +339,24 @@ Tilanne on siis tällainen:
\end{tabular} \end{tabular}
\end{center} \end{center}
Huomaa epäsymmetria iteraattoreissa: Note the asymmetry in the iterators:
\texttt{s.begin()} osoittaa tietorakenteen alkioon, \texttt{s.begin()} points to an element in the data structure,
kun taas \texttt{s.end()} osoittaa tietorakenteen ulkopuolelle. while \texttt{s.end()} points outside the data structure.
Iteraattoreiden rajaama joukon väli on siis \emph{puoliavoin}. Thus, the range defined by the iterators is \emph{half-open}.
\subsubsection{Välien käsittely} \subsubsection{Handling ranges}
Iteraattoreita tarvitsee Iterators are used in C++ standard library functions
C++:n standardikirjaston funktioissa, jotka käsittelevät that work with ranges of data structures.
tietorakenteen välejä. Usually, we want to process all elements in a
Yleensä halutaan käsitellä tietorakenteiden kaikkia data structure, so the iterators
alkioita, jolloin funktiolle annetaan \texttt{begin} and \texttt{end} are given for the function.
iteraattorit \texttt{begin} ja \texttt{end}.
Esimerkiksi seuraava koodi järjestää vektorin funktiolla \texttt{sort}, For example, the following code sorts a vector
kääntää sitten alkioiden järjestyksen funktiolla \texttt{reverse} using the function \texttt{sort},
ja sekoittaa lopuksi alkioiden järjestyksen funktiolla \texttt{random\_shuffle}. then reverses the order of the elements using the function
\texttt{reverse}, and finally shuffles the order of
the elements using the function \texttt{random\_shuffle}.
\index{sort@\texttt{sort}} \index{sort@\texttt{sort}}
\index{reverse@\texttt{reverse}} \index{reverse@\texttt{reverse}}
@ -370,89 +368,84 @@ reverse(v.begin(), v.end());
random_shuffle(v.begin(), v.end()); random_shuffle(v.begin(), v.end());
\end{lstlisting} \end{lstlisting}
Samoja funktioita voi myös käyttää tavallisen taulukon These functions can also be used with a regular array.
yhteydessä, jolloin iteraattorin sijasta annetaan In this case, the functions are given pointers to the array
osoitin taulukkoon: instead of iterators:
\newpage
\begin{lstlisting} \begin{lstlisting}
sort(t, t+n); sort(t, t+n);
reverse(t, t+n); reverse(t, t+n);
random_shuffle(t, t+n); random_shuffle(t, t+n);
\end{lstlisting} \end{lstlisting}
\subsubsection{Joukon iteraattorit} \subsubsection{Set iterators}
Iteraattoreita tarvitsee usein joukon Iterators are often used when accessing
alkioiden käsittelyssä. elements in a set.
Seuraava koodi määrittelee iteraattorin The following code creates an iterator
\texttt{it}, joka osoittaa joukon \texttt{s} alkuun: \texttt{it} that points to the first element in the set:
\begin{lstlisting} \begin{lstlisting}
set<int>::iterator it = s.begin(); set<int>::iterator it = s.begin();
\end{lstlisting} \end{lstlisting}
Koodin voi kirjoittaa myös lyhyemmin näin: A shorter way to write the code is as follows:
\begin{lstlisting} \begin{lstlisting}
auto it = s.begin(); auto it = s.begin();
\end{lstlisting} \end{lstlisting}
Iteraattoria vastaavaan joukon alkioon The element to which an iterator points
pääsee käsiksi \texttt{*}-merkinnällä. can be accessed through the \texttt{*} symbol.
Esimerkiksi seuraava koodi tulostaa For example, the following code prints
joukon ensimmäisen alkion: the first element in the set:
\begin{lstlisting} \begin{lstlisting}
auto it = s.begin(); auto it = s.begin();
cout << *it << "\n"; cout << *it << "\n";
\end{lstlisting} \end{lstlisting}
Iteraattoria pystyy liikuttamaan Iterators can be moved using operators
operaatioilla \texttt{++} (eteenpäin) \texttt{++} (forward) and \texttt{---} (backward),
ja \texttt{---} (taaksepäin). meaning that the iterator moves to the next
Tällöin iteraattori siirtyy seuraavaan or previous element in the set.
tai edelliseen alkioon joukossa.
Seuraava koodi tulostaa joukon kaikki alkiot:
The following code prints all elements in the set:
\begin{lstlisting} \begin{lstlisting}
for (auto it = s.begin(); it != s.end(); it++) { for (auto it = s.begin(); it != s.end(); it++) {
cout << *it << "\n"; cout << *it << "\n";
} }
\end{lstlisting} \end{lstlisting}
Seuraava koodi taas tulostaa joukon The following code prints the last element in the set:
viimeisen alkion:
\begin{lstlisting} \begin{lstlisting}
auto it = s.end(); auto it = s.end();
it--; it--;
cout << *it << "\n"; cout << *it << "\n";
\end{lstlisting} \end{lstlisting}
% Iteraattoria täytyi liikuttaa askel taaksepäin,
% koska se osoitti aluksi joukon viimeisen
% alkion jälkeiseen kohtaan.
Funktio $\texttt{find}(x)$ palauttaa iteraattorin The function $\texttt{find}(x)$ returns an iterator
joukon alkioon, jonka arvo on $x$. that points to an element whose value is $x$.
Poikkeuksena jos alkiota $x$ ei esiinny joukossa, However, if the set doesn't contain $x$,
iteraattoriksi tulee \texttt{end}. the iterator will be \texttt{end}.
\begin{lstlisting} \begin{lstlisting}
auto it = s.find(x); auto it = s.find(x);
if (it == s.end()) cout << "x puuttuu joukosta"; if (it == s.end()) cout << "x is missing";
\end{lstlisting} \end{lstlisting}
Funktio $\texttt{lower\_bound}(x)$ palauttaa The function $\texttt{lower\_bound}(x)$ returns
iteraattorin joukon pienimpään alkioon, an iterator to the smallest element in the set
joka on ainakin yhtä suuri kuin $x$. whose value is at least $x$.
Vastaavasti $\texttt{upper\_bound}(x)$ palauttaa Correspondingly,
iteraattorin pienimpään alkioon, the function $\texttt{upper\_bound}(x)$
joka on suurempi kuin $x$. returns an iterator to the smallest element
Jos tällaisia alkioita ei ole joukossa, in the set whose value is larger than $x$.
funktiot palauttavat arvon \texttt{end}. If such elements do not exist,
Näitä funktioita ei voi käyttää the return value of the functions will be \texttt{end}.
\texttt{unordered\_set}-rakenteessa, These functions are not supported by the
joka ei pidä yllä alkioiden järjestystä. \texttt{unordered\_set} structure that
doesn't maintain the order of the elements.
\begin{samepage} \begin{samepage}
Esimerkiksi seuraava koodi etsii joukosta For example, the following code finds the element
alkion, joka on lähinnä lukua $x$: nearest to $x$:
\begin{lstlisting} \begin{lstlisting}
auto a = s.lower_bound(x); auto a = s.lower_bound(x);
@ -470,20 +463,19 @@ if (a == s.begin() && a == s.end()) {
} }
\end{lstlisting} \end{lstlisting}
Koodi käy läpi mahdolliset tapaukset The code goes through all possible cases
iteraattorin \texttt{a} avulla. using the iterator \texttt{a}.
Iteraattori First, the iterator points to the smallest
osoittaa aluksi pienimpään alkioon, element whose value is at least $x$.
joka on ainakin yhtä suuri kuin $x$. If \texttt{a} is both \texttt{begin}
Jos \texttt{a} on samaan aikaan \texttt{begin} and \texttt{end} at the same time, the set is empty.
ja \texttt{end}, joukko on tyhjä. If \texttt{a} equals \texttt{begin},
Muuten jos \texttt{a} on \texttt{begin}, the corresponding element is nearest to $x$.
sen osoittama alkio on $x$:ää lähin alkio. If \texttt{a} equals \texttt{end},
Jos taas \texttt{a} on \texttt{end}, the last element in the set is nearest to $x$.
$x$:ää lähin alkio on joukon viimeinen alkio. If none of the previous cases is true,
Jos mikään edellisistä tapauksista ei päde, the element nearest to $x$ is either the
niin $x$:ää lähin alkio element that corresponds to $a$ or the previous element.
on joko $a$:n osoittama alkio tai sitä edellinen alkio.
\end{samepage} \end{samepage}
\section{Muita tietorakenteita} \section{Muita tietorakenteita}