1
0

Verslag verbeterd.

This commit is contained in:
Ruben Van Laer
2019-08-15 20:01:24 +02:00
committed by GitHub
parent 69e87562a5
commit 9b1001e7c1

View File

@@ -10,9 +10,9 @@
\usepackage{graphicx}
\graphicspath{ {./} }
\title{Project: Snijdende cirkels}
\title{Project TMI: Snijdende cirkels}
\author{Arthur Bols \& Ruben Van Laer}
\date{Mei 2019}
\date{Herziening Augustus 2019}
\newcommand{\CS}{C\nolinebreak\hspace{-.05em}\raisebox{.4ex}{\tiny\bf +}\nolinebreak\hspace{-.10em}\raisebox{.4ex}{\bf +}}
\def\CS{{C\nolinebreak[4]\hspace{-.05em}\raisebox{.4ex}{\bf \#}}}
@@ -35,24 +35,24 @@
\{$cirkels$: lijst van cirkels met een middelpunt en een straal\}\\
$S \gets \emptyset$ \{$S$: lijst met alle snijpunten\}\\
\For{iedere $c_1$ in $cirkels$}{
Verwijder($cirkels$, $c_1$)\\
\For{iedere $c_2$ in ($cirkels$)}{
\For{iedere $c_2$ in $cirkels$}{
$snpt \gets$ Snijpunten($c_1$,$c_2$)\\
\If{$snpt \neq \emptyset$}{
Voegtoe($S$,$snpt$)
}
}
Verwijder($cirkels$, $c_1$)\\
}
\caption{Simpel Algoritme}
\label{algo1}
\end{algorithm}
\subsection{Doorlooplijnalgoritme $O(N^2)$}
Het tweede algoritme dat we beschouwen, is een algoritme gebaseerd op het concept van een verticale doorlooplijn. We slaan het begin- en eindpunt van elke cirkel op en sorteren deze punten op basis van de x-coördinaat. Hierna gaan we van klein naar groot door al deze punten en markeren we cirkels bij het startpunt als actief. Bij het eindpunt worden ze weer inactief. Elke keer we een startpunt tegenkomen, bepalen we alle snijpunten van deze nieuwe cirkel met alle andere actieve cirkels. De complexiteit in het slechtste geval, zijnde wanneer alle cirkels tegelijkertijd actief zijn, zorgt voor het zoeken van snijpunten met alle andere cirkels zoals in algoritme \ref{algo1}, wat via dezelfde redenering een rekencomplexiteit van de grootte-orde $N^2$ oplevert.\\
Het tweede algoritme dat we beschouwen, is een algoritme gebaseerd op het concept van een verticale doorlooplijn. We slaan het begin- en eindpunt van elke cirkel op en sorteren deze punten op basis van de x-coördinaat. Hierna gaan we van klein naar groot door al deze punten en markeren we cirkels bij het startpunt als actief. Bij het eindpunt worden ze weer inactief. Elke keer we een startpunt tegenkomen, bepalen we alle snijpunten van deze nieuwe cirkel met alle andere actieve cirkels. De complexiteit in het slechtste geval, zijnde wanneer alle cirkels tegelijkertijd actief zijn, zorgt voor het zoeken van snijpunten met alle andere cirkels zoals in algoritme \ref{algo1}. Dit levert via eenzelfde redenering een rekencomplexiteit van $O(N^2)$ op.\\
\begin{algorithm}[H]
\{$cirkels$: lijst van cirkels met een middelpunt en een straal\}\\
$E \gets \emptyset$ \{$E$: gesorteerde rij met de horizontale begin- en eindpunten van elke cirkel (ook wel de 'Events' van de doorlooplijn)\}\\
$E \gets \emptyset$ \{$E$: oplopend gesorteerde lijst met de horizontale begin- en eindpunten van elke cirkel (ook wel de 'Events' van de doorlooplijn)\}\\
\For{iedere $c$ in $cirkels$}{
$p_1 \gets$ Beginpunt($c$)\\
$p_2 \gets$ Eindpunt($c$)\\
@@ -60,12 +60,12 @@
Voegtoe($E$, $p_2$)
}
$S \gets \emptyset$ \{$S$: lijst met alle snijpunten\}\\
$A \gets \emptyset$ \{$A$: lijst met cirkels die snijden met de doorlooplijn\}\\
$A \gets \emptyset$ \{$A$: lijst met cirkels die snijden met de doorlooplijn (ook wel de 'Actieve' lijst)\}\\
Verwijder($E$, $e$)\\
\While{$E \neq \emptyset$}{
$e \gets$ Kleinste($E$)\\
Verwijder($E$, $e$)\\
\If{$e$ is een beginpunt}{
$c \gets$ Cirkel($e$)\\
$e \gets$ Kleinste($E$) \{Geeft het event met de kleinste x-waarde terug\}\\
$c \gets$ Cirkel($e$) \{Geeft de cirkel behorende bij het event $e$ terug\}\\
\If{Beginpunt($e$)}{
\For{iedere $c_i$ in $A$}{
$snpt \gets$ Snijpunten($c$,$c_i$)\\
\If{$snpt \neq \emptyset$}{
@@ -74,8 +74,7 @@
}
Voegtoe($A$, $c$)\\
}
\If{$e$ is een eindpunt}{
$c \gets$ Cirkel($e$)\\
\If{Eindpunt($e$)}{
Verwijder($A$, $c$)
}
}
@@ -85,7 +84,11 @@
\subsection{Doorlooplijnalgoritme $O((N+S)log_2(N))$}
Het derde en laatst beschouwde algoritme is een variant op algoritme \ref{algo2}, maar dan met efficiëntere gegevensstructuren. Het concept hierbij is hetzelfde, maar in plaats van het nagaan van de snijpunten met alle andere actieve cirkels, worden de actieve cirkels gesorteerd in een binaire boom-structuur op basis van de volgorde waarin ze de doorlooplijn snijden. Dit werkt omdat vlak voor de snijding van twee cirkels, deze opeenvolgende cirkels zijn. De binaire boom-structuur garandeert een complexiteit van $log_2(N)$ voor het zoeken in de boom. Aangezien er $N$ cirkels zijn en er voor deze $N$ telkens de voorganger en opvolger gezocht dient te worden, waarna we de snijpunten ook toevoegen en de buren ervan zoeken, vinden we een complexiteit van ongeveer $(2N + 2S)log_2(N)$. Dit is $O((N + S)log_2(N))$.
Het derde en laatst beschouwde algoritme is een variant op algoritme \ref{algo2} met efficiëntere gegevensstructuren. Het concept hierbij is hetzelfde, maar in plaats van het nagaan van de snijpunten met alle andere actieve cirkels, worden de actieve cirkels gesorteerd in een binaire boom-structuur op basis van de volgorde waarin ze de doorlooplijn snijden. Dit werkt omdat vlak voor de snijding van twee cirkels, deze opeenvolgende cirkels zijn. De binaire boom-structuur garandeert een complexiteit van $log_2(N)$ voor het zoeken in de boom. Aangezien er $N$ cirkels zijn en er voor deze $N$ telkens de voorganger en opvolger gezocht dient te worden, waarna we de snijpunten ook toevoegen en de buren ervan zoeken, vinden we een complexiteit van ongeveer $(2N + 2S)log_2(N)$. Dit is $O((N + S)log_2(N))$. Algoritme \ref{algo3} toont het de verschillende stappen die hiervoor nodig zijn.
\section{Beschrijving experimenten}\label{exp}
Om de complexiteit van de algoritmen na te gaan, voeren we experimenten op een toenemend aantal cirkels uit. We proberen het aantal snijpunten constant te houden door de straal te nemen als $1/N$. We starten met $2$ cirkels en verdubbelen steeds het aantal. Bij elk aantal voeren we voor elk algoritme $100$ testen uit, meten de tijd die het algoritme erover doet en nemen het gemiddelde.
\begin{algorithm}[H]
\{$cirkels$: lijst van cirkels met een middelpunt en een straal\}\\
@@ -97,44 +100,49 @@
Voegtoe($E$, $p_2$)
}
$S \gets \emptyset$ \{$S$: lijst met alle snijpunten\}\\
$A \gets \emptyset$ \{$A$: (gesorteerde) binaire boom met cirkels die snijden met de doorlooplijn\}\\
$A \gets \emptyset$ \{$A$: binaire boom met tupels (cirkelsegment, cirkel), waarbij het cirkelsegment de bovenste of onderste helft van de cirkel aanduidt, overeenkomend met de cirkels die snijden met de doorlooplijn (ook wel de 'Actieve' boom)\}\\
\While{$E \neq \emptyset$}{
$e \gets$ Kleinste($E$)\\
$c \gets$ Cirkel($e$)\\
Verwijder($E$, $e$)\\
\If{$e$ is een beginpunt}{
Voegtoe($A$, $c$)\\
$c_v \gets$ Voorganger($c$)\\
$c_o \gets$ Opvolger($c$)\\
$snpt \gets$ Snijpunten($c$,$c_v$)\\
\If{$snpt \neq \emptyset$}{
Voegtoe($S$,$snpt$)
}
$snpt \gets$ Snijpunten($c$,$c_o$)\\
\If{$snpt \neq \emptyset$}{
Voegtoe($S$,$snpt$)
}
$c_1 \gets$ BovensteSegment($c$)\\
$c_2 \gets$ OndersteSegment($c$)\\
$c_v \gets$ Voorganger($c_2$)\\
$c_o \gets$ Opvolger($c_1$)\\
\If{Beginpunt($e$)}{
Voegtoe($A$, $c_1$)\\
Voegtoe($A$, $c_2$)\\
$snpt_v \gets$ Snijpunten($c_2$,$c_v$)\\
$snpt_o \gets$ Snijpunten($c_1$,$c_o$)\\
}
\If{$e$ is een eindpunt}{
Verwijder($A$, $c$)
\If{Eindpunt($e$)}{
$snpt_v \gets$ Snijpunten($c_2$,$c_v$)\\
$snpt_o \gets$ Snijpunten($c_1$,$c_o$)\\
Verwijder($A$, $c_1$)\\
Verwijder($A$, $c_2$)
}
\If{$snpt_v \neq \emptyset$}{
Voegtoe($S$,$snpt_v$)
}
\If{$snpt_o \neq \emptyset$}{
Voegtoe($S$,$snpt_o$)
}
}
\caption{Doorlooplijnalgoritme $O((N+S)log_2(N))$}
\label{algo3}
\end{algorithm}
\vspace{1cm}
\section{Beschrijving experimenten}\label{exp}
Om de complexiteit van de algoritmen na te gaan, voeren we experimenten op een toenemend aantal cirkels uit. We proberen het aantal snijpunten constant te houden door de straal te nemen als $1/N$. We starten met $2$ cirkels en verdubbelen steeds het aantal. Bij elk aantal voeren we voor elk algoritme $100$ testen uit, meten de tijd die het algoritme erover doet en nemen het gemiddelde. Dit herhalen we tot $32.768$ cirkels voor het simpele algoritme en tot $262.144$ cirkels voor de andere algoritmes, aangezien we dan voldoende informatie hebben om de complexiteit aan te tonen, zonder onnodig langdurige experimenten uit te moeten voeren. Deze gemiddelde tijd kunnen we dan plotten in functie van het aantal cirkels en deze vergelijken met de grafiek van de complexiteit die we verwachten.
Dit herhalen we tot $32.768$ cirkels voor het simpele algoritme en tot $262.144$ cirkels voor de andere algoritmes, aangezien we dan voldoende informatie hebben om de complexiteit aan te tonen, zonder onnodig langdurige experimenten uit te moeten voeren. Deze gemiddelde tijd kunnen we dan plotten in functie van het aantal cirkels en deze vergelijken met de grafiek van de complexiteit die we verwachten.
\subsection{Alternatieve benadering}
Het enige probleem met het vergelijken van de voorgenoemde plots is dat we ze moeilijk op eenzelfde grafiek kunnen plaatsen omdat de grootte-orde van tijden ten opzichte van aantallen sterk verschillen. Om geen schaalfactor in te moeten voeren, kiezen we daarom voor een andere manier om het verloop van de tijd te bepalen, namelijk het doubling ratio experiment. Hierbij verdubbelen we steeds de invoerwaarde - in dit geval het aantal cirkels - en berekenen de verhouding waarmee de gemeten tijd elke keer toeneemt. Deze verhouding is de doubling ratio. We doen daarna hetzelfde voor de functie die de tijdscomplexiteit voorstelt, bijvoorbeeld $Nlog_2(N)$. Wanneer we van al deze verhoudingen het gemiddelde nemen, hebben we dan twee getallen om met elkaar te vergelijken, in plaats van grafieken.\\
Wanneer een getal kleiner is, duidt dit op een kleinere stijging bij een verdubbeling van de grootte van de invoer en dus ook een kleinere stijging van de grafiek ten opzichte van de grafiek met het grotere getal. Wanneer we dus een gelijkaardige waarde uitkomen voor de testwaarden en de complexiteitsfunctie, kunnen we besluiten dat de complexiteitsfunctie de complexiteit van de testwaarden voldoende benaderd. De concrete resultaten van onze experimenten zijn te vinden in Sectie \ref{comp}.
Wanneer bij een doubling ratio experiment een getal kleiner is, duidt dit op een kleinere stijging bij een verdubbeling van de grootte van de invoer en dus ook een kleinere stijging van de grafiek ten opzichte van de grafiek met het grotere getal. Wanneer we dus een gelijkaardige waarde uitkomen voor de testwaarden en de complexiteitsfunctie, kunnen we besluiten dat de complexiteitsfunctie de complexiteit van de testwaarden voldoende benaderd. De concrete resultaten van onze experimenten zijn te vinden in Sectie \ref{comp}.
\section{Correctheid van het algoritme}\label{cor}
Om de correctheid van de drie algoritmes na te gaan, bewijzen we eerst de correctheid van het simpele algoritme. Hierna voeren we een groot aantal testen uit waarbij zowel het simpele algoritme als een van de andere algoritmes uitgevoerd worden. Na het uitvoeren vergelijken we de uitvoer met elkaar, waarin we nagaan of de resultaten op kleine afrondingsfouten na, hetzelfde zijn. Indien dit zo is voor het grote aantal testen, gaan we ervan uit dat het andere algoritme correct is.
Om de correctheid van de drie algoritmes na te gaan, bewijzen we eerst de correctheid van het simpele algoritme. Hierna voeren we een groot aantal testen uit waarbij zowel het simpele algoritme als een van de andere algoritmes uitgevoerd worden. Na het uitvoeren vergelijken we de uitvoer met elkaar, waarin we nagaan of de resultaten op kleine afrondingsfouten na, hetzelfde zijn. Indien dit zo is voor het grote aantal testen, gaan we ervan uit dat het andere algoritme een correcte uitvoer geeft en dus ook correct is.
\subsection{Correctheid simpel algoritme}
@@ -146,43 +154,117 @@
\item Deze redenering kan doorgetrokken worden voor $N$ cirkels, waarna de correcte snijpunten bekomen worden.
\end{itemize}
\textbf{Bemerking:} Een laatste bemerking die wel nog gemaakt moet worden is dat wanneer drie cirkels in eenzelfde punt snijden, dit punt meermaals aan $S$ toegevoegd zal worden. Dit kan opgelost worden door van $S$ een set te maken (die geen dubbele waarden bijhoudt), of extra te controleren of een waarde zich al in $S$ bevindt.\\
Indien dit zo geïmplementeerd wordt, is de uitvoer van het simpele algoritme correct.
\textbf{Bemerking:} Een laatste bemerking die wel nog gemaakt moet worden is dat wanneer drie cirkels in eenzelfde punt snijden, dit punt meermaals aan $S$ toegevoegd zal worden. Dit kan opgelost worden door van $S$ een set te maken (die geen dubbele waarden bijhoudt), of extra te controleren of een waarde zich al in $S$ bevindt. Indien dit zo geïmplementeerd wordt, is de uitvoer van het simpele algoritme correct.
\section{Bespreking resultaten en rekentijden}\label{comp}
\subsection{Simpel algoritme}
Theoretisch zagen we dat het simpele algoritme een complexiteit $O(N^2)$ heeft. Dit wordt ook bevestigd door het doubling ratio experiment in tabel \ref{tab1}. In kolom 3 zien we dat de doubling ratio rond $4$ fluctueert en als gemiddelde $5$ heeft, terwijl de doubling ratio van een kwadratisch verband exact $4$ is. De waarden voor de testen met 256 en 512 cirkels halen het gemiddelde wel sterk naar boven. Het verschil zou kunnen komen door minder goede nauwkeurigheid en hogere waarden bij de experimenten met relatief minder cirkels. De complexiteit is dan ook gebaseerd op het gedrag op lange termijn van een functie. We kunnen dus ook door de testresultaten zien dat het simpele algoritme een complexiteit van $O(N^2)$ heeft aan de hand van de zes laatste rijen.
Theoretisch zagen we dat het simpele algoritme een complexiteit $O(N^2)$ heeft. Dit wordt ook bevestigd door het doubling ratio experiment in tabel \ref{tab1}. In kolom 3 zien we dat de doubling ratio rond $4$ fluctueert en als gemiddelde $5$ heeft, terwijl de doubling ratio van een kwadratisch verband exact $4$ is. De waarden voor de testen met 256 en 512 cirkels halen het gemiddelde wel sterk naar boven. Het verschil zou kunnen komen door minder goede nauwkeurigheid en hogere waarden bij de experimenten met relatief minder cirkels. De complexiteit is dan ook gebaseerd op het gedrag op lange termijn van een functie. We kunnen dus ook door de testresultaten zien dat het simpele algoritme een complexiteit van $O(N^2)$ heeft aan de hand van de zes laatste rijen, die allen zeer dicht bij de verwachte waarde 4 liggen.
\begin{figure}[H]
\centering
\includegraphics[scale=.7]{simpel_doubling.png}
\caption{Tabel met de doubling ratio van het simpele algoritme.}
\label{tab1}
\end{figure}
\begin{table}[H]
\centering
\begin{tabular}{lllll}
\hline
\textbf{Aantal Cirkels} & \textbf{Simpel} & \textbf{doubling ratio} & $\mathbf{N^2}$ & \textbf{doubling ratio}\\
\hline
2&0&/&4&/\\
4&0&/&16&4\\
8&0&/&64&4\\
16&0&/&256&4\\
32&0&/&1024&4\\
64&0&/&4096&4\\
128&1&/&16384&4\\
256&6.01&6.01&65536&4\\
512&27.02&4.4958&262144&4\\
1024&110.13&4.0758&1048576&4\\
2048&441.8&4.0116&4194304&4\\
4096&1769.7&4.0056&16777216&4\\
8192&7077.57&3.9993&671088664&4\\
16384&28382.29&4.0101&268435456&4\\
32768&113319.69&3.9926&1073741824&4\\
\hline
\textbf{GEM.}&&\textbf{5.0013}&&\textbf{4}\\
\hline
\end{tabular}
\caption{Tabel met de doubling ratio van het simpele algoritme.}
\label{tab1}
\end{table}
\subsection{Doorlooplijnalgoritme $O(N^2)$}
Theoretisch zagen we dat bij het gewone doorlooplijnalgoritme de worst-case tijdscomplexiteit kwadratisch was. De gemiddelde tijdscomplexiteit is echter veel beter dan dat, wat tabel \ref{tab2} dan ook bevestigd. De gemiddelde ratio van onze testwaarden is $1.64$ en die van $Nlog_2(N)$ is $2.4$. De gemiddelde doubling ratio van $N^2$ is dan weer $4$. De ratio is zelfs lager dan een $Nlog_2(N)$-functie. Hieruit kunnen we besluiten dat de doubling ratio van de testwaarden veel meer aansluit bij die van $Nlog_2(N)$ dan bij een kwadratisch verband.
\begin{figure}[H]
\centering
\includegraphics[width=.6\textwidth]{doorloop_doubling.png}
\caption{Tabel met de doubling ratio van het gewone doorlooplijnalgoritme.}
\label{tab2}
\end{figure}
\begin{table}[H]
\centering
\begin{tabular}{lllll}
\hline
\textbf{Aantal cirkels} & \textbf{Doorlooplijn} & \textbf{doubling ratio} & $\mathbf{Nlog_2(N)}$ & \textbf{doubling ratio}\\
\hline
2&0&/&2&/\\
4&0&/&8&4\\
8&0&/&24&3\\
16&0&/&64&2.67\\
32&0&/&160&2.5\\
64&0&/&384&2.4\\
128&0.01&/&896&2.33\\
256&0.01&1&2048&2.29\\
512&1.01&101&4608&2.25\\
1024&2.04&2.0198&10240&2.22\\
2048&5.07&2.485&22528&2.2\\
4096&10.06&1.9842&49152&2.18\\
8192&22.78&2.2644&106496&2.17\\
16384&48.76&2.1404&229376&2.15\\
32768&104.28&2.1386&491520&2.14\\
65536&224.24&2.1503&1048576&2.13\\
131072&493.96&2.2028&2228224&2.13\\
262144&1124.17&2.2758&4718592&2.12\\
\hline
\textbf{GEM.} && \textbf{1.638} && \textbf{2.405}\\
\hline
\end{tabular}
\caption{Tabel met de doubling ratio van het gewone doorlooplijnalgoritme.}
\label{tab2}
\end{table}
\vspace{1cm}
\begin{table}[H]
\centering
\begin{tabular}{lllll}
\hline
\textbf{Aantal cirkels} & \textbf{Doorlooplijn\_eff} & \textbf{doubling ratio} & $\mathbf{Nlog_2(N)}$ & \textbf{doubling ratio} \\
\hline
2&0&/&2&/\\
4&0&/&8&4\\
8&0&/&24&3\\
16&0&/&64&2.67\\
32&0&/&160&2.5\\
64&0&/&384&2.4\\
128&0.83&/&896&2.33\\
256&2.01&2.4217&2048&2.29\\
512&4.23&2.1045&4608&2.25\\
1024&9.76&2.3073&10240&2.22\\
2048&21.02&2.1537&22528&2.2\\
4096&44.34&2.1094&49152&2.18\\
8192&93.51&2.1089&106496&2.17\\
16384&198.24&2.1199&229376&2.15\\
32768&418.44&2.1108&491520&2.14\\
65536&910.87&2.1768&1048576&2.13\\
131072&1990.7&2.1855&2228224&2.13\\
262144&4439.56&2.2302&4718591&2.12\\
\hline
\textbf{GEM.} && \textbf{2.326} && \textbf{2.405}\\
\hline
\end{tabular}
\caption{Tabel met de doubling ratio van het efficiëntere doorlooplijnalgoritme.}
\label{tab3}
\end{table}
\newpage
\subsection{Doorlooplijnalgoritme $O((N+S)log_2(N))$}
Om de rekentijd van het derde algoritme na te gaan, maken we opnieuw gebruik van een doubling ratio experiment. We gaan na wat de doubling ratio van de verwachte complexiteit is en wat de doubling ratio van de testwaarden is. In dit geval zien we in de derde kolom van tabel \ref{tab3} de doubling ratio van onze testwaarden en in de vijde kolom de doubling ratio van $Nlog_2(N)$. Het gemiddelde van de ratio's van onze testwaarden is $2.33$ en dat van $Nlog_2(N)$ is $3.06$, wat op een tragere stijging van onze testwaarden dan de $Nlog_2(N)$-functie wijst. Dit kunnen we verklaren doordat het aantal snijpunten constant wordt gehouden.
\begin{figure}[H]
\centering
\includegraphics[scale=.6]{doorloopeff_doubling.png}
\caption{Tabel met de doubling ratio van het efficiëntere doorlooplijnalgoritme.}
\label{tab3}
\end{figure}
Om de rekencomplexiteit van het derde algoritme na te gaan, maken we opnieuw gebruik van een doubling ratio experiment. We gaan na wat de doubling ratio van de verwachte complexiteit is en wat de doubling ratio van de testwaarden is. In dit geval zien we in de derde kolom van tabel \ref{tab3} de doubling ratio van onze testwaarden en in de vijde kolom de doubling ratio van $Nlog_2(N)$. Het gemiddelde van de ratio's van onze testwaarden is $2.33$ en dat van $Nlog_2(N)$ is $2.41$, wat op een gelijkaardige stijging van onze testwaarden in vergelijking met de $Nlog_2(N)$-functie wijst. Dit kunnen we verklaren doordat het aantal snijpunten nagenoeg constant wordt gehouden.\\
Bij het vergelijken van de tijden met het tweede algoritme wordt duidelijk dat dit algoritme bij onze invoergroottes steeds trager blijft. Dit kunnen we verklaren aan de hand van de complexiteit van de implementatie van het algoritme. Het tweede algoritme heeft een redelijk eenvoudige implementatie. Omdat er bij het derde algoritme met halve cirkels gewerkt moet worden en het ingewikkeld is om deze correct te sorteren in de binaire boom, doordat er veel gelijke y-waarden zijn, moeten er bij elke iteratie veel meer operaties uitgevoerd worden. In het slechtste geval van het tweede algoritme, zal dit algoritme voor bepaalde invoergroottes wel sneller zijn.