„Sentinel (Programmierung)“ – Versionsunterschied
[gesichtete Version] | [gesichtete Version] |
Ich habe das Wort "dort" gelöscht. Es war stilistisch unschön. |
K →Beispiel: Zeilennummern line mit highlight |
||
Zeile 7: | Zeile 7: | ||
== Beispiel == |
== Beispiel == |
||
In den beiden folgenden [[C (Programmiersprache)|C]]-Funktionen <code>Search</code> und <code>SearchWithSentinel</code> soll in einer [[Verkettete Liste|verketteten Liste]] vom Typ |
In den beiden folgenden [[C (Programmiersprache)|C]]-Funktionen <code>Search</code> und <code>SearchWithSentinel</code> soll in einer [[Verkettete Liste|verketteten Liste]] vom Typ |
||
<syntaxhighlight lang="c"> |
<syntaxhighlight lang="c" line> |
||
⚫ | |||
⚫ | |||
{ |
|||
⚫ | |||
int key; |
int key; |
||
struct sll_node *next; |
struct sll_node *next; // end-of-list-Indikator oder -> nächster Knoten |
||
} sll, |
} sll, |
||
⚫ | |||
</syntaxhighlight> |
</syntaxhighlight> |
||
nach einem Schlüsselwert <code>search_key</code> gesucht werden – bei gleichem Suchergebnis. |
nach einem Schlüsselwert <code>search_key</code> gesucht werden – bei gleichem Suchergebnis. |
||
Zeile 18: | Zeile 19: | ||
=== Version mit NULL === |
=== Version mit NULL === |
||
Die Liste <code>sll</code> wird [[Liste (Datenstruktur)#Einfach verkettete Liste|terminiert]] durch den [[Nullwert]] <code>NULL</code>. |
Die Liste <code>sll</code> wird [[Liste (Datenstruktur)#Einfach verkettete Liste|terminiert]] durch den [[Nullwert]] <code>NULL</code>. |
||
<syntaxhighlight lang="c"> |
<syntaxhighlight lang="c" line highlight="10,13"> |
||
// Global: |
// Global: |
||
first = NULL; |
first = NULL; // Terminierung vor der ersten Einfügung |
||
// NB: Einfügung nicht gebracht. |
// NB: Einfügung nicht gebracht. Sie hat aber |
||
// |
// für den immer gleichen Terminator (hier: Nullzeiger) zu sorgen. |
||
struct sll_node *Search(int search_key) |
struct sll_node *Search(int search_key) |
||
{ |
|||
struct sll_node *node; |
struct sll_node *node; |
||
for (node = first; node != NULL; node = node->next) |
for (node = first; |
||
node != NULL; |
|||
node = node->next) |
|||
⚫ | |||
if (node->key == search_key) |
if (node->key == search_key) |
||
return node; |
return node; // gefunden |
||
} |
} |
||
// nicht gefunden: |
// nicht gefunden: |
||
Zeile 36: | Zeile 41: | ||
Die <code>for</code>-Schleife enthält pro Schleifenschritt die zwei Abfragen |
Die <code>for</code>-Schleife enthält pro Schleifenschritt die zwei Abfragen |
||
# <code>if (node != NULL)</code> und |
# <code>if (node != NULL)</code> und |
||
# <code>if (node->key == search_key)</code>. |
# <code>if (node->key == search_key)</code> (beide gelb hinterlegt). |
||
=== Version mit Sentinel === |
=== Version mit Sentinel === |
||
Der global zugreifbare [[Zeiger (Informatik)|Zeiger]] <code>sentinel</code> zum für die Schleife gezielt zu präparierenden Objekt <code>Sentinel</code> dient als Terminator der Liste <code>sll</code>. |
Der global zugreifbare [[Zeiger (Informatik)|Zeiger]] <code>sentinel</code> zum für die Schleife gezielt zu präparierenden Objekt <code>Sentinel</code> dient als Terminator der Liste <code>sll</code>. |
||
<syntaxhighlight lang="c"> |
<syntaxhighlight lang="c" line highlight="16"> |
||
// Globale Variable: |
// Globale Variable: |
||
struct sll_node Sentinel, *sentinel = &Sentinel; |
struct sll_node Sentinel, *sentinel = &Sentinel; |
||
// Global: |
// Global: |
||
sentinel->next = sentinel; |
sentinel->next = sentinel; |
||
first = sentinel; |
first = sentinel; // Terminierung vor der ersten Einfügung |
||
// NB: Einfügung nicht gebracht. |
// NB: Einfügung nicht gebracht. Sie hat aber |
||
// |
// für den immer gleichen Terminator (hier: Zeigerwert) zu sorgen. |
||
struct sll_node *SearchWithSentinel(int search_key) |
struct sll_node *SearchWithSentinel(int search_key) |
||
{ |
|||
struct sll_node *node; |
struct sll_node *node; |
||
// gezielte Präparation: |
|||
sentinel->key = search_key; |
|||
for (node = first; node->key != search_key; node = node->next) { |
for (node = first; |
||
node->key != search_key; |
|||
node = node->next) {} |
|||
⚫ | |||
if (node != sentinel) |
if (node != sentinel) |
||
return node; // gefunden |
return node; // gefunden |
||
// nicht gefunden |
return NULL; // nicht gefunden |
||
return NULL; |
|||
} |
} |
||
</syntaxhighlight> |
</syntaxhighlight> |
||
Die <code>for</code>-Schleife enthält pro Schleifenschritt nur die eine Abfrage |
Die <code>for</code>-Schleife enthält pro Schleifenschritt nur die eine Abfrage |
||
#<code>if (node->key != search_key)</code>. |
#<code>if (node->key != search_key)</code> (gelb hinterlegt). |
||
;Bemerkung |
;Bemerkung |
||
Wird auf die Datenstruktur [[Parallele Programmierung|parallel]] (konkurrent) zugegriffen, dann gehört auch <code>SearchWithSentinel</code> (modifizierende Operationen sowieso) in einen [[Kritischer Abschnitt|kritischen Abschnitt]], der durch ein [[Mutex]] abgesichert werden muss. |
Wird auf die Datenstruktur [[Parallele Programmierung|parallel]] (konkurrent) zugegriffen, dann gehört auch <code>SearchWithSentinel</code> (modifizierende Operationen sowieso) in einen [[Kritischer Abschnitt|kritischen Abschnitt]], der durch ein [[Mutex]] abgesichert werden muss. |
Version vom 20. Oktober 2019, 15:18 Uhr
Als Sentinel (Aussprache: Informatik, im Bereich der Programmierung, ein Konstrukt, welches eine Sequenz derart terminiert, dass die Programmlogik nach einer erfolglosen Inspektion aller echten Fälle abschließend (mit unechtem Erfolg) auf das Ergebnis »gefunden« läuft.[1] Wenn so geschehen, wird nachträglich das Ergebnis auf »nicht gefunden« korrigiert.
, engl. für Wächter), Wächter oder Wächterwert (im engeren Sinn) bezeichnet man in derMit diesem Trick wird die Anzahl der Abfragen innerhalb der Suchschleife um eine, nämlich die Abfrage auf das Ende der Sequenz, verringert – auf Kosten geringfügig komplizierterer Erfordernisse und Aktionen außerhalb der Schleife.
Im weiteren Sinn gilt (insbesondere im englischen Sprachraum) jede Form eines Terminators einer Sequenz, so auch das Nullzeichen bei Zeichenketten, als Sentinel.
Beispiel
In den beiden folgenden C-Funktionen Search
und SearchWithSentinel
soll in einer verketteten Liste vom Typ
struct sll_node // ein Knoten der verketteten Liste sll
{
int key;
struct sll_node *next; // end-of-list-Indikator oder -> nächster Knoten
} sll,
*first; // globale Variable
nach einem Schlüsselwert search_key
gesucht werden – bei gleichem Suchergebnis.
Version mit NULL
Die Liste sll
wird terminiert durch den Nullwert NULL
.
// Global:
first = NULL; // Terminierung vor der ersten Einfügung
// NB: Einfügung nicht gebracht. Sie hat aber
// für den immer gleichen Terminator (hier: Nullzeiger) zu sorgen.
struct sll_node *Search(int search_key)
{
struct sll_node *node;
for (node = first;
node != NULL;
node = node->next)
{
if (node->key == search_key)
return node; // gefunden
}
// nicht gefunden:
return NULL;
}
Die for
-Schleife enthält pro Schleifenschritt die zwei Abfragen
if (node != NULL)
undif (node->key == search_key)
(beide gelb hinterlegt).
Version mit Sentinel
Der global zugreifbare Zeiger sentinel
zum für die Schleife gezielt zu präparierenden Objekt Sentinel
dient als Terminator der Liste sll
.
// Globale Variable:
struct sll_node Sentinel, *sentinel = &Sentinel;
// Global:
sentinel->next = sentinel;
first = sentinel; // Terminierung vor der ersten Einfügung
// NB: Einfügung nicht gebracht. Sie hat aber
// für den immer gleichen Terminator (hier: Zeigerwert) zu sorgen.
struct sll_node *SearchWithSentinel(int search_key)
{
struct sll_node *node;
// gezielte Präparation:
sentinel->key = search_key;
for (node = first;
node->key != search_key;
node = node->next) {}
if (node != sentinel)
return node; // gefunden
return NULL; // nicht gefunden
}
Die for
-Schleife enthält pro Schleifenschritt nur die eine Abfrage
if (node->key != search_key)
(gelb hinterlegt).
- Bemerkung
Wird auf die Datenstruktur parallel (konkurrent) zugegriffen, dann gehört auch SearchWithSentinel
(modifizierende Operationen sowieso) in einen kritischen Abschnitt, der durch ein Mutex abgesichert werden muss.
Siehe auch
- Binärer Suchbaum#Suchen ohne Duplikate (iterativ und mit Sentinel) Wächterknoten in einem Binären Suchbaum
- Sentinel-Lymphknoten, siehe Wächterlymphknoten
Einzelnachweise
- ↑ Kurt Mehlhorn, Peter Sanders: Algorithms and Data Structures. The Basic Toolbox. Springer, Berlin / Heidelberg 2008, ISBN 978-3-540-77977-3, S. 63, doi:10.1007/978-3-540-77978-0. 3 Representing Sequences by Arrays and Linked Lists