Der Satz ist ein Auflistungstyp, der die grundlegenden algebraischen Satzalgorithmen implementiert, einschließlich Vereinigung, Schnittmenge, Differenz und symmetrischer Differenz. Jeder dieser Algorithmen wird in den jeweiligen Abschnitten ausführlich erläutert.
Konzeptionell sind Sets Sammlungen von Objekten, die häufig Gemeinsamkeiten aufweisen. Zum Beispiel könnten wir eine Menge haben, die sogar positive ganze Zahlen enthält:
[2, 4, 6, 8, 10,…]
Und ein Set, das positive ungerade ganze Zahlen enthält:
[1, 3, 5, 7, 9,…]
Diese beiden Sätze haben keine gemeinsamen Werte. Betrachten wir nun einen dritten Satz, der alle Faktoren der Zahl 100 darstellt:
[1, 2, 4, 5, 10, 20, 25, 50, 100]
In Anbetracht dieser Mengen können wir nun die Frage „Welche Faktoren von 100 sind ungerade?“ Beantworten, indem wir die Menge der ungeraden Ganzzahlen und die Menge der Faktoren von 100 betrachten und sehen, welche Werte in beiden Mengen vorhanden sind. Aber wir könnten auch Fragen beantworten wie: "Welche ungeraden Zahlen sind keine Faktoren von 100?" Oder "Welche positiven Zahlen, gerade oder ungerade, sind keine Faktoren von 100?"
Das mag nicht sehr nützlich erscheinen, aber das liegt daran, dass das Beispiel etwas durchdacht ist. Stellen Sie sich vor, die Sets wären alle Mitarbeiter eines Unternehmens und alle Mitarbeiter, die die jährliche Schulung absolviert haben.
Wir könnten leicht die Frage beantworten: "Welche Mitarbeiter haben die obligatorische Schulung nicht absolviert?"
Wir können fortlaufend weitere Sätze hinzufügen und beginnen, sehr komplexe Fragen zu beantworten, z.
Das einstellen
Klasse implementiert die IEnumerable
Schnittstelle und akzeptiert ein generisches Argument, das ein sein sollte IC vergleichbar
type (Test auf Gleichheit ist notwendig, damit die eingestellten Algorithmen funktionieren).
Die Mitglieder des Sets werden in einem .NET enthalten Liste
Klasse, aber in der Praxis sind Sets oft in Baumstrukturen enthalten, wie z. B. einem binären Suchbaum. Diese Wahl des zugrunde liegenden Containers beeinflusst die Komplexität der verschiedenen Algorithmen. Zum Beispiel mit der Liste
, Enthält
hat eine Komplexität von O (n), wohingegen die Verwendung eines Baums im Durchschnitt zu O (log n) führen würde.
Zusätzlich zu den Methoden, die wir implementieren werden, die einstellen
Enthält einen Standardkonstruktor und einen, der ein akzeptiert IEnumerable
von Elementen, um den Satz mit zu füllen.
public class Set: IEnumerable Dabei gilt Folgendes: T: IComparable private readonly List _items = new List (); public Set () public Set (IEnumerable-Elemente) AddRange (items); public void Add (T item); public void AddRange (IEnumerable-Elemente); public bool Remove (T-Eintrag); public bool Enthält (T-Eintrag); public int Count erhalten; public Set Union (Set other); public Set Intersection (Set other); public Set Difference (Andere einstellen); public Set SymmetricDifference (Set other); public IEnumerator GetEnumerator (); System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator ();
Verhalten | Fügt das Element dem Satz hinzu. Wenn das Element bereits in der Gruppe vorhanden ist, wird eine InvalidOperationException ausgelöst. |
Performance | Auf) |
Bei der Implementierung des Hinzufügen
Algorithmus muss eine Entscheidung getroffen werden: Wird das Set doppelte Elemente zulassen oder nicht? Zum Beispiel gegeben der folgende Satz:
[1, 2, 3, 4]
Wenn der Anrufer versucht, den Wert drei hinzuzufügen, wird der Satz folgendermaßen:
[1, 2, 3, 3, 4]
Während dies in manchen Kontexten akzeptabel ist, ist es nicht das Verhalten, das wir implementieren werden. Stellen Sie sich ein Set vor, das alle Schüler einer örtlichen Hochschule enthält. Es ist nicht logisch, dass derselbe Schüler zweimal zum Satz hinzugefügt wird. In der Tat ist der Versuch wahrscheinlich ein Fehler (und wird in dieser Implementierung als solcher behandelt)..
Hinweis: Hinzufügen verwendet die Enthält
Methode
public void Add (T item) if (Enthält (item)) neue InvalidOperationException werfen ("Element ist bereits in Set vorhanden"); _items.Add (item);
Verhalten | Fügt dem Satz mehrere Elemente hinzu. Wenn ein Mitglied des Eingabe-Enumerators im Satz vorhanden ist oder wenn doppelte Elemente im Eingabe-Enumerator vorhanden sind, wird eine InvalidOperationException ausgelöst. |
Performance | O (mn), wobei m die Anzahl der Elemente in der Eingabeaufzählung und n die Anzahl der Elemente ist, die sich aktuell im Set befinden. |
public void AddRange (IEnumerable items) foreach (T item in items) Add (item);
Verhalten | Entfernt den angegebenen Wert aus der Gruppe, wenn er gefunden wird, und gibt true zurück. Wenn der Satz den angegebenen Wert nicht enthält, wird false zurückgegeben. |
Performance | Auf) |
public bool Remove (T item) return _items.Remove (item);
Verhalten | Gibt "true" zurück, wenn der Satz den angegebenen Wert enthält. Andernfalls wird falsch zurückgegeben. |
Performance | Auf) |
public bool Enthält (T item) return _items.Contains (item);
Verhalten | Gibt die Anzahl der Elemente im Set oder 0 zurück, wenn das Set leer ist. |
Performance | O (1) |
public int Count get return _items.Count;
Verhalten | Gibt einen Enumerator für alle Elemente in der Gruppe zurück. |
Performance | O (1), um den Enumerator zurückzugeben. Das Aufzählen aller Elemente hat eine Komplexität von O (n).. |
public IEnumerator GetEnumerator () return _items.GetEnumerator (); System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator () return _items.GetEnumerator ();
Verhalten | Gibt einen neuen Satz zurück, der das Ergebnis der Vereinigungsoperation des aktuellen Satzes und des Eingangssatzes ist. |
Performance | O (mn), wobei m und n die Anzahl der Elemente in den bereitgestellten bzw. aktuellen Mengen sind. |
Die Vereinigung zweier Sätze ist ein Satz, der alle unterschiedlichen Elemente enthält, die in beiden Sätzen vorhanden sind.
Zum Beispiel zwei gegebene Mengen (jeweils rot dargestellt):
Zwei Eingabesätze vor der VereinigungsoperationWenn die Vereinigungsoperation ausgeführt wird, enthält der Ausgabesatz alle Elemente in beiden Sätzen. Wenn in beiden Sätzen Elemente vorhanden sind, wird nur eine einzelne Kopie jedes Elements zum Ausgabesatz hinzugefügt.
Die nach dem Union-Vorgang gesetzte Ausgabe (zurückgegebene Artikel sind gelb)Ein konkreteres Beispiel ist zu sehen, wenn wir mehrere Gruppen von Ganzzahlen zusammenführen:
[1, 2, 3, 4]
Union [3, 4, 5, 6]
= [1, 2, 3, 4, 5, 6]
public Set Union (Andere setzen) Set result = new Set (_items); foreach (T item in other._items) if (! Contains (item)) result.Add (item); Ergebnis zurückgeben;
Verhalten | Gibt einen neuen Satz zurück, der das Ergebnis der Schnittmenge des aktuellen Satzes und des Eingangssatzes ist. |
Performance | O (mn), wobei m und n die Anzahl der Elemente in den bereitgestellten bzw. aktuellen Mengen sind. |
Schnittpunkt ist der Punkt, an dem sich zwei Sätze "schneiden", beispielsweise ihre gemeinsamen Mitglieder. Anhand des Venn-Diagramms aus dem Union-Beispiel wird hier der Schnittpunkt der beiden Mengen dargestellt:
Der Schnittpunkt der beiden Eingangssätze ist gelb dargestelltOder mit ganzen Zahlen:
[1, 2, 3, 4]
sich schneiden [3, 4, 5, 6]
= [3, 4]
public Set Intersection (Set other) Set Ergebnis = Neu Set (); foreach (T item in _items) if (other._items.Contains (item)) result.Add (item); Ergebnis zurückgeben;
Verhalten | Gibt einen neuen Satz zurück, der das Ergebnis der Differenzoperation der aktuellen und der Eingangssätze ist. |
Performance | O (mn), wobei m und n die Anzahl der Elemente in den bereitgestellten bzw. aktuellen Mengen sind. |
Die Differenz oder Satzdifferenz zwischen zwei Sätzen ist die Elemente, die im ersten Satz vorhanden sind (der Satz, dessen Unterschied
Methode wird aufgerufen), sind aber in der zweiten Menge (dem Parameter der Methode) nicht vorhanden. Das Venn-Diagramm für diese Methode wird hier mit dem zurückgegebenen Satz in Gelb angezeigt:
Oder mit ganzen Zahlen:
[1, 2, 3, 4]
Unterschied [3, 4, 5, 6]
= [1, 2]
public Set Difference (Andere setzen) Set result = new Set (_items); foreach (T item in other._items) result.Remove (item); Ergebnis zurückgeben;
Verhalten | Gibt einen neuen Satz zurück, der das Ergebnis der symmetrischen Differenzoperation des aktuellen Satzes und des Eingangssatzes ist. |
Performance | O (mn), wobei m und n die Anzahl der Elemente in den bereitgestellten bzw. aktuellen Mengen sind. |
Der symmetrische Unterschied zweier Sätze ist ein Satz, dessen Mitglieder die Elemente sind, die nur in dem einen oder dem anderen Satz vorhanden sind. Das Venn-Diagramm für diese Methode wird hier mit dem zurückgegebenen Satz in Gelb angezeigt
Der symmetrische Unterschied von zwei SätzenOder verwenden Sie Ganzzahlsätze:
[1, 2, 3, 4]
symmetrischer Unterschied [3, 4, 5, 6]
= [1, 2, 5, 6]
Möglicherweise haben Sie festgestellt, dass dies genau das Gegenteil der Kreuzungsoperation ist. Lassen Sie uns vor diesem Hintergrund sehen, was es braucht, um den symmetrischen Unterschied nur mit den bereits gesetzten Algorithmen zu finden.
Gehen wir durch das, was wir wollen.
Wir möchten ein Set, das alle Elemente aus beiden Sets enthält, mit Ausnahme der Elemente, die in beiden vorhanden sind. Oder anders gesagt, wir wollen die Vereinigung beider Mengen mit Ausnahme der Schnittmenge beider Mengen. Wir wollen den Satzunterschied zwischen der Vereinigung und dem Schnittpunkt beider Mengen.
Schritt für Schritt sieht es so aus:
[1, 2, 3, 4]
Union [3, 4, 5, 6]
= [1, 2, 3, 4, 5, 6]
[1, 2, 3, 4]
Überschneidung [3, 4, 5, 6]
= [3, 4]
[1, 2, 3, 4, 5, 6]
Differenz einstellen [3, 4]
= [1, 2, 5, 6]
Was ergibt das Ergebnis, das wir wollten:[1, 2, 5, 6]
).
public Set SymmetricDifference (Andere setzen) Set union = Union (andere); Schnittmenge festlegen = Schnittmenge (andere); return union.Difference (Kreuzung);
Sie fragen sich vielleicht, warum ich keine hinzugefügt habe IsSubset
Methode. Diese Art von Methode wird häufig verwendet, um festzustellen, ob eine Gruppe vollständig in einer anderen Gruppe enthalten ist. Zum Beispiel möchten wir vielleicht wissen, ob:
[1, 2, 3]
ist Teilmenge [0, 1, 2, 3, 4, 5]
= wahr
Wohingegen:
[1, 2, 3]
ist Teilmenge [0, 1, 2]
= falsch
Der Grund, aus dem ich keinen detailliert habe IsSubset
Methode ist, dass es mit vorhandenen Mitteln durchgeführt werden kann. Zum Beispiel:
[1, 2, 3]
Unterschied [0, 1, 2, 3, 4, 5]
= []
Eine leere Ergebnismenge zeigt, dass die gesamte erste Menge in der zweiten Menge enthalten war. Wir wissen also, dass die erste Menge eine vollständige Teilmenge der zweiten ist. Ein anderes Beispiel mit der Kreuzung:
[1, 2, 3]
Überschneidung [0, 1, 2, 3, 4, 5]
= [1, 2, 3]
Wenn der Ausgangssatz die gleiche Anzahl von Elementen wie der Eingangssatz hat, wissen wir, dass der Eingangssatz eine Untermenge des zweiten Satzes ist.
In einer Set-Klasse für allgemeine Zwecke mit einer IsSubset
Methode kann nützlich sein (und könnte optimaler implementiert werden); Ich wollte jedoch darauf hinweisen, dass dies nicht unbedingt ein neues Verhalten ist, sondern lediglich eine andere Art, über bestehende Operationen nachzudenken.