Sets as bits

This commit is contained in:
Antti H S Laaksonen 2017-01-07 13:51:53 +02:00
parent e65fe7c8c7
commit 0899147194
1 changed files with 54 additions and 57 deletions

View File

@ -266,119 +266,116 @@ but there are also \texttt{long long} versions
of the functions of the functions
available with the prefix \texttt{ll}. available with the prefix \texttt{ll}.
\section{Bit representation of sets}
\section{Joukon bittiesitys} Each subset of a set $\{0,1,2,\ldots,n-1\}$
corresponds to a $n$ bit number
where the one bits indicate which elements
are included in the subset.
For example, the bit representation for $\{1,3,4,8\}$
is 100011010 that equals $2^8+2^4+2^3+2^1=282$.
Joukon $\{0,1,2,\ldots,n-1\}$ The bit representation of a set uses little memory
jokaista osajoukkoa because only one bit is needed for the information
vastaa $n$-bittinen luku, whether an element belongs to the set.
jossa ykkösbitit ilmaisevat, In addition, we can efficiently manipulate sets
mitkä alkiot ovat mukana osajoukossa. that are stored as bits.
Esimerkiksi joukkoa $\{1,3,4,8\}$
vastaa bittiesitys 100011010 eli luku
$2^8+2^4+2^3+2^1=282$.
Joukon bittiesitys vie vähän muistia, \subsubsection{Set operations}
koska tieto kunkin alkion kuulumisesta
osajoukkoon vie vain yhden bitin tilaa.
Lisäksi bittimuodossa tallennettua joukkoa
on tehokasta käsitellä bittioperaatioilla.
\subsubsection{Joukon käsittely} In the following code, the variable $x$
contains a subset of $\{0,1,2,\ldots,31\}$.
Seuraavan koodin muuttuja $x$ The code adds elements 1, 3, 4 and 8
sisältää joukon $\{0,1,2,\ldots,31\}$ to the set and then prints the elements in the set.
osajoukon.
Koodi lisää luvut 1, 3, 4 ja 8
joukkoon ja tulostaa
joukon sisällön.
\begin{lstlisting} \begin{lstlisting}
// x on tyhjä joukko // x is an empty set
int x = 0; int x = 0;
// lisätään luvut 1, 3, 4 ja 8 joukkoon // add numbers 1, 3, 4 and 8 to the set
x |= (1<<1); x |= (1<<1);
x |= (1<<3); x |= (1<<3);
x |= (1<<4); x |= (1<<4);
x |= (1<<8); x |= (1<<8);
// tulostetaan joukon sisältö // print the elements in the set
for (int i = 0; i < 32; i++) { for (int i = 0; i < 32; i++) {
if (x&(1<<i)) cout << i << " "; if (x&(1<<i)) cout << i << " ";
} }
cout << "\n"; cout << "\n";
\end{lstlisting} \end{lstlisting}
Koodin tulostus on seuraava: The output of the code is as follows:
\begin{lstlisting} \begin{lstlisting}
1 3 4 8 1 3 4 8
\end{lstlisting} \end{lstlisting}
Kun joukko on tallennettu bittiesityksenä, Using the bit representation of a set,
niin joukko-operaatiot voi toteuttaa we can efficiently implement set operations
tehokkaasti bittioperaatioiden avulla: using bit operations:
\begin{itemize} \begin{itemize}
\item $a$ \& $b$ on joukkojen $a$ ja $b$ leikkaus $a \cap b$ \item $a$ \& $b$ is the intersection $a \cap b$ of $a$ and $b$
(tämä sisältää alkiot, (this contains the elements that are in both the sets)
jotka ovat kummassakin joukossa) \item $a$ | $b$ is the union $a \cup b$ of $a$ and $b$
\item $a$ | $b$ on joukkojen $a$ ja $b$ yhdiste $a \cup b$ (this contains the elements that are at least
(tämä sisältää alkiot, in one of the sets)
jotka ovat ainakin toisessa joukossa) \item $a$ \& (\textasciitilde$b$) is the difference
\item $a$ \& (\textasciitilde$b$) on joukkojen $a$ ja $b$ erotus $a \setminus b$ of $a$ and $b$
$a \setminus b$ (tämä sisältää alkiot, (this contains the elements that are in $a$
jotka ovat joukossa $a$ mutta eivät joukossa $b$) but not in $b$)
\end{itemize} \end{itemize}
Seuraava koodi muodostaa The following code constructs the union
joukkojen $\{1,3,4,8\}$ ja $\{3,6,8,9\}$ yhdisteen: of $\{1,3,4,8\}$ and $\{3,6,8,9\}$:
\begin{lstlisting} \begin{lstlisting}
// joukko {1,3,4,8} // set {1,3,4,8}
int x = (1<<1)+(1<<3)+(1<<4)+(1<<8); int x = (1<<1)+(1<<3)+(1<<4)+(1<<8);
// joukko {3,6,8,9} // set {3,6,8,9}
int y = (1<<3)+(1<<6)+(1<<8)+(1<<9); int y = (1<<3)+(1<<6)+(1<<8)+(1<<9);
// joukkojen yhdiste // union of the sets
int z = x|y; int z = x|y;
// tulostetaan yhdisteen sisältö // print the elements in the union
for (int i = 0; i < 32; i++) { for (int i = 0; i < 32; i++) {
if (z&(1<<i)) cout << i << " "; if (z&(1<<i)) cout << i << " ";
} }
cout << "\n"; cout << "\n";
\end{lstlisting} \end{lstlisting}
Koodin tulostus on seuraava: The output of the code is as follows:
\begin{lstlisting} \begin{lstlisting}
1 3 4 6 8 9 1 3 4 6 8 9
\end{lstlisting} \end{lstlisting}
\subsubsection{Osajoukkojen läpikäynti} \subsubsection{Iterating through subsets}
Seuraava koodi käy läpi joukon $\{0,1,\ldots,n-1\}$ osajoukot: The following code iterates through
the subsets of $\{0,1,\ldots,n-1\}$:
\begin{lstlisting} \begin{lstlisting}
for (int b = 0; b < (1<<n); b++) { for (int b = 0; b < (1<<n); b++) {
// osajoukon b käsittely // process subset b
} }
\end{lstlisting} \end{lstlisting}
Seuraava koodi käy läpi The following code goes through
osajoukot, joissa on $k$ alkiota: subsets with exactly $k$ elements:
\begin{lstlisting} \begin{lstlisting}
for (int b = 0; b < (1<<n); b++) { for (int b = 0; b < (1<<n); b++) {
if (__builtin_popcount(b) == k) { if (__builtin_popcount(b) == k) {
// osajoukon b käsittely // process subset b
} }
} }
\end{lstlisting} \end{lstlisting}
Seuraava koodi käy läpi joukon $x$ osajoukot: The following code goes through the subsets
of a set $x$:
\begin{lstlisting} \begin{lstlisting}
int b = 0; int b = 0;
do { do {
// osajoukon b käsittely // process subset b
} while (b=(b-x)&x); } while (b=(b-x)&x);
\end{lstlisting} \end{lstlisting}
Esimerkiksi jos $x$ esittää joukkoa $\{2,5,7\}$, % Esimerkiksi jos $x$ esittää joukkoa $\{2,5,7\}$,
niin koodi käy läpi osajoukot % niin koodi käy läpi osajoukot
$\emptyset$, $\{2\}$, $\{5\}$, $\{7\}$, % $\emptyset$, $\{2\}$, $\{5\}$, $\{7\}$,
$\{2,5\}$, $\{2,7\}$, $\{5,7\}$ ja $\{2,5,7\}$. % $\{2,5\}$, $\{2,7\}$, $\{5,7\}$ ja $\{2,5,7\}$.
\section{Dynaaminen ohjelmointi} \section{Dynaaminen ohjelmointi}