Greedy-Algorithmus mit Beispiel: Was ist, Methode und Ansatz
Was ist ein Greedy-Algorithmus?
In Gieriger Algorithmus Eine Reihe von Ressourcen wird rekursiv aufgeteilt, basierend auf der maximalen, unmittelbaren Verfรผgbarkeit dieser Ressource in einer bestimmten Ausfรผhrungsphase.
Um ein Problem auf der Grundlage des Greedy-Ansatzes zu lรถsen, gibt es zwei Phasen
- Scannen der Artikelliste
- Optimierung
Diese Phasen werden in diesem Greedy-Algorithmus-Tutorial parallel zum Verlauf der Aufteilung des Arrays behandelt.
Um den Greedy-Algorithmus zu verstehen, benรถtigen Sie Grundkenntnisse in Rekursion und Kontextwechsel. Dies hilft Ihnen zu verstehen, wie manโฆ tracSchauen Sie sich den Code an. Sie kรถnnen das Greedy-Paradigma anhand Ihrer eigenen notwendigen und hinreichenden Aussagen definieren.
Zwei Bedingungen definieren das Greedy-Paradigma.
- Jede schrittweise Lรถsung muss ein Problem in Richtung der am besten akzeptierten Lรถsung strukturieren.
- Es reicht aus, wenn die Strukturierung des Problems in einer endlichen Anzahl gieriger Schritte anhalten kann.
Lassen Sie uns im weiteren Verlauf der Theorie die Geschichte beschreiben, die mit dem Greedy-Suchansatz verbunden ist.
Geschichte von Greedy Algorithms
Hier ist ein wichtiger Meilenstein der Greedy-Algorithmen:
- Greedy-Algorithmen wurden in den 1950er Jahren fรผr viele Graph-Walk-Algorithmen konzipiert.
- Esdger Djikstra hat den Algorithmus so konzipiert, dass er minimale Spannbรคume generiert. Sein Ziel war es, die Streckenlรคnge innerhalb der niederlรคndischen Hauptstadt Amsterdam zu verkรผrzen.
- Im selben Jahrzehnt entwickelten Prim und Kruskal Optimierungsstrategien, die auf der Minimierung der Pfadkosten entlang gewichteter Routen beruhten.
- In den 70er Jahren schlugen die amerikanischen Forscher Cormen, Rivest und Stein in ihrem klassischen Einfรผhrungsbuch in die Algorithmen eine rekursive Substrukturierung von Greedy-Lรถsungen vor.
- Das Greedy-Suchparadigma wurde 2005 als eine andere Art von Optimierungsstrategie in den NIST-Aufzeichnungen registriert.
- Bis heute verwenden Protokolle, die das Web betreiben, wie etwa das Open-Shortest-Path-First (OSPF) und viele andere Netzwerk-Paketvermittlungsprotokolle, die Greedy-Strategie, um den Zeitaufwand fรผr ein Netzwerk zu minimieren.
Gierige Strategien und Entscheidungen
Logik in ihrer einfachsten Form wurde auf โgierigโ oder โnicht gierigโ reduziert. Diese Aussagen wurden durch den Ansatz definiert, mit dem in jeder Algorithmusstufe vorangekommen wurde.
Beispielsweise nutzte der Algorithmus von Djikstra eine schrittweise gierige Strategie zur Identifizierung von Hosts im Internet durch Berechnung einer Kostenfunktion. Der von der Kostenfunktion zurรผckgegebene Wert legte fest, ob der nรคchste Pfad โgierigโ oder โnicht gierigโ ist.
Kurz gesagt: Ein Algorithmus ist nicht mehr gierig, wenn er zu irgendeinem Zeitpunkt einen Schritt unternimmt, der nicht lokal gierig ist. Die Greedy-Probleme hรถren auf, da die Gier kein weiteres Ausmaร mehr hat.
Eigenschaften des Greedy-Algorithmus
Die wichtigen Merkmale eines Greedy-Algorithmus sind:
- Es gibt eine geordnete Liste von Ressourcen mit Kosten- oder Wertzuordnungen. Diese quantifizieren Einschrรคnkungen eines Systems.
- In der Zeit, in der eine Einschrรคnkung gilt, nehmen Sie die maximale Menge an Ressourcen in Anspruch.
- Beispielsweise werden bei einem Aktivitรคtsplanungsproblem die Ressourcenkosten in Stunden angegeben und die Aktivitรคten mรผssen in serieller Reihenfolge ausgefรผhrt werden.
Warum den Greedy-Ansatz verwenden?
Hier sind die Grรผnde fรผr die Verwendung des Greedy-Ansatzes:
- Der Greedy-Ansatz weist einige Kompromisse auf, die ihn mรถglicherweise fรผr die Optimierung geeignet machen.
- Ein wichtiger Grund ist, sofort die realisierbarste Lรถsung zu finden. Wenn beim Aktivitรคtsauswahlproblem (unten erlรคutert) mehr Aktivitรคten ausgefรผhrt werden kรถnnen, bevor die aktuelle Aktivitรคt abgeschlossen ist, kรถnnen diese Aktivitรคten gleichzeitig ausgefรผhrt werden.
- Ein weiterer Grund besteht darin, ein Problem rekursiv basierend auf einer Bedingung zu unterteilen, ohne dass alle Lรถsungen kombiniert werden mรผssen.
- Beim Aktivitรคtsauswahlproblem wird der Schritt der โrekursiven Divisionโ erreicht, indem eine Liste von Elementen nur einmal gescannt und bestimmte Aktivitรคten berรผcksichtigt werden.
So lรถsen Sie das Problem der Aktivitรคtsauswahl
Im Beispiel der Aktivitรคtsplanung gibt es fรผr jede Aktivitรคt eine โStartโ- und โEndzeitโ. Jede Aktivitรคt ist als Referenz mit einer Nummer versehen. Es gibt zwei Aktivitรคtskategorien.
- betrachtete Aktivitรคt: ist die Aktivitรคt, die die Referenz darstellt, anhand derer die Fรคhigkeit analysiert wird, mehr als eine verbleibende Aktivitรคt auszufรผhren.
- verbleibende Aktivitรคten: Aktivitรคten an einem oder mehreren Indizes vor der betrachteten Aktivitรคt.
Die Gesamtdauer gibt die Kosten fรผr die Durchfรผhrung der Aktivitรคt an. Das heiรt (Ende โ Anfang) gibt uns die Dauer als Kosten einer Aktivitรคt an.
Sie werden erfahren, dass das Greedy-Ausmaร die Anzahl der verbleibenden Aktivitรคten ist, die Sie in der Zeit einer betrachteten Aktivitรคt ausfรผhren kรถnnen.
ArchiStruktur des Greedy-Ansatzes
SCHRITT 1) Durchsuchen Sie die Liste der Aktivitรคtskosten, beginnend mit Index 0 als berรผcksichtigtem Index.
SCHRITT 2) Wenn bis zum Abschluss der betreffenden Aktivitรคt noch weitere Aktivitรคten abgeschlossen werden kรถnnen, beginnen Sie mit der Suche nach einer oder mehreren verbleibenden Aktivitรคten.
SCHRITT 3) Wenn keine verbleibenden Aktivitรคten mehr vorhanden sind, wird die aktuelle verbleibende Aktivitรคt zur nรคchsten berรผcksichtigten Aktivitรคt. Wiederholen Sie Schritt 1 und Schritt 2 mit der neu in Betracht gezogenen Aktivitรคt. Wenn keine verbleibenden Aktivitรคten mehr vorhanden sind, fahren Sie mit Schritt 4 fort.
SCHRITT 4 ) Gibt die Vereinigung der betrachteten Indizes zurรผck. Dies sind die Aktivitรคtsindizes, die zur Maximierung des Durchsatzes verwendet werden.

Code Erlรคuterung
#include<iostream> #include<stdio.h> #include<stdlib.h> #define MAX_ACTIVITIES 12
Erklรคrung des Codes:
- Enthaltene Header-Dateien/Klassen
- Eine maximale Anzahl von Aktivitรคten, die vom Benutzer bereitgestellt werden.
using namespace std;
class TIME
{
public:
int hours;
public: TIME()
{
hours = 0;
}
};
Erklรคrung des Codes:
- Der Namespace fรผr Streaming-Vorgรคnge.
- Eine Klassendefinition fรผr TIME
- Ein Stunden-Zeitstempel.
- Ein TIME-Standardkonstruktor
- Die Stundenvariable.
class Activity
{
public:
int index;
TIME start;
TIME finish;
public: Activity()
{
start = finish = TIME();
}
};
Erklรคrung des Codes:
- Eine Klassendefinition aus Aktivitรคt
- Zeitstempel, die eine Dauer definieren
- Alle Zeitstempel werden im Standardkonstruktor auf 0 initialisiert
class Scheduler
{
public:
int considered_index,init_index;
Activity *current_activities = new Activity[MAX_ACTIVITIES];
Activity *scheduled;
Erklรคrung des Codes:
- Teil 1 der Definition der Scheduler-Klasse.
- Der berรผcksichtigte Index ist der Ausgangspunkt fรผr das Scannen Array.
- Der Initialisierungsindex wird verwendet, um zufรคllige Zeitstempel zuzuweisen.
- Ein Array von Aktivitรคtsobjekten wird dynamisch mithilfe des neuen Operators zugewiesen.
- Der geplante Zeiger definiert den aktuellen Basisstandort fรผr Gier.
Scheduler()
{
considered_index = 0;
scheduled = NULL;
...
...
Erklรคrung des Codes:
- Der Scheduler-Konstruktor โ Teil 2 der Scheduler-Klassendefinition.
- Der betrachtete Index definiert den aktuellen Start des aktuellen Scans.
- Der aktuelle Greedy-Ausmaร ist zu Beginn undefiniert.
for(init_index = 0; init_index < MAX_ACTIVITIES; init_index++)
{
current_activities[init_index].start.hours =
rand() % 12;
current_activities[init_index].finish.hours =
current_activities[init_index].start.hours +
(rand() % 2);
printf("\nSTART:%d END %d\n",
current_activities[init_index].start.hours
,current_activities[init_index].finish.hours);
}
โฆ
โฆ
Erklรคrung des Codes:
- Eine For-Schleife zum Initialisieren der Start- und Endzeiten aller aktuell geplanten Aktivitรคten.
- Startzeitinitialisierung.
- Endzeitinitialisierung immer nach oder genau zur Startstunde.
- Eine Debug-Anweisung zum Ausdrucken zugewiesener Dauern.
public: Activity * activity_select(int); };
Erklรคrung des Codes:
- Teil 4 โ der letzte Teil der Definition der Scheduler-Klasse.
- Die Aktivitรคtsauswahlfunktion verwendet einen Startpunktindex als Basis und unterteilt die gierige Suche in gierige Teilprobleme.
Activity * Scheduler :: activity_select(int considered_index)
{
this->considered_index = considered_index;
int greedy_extent = this->considered_index + 1;
โฆ
โฆ
- Mithilfe des Bereichsauflรถsungsoperators (::) wird die Funktionsdefinition bereitgestellt.
- Der betrachtete Index ist der nach Wert aufgerufene Index. Der greedy_extent wird nur einen Index nach dem betrachteten Index initialisiert.
Activity * Scheduler :: activity_select(int considered_index)
{
while( (greedy_extent < MAX_ACTIVITIES ) &&
((this->current_activities[greedy_extent]).start.hours <
(this->current_activities[considered_index]).finish.hours ))
{
printf("\nSchedule start:%d \nfinish%d\n activity:%d\n",
(this->current_activities[greedy_extent]).start.hours,
(this->current_activities[greedy_extent]).finish.hours,
greedy_extent + 1);
greedy_extent++;
}
โฆ
...
Erklรคrung des Codes:
- Die Kernlogik: Das Ausmaร der Gier ist auf die Anzahl der Aktivitรคten beschrรคnkt.
- Die Startstunden der aktuellen Aktivitรคt werden als planbar รผberprรผft, bevor die betreffende Aktivitรคt (angegeben durch den betreffenden Index) enden wรผrde.
- Solange dies mรถglich ist, wird eine optionale Debug-Anweisung gedruckt.
- Gehen Sie zum nรคchsten Index im Aktivitรคtsarray
...
if ( greedy_extent <= MAX_ACTIVITIES )
{
return activity_select(greedy_extent);
}
else
{
return NULL;
}
}
Erklรคrung des Codes:
- Die Bedingung prรผft, ob alle Aktivitรคten abgedeckt wurden.
- Wenn nicht, kรถnnen Sie Ihren Greedy mit dem betrachteten Index als aktuellem Punkt neu starten. Dies ist ein rekursiver Schritt, der die Problemstellung gierig teilt.
- Wenn ja, kehrt es zum Anrufer zurรผck und hat keinen Spielraum fรผr die Ausweitung der Gier.
int main()
{
Scheduler *activity_sched = new Scheduler();
activity_sched->scheduled = activity_sched->activity_select(
activity_sched->considered_index);
return 0;
}
Erklรคrung des Codes:
- Die Hauptfunktion zum Aufrufen des Planers.
- Ein neuer Scheduler wird instanziiert.
- Die Aktivitรคtsauswahlfunktion, die einen Zeiger vom Typ Aktivitรคt zurรผckgibt, kehrt zum Aufrufer zurรผck, nachdem die gierige Suche beendet ist.
Ausgang:
START:7 END 7 START:9 END 10 START:5 END 6 START:10 END 10 START:9 END 10 Schedule start:5 finish6 activity:3 Schedule start:9 finish10 activity:5
Einschrรคnkungen der Greedy-Technik
Es ist nicht fรผr Greedy-Probleme geeignet, bei denen fรผr jedes Teilproblem wie das Sortieren eine Lรถsung erforderlich ist.
Bei solchen รbungsproblemen des Greedy-Algorithmus kann die Greedy-Methode falsch sein; im schlimmsten Fall sogar zu einer nicht optimalen Lรถsung fรผhren.
Der Nachteil von Greedy-Algorithmen besteht daher darin, dass man nicht weiร, was vor dem aktuellen Greedy-Zustand liegt.
Nachfolgend finden Sie eine Darstellung der Nachteile der Greedy-Methode:
Im hier als Baum dargestellten gierigen Scan (hรถherer Wert, hรถhere Gier) nimmt ein Algorithmus mit dem Wert 40 wahrscheinlich 29 als nรคchsten Wert an. Auรerdem endet seine Quest bei 12. Dies ergibt einen Wert von 41.
Allerdings, wenn der Algorithmus einen suboptimalen Weg eingeschlagen oder eine Eroberungsstrategie รผbernommen hat. dann wรผrde auf 25 40 folgen, und die Gesamtkostenverbesserung wรคre 65, was als suboptimale Entscheidung um 24 Punkte hรถher bewertet wird.
Beispiele fรผr Gierig Algorithms
Die meisten Netzwerkalgorithmen verwenden den Greedy-Ansatz. Hier ist eine Liste einiger Beispiele fรผr Greedy-Algorithmen:
- Prims Minimal Spanning Tree-Algorithmus
- Problem mit dem reisenden Verkรคufer
- Diagramm โ Kartenfรคrbung
- Kruskals Minimal-Spanning-Tree-Algorithmus
- Dijkstras Minimal Spanning Tree-Algorithmus
- Diagramm โ Scheitelpunktabdeckung
- Rucksackproblem
- Jobplanungsproblem
Zusammenfassung
Zusammenfassend lรคsst sich sagen, dass der Artikel das Greedy-Paradigma definiert und gezeigt hat, wie Greedy-Optimierung und Rekursion Ihnen helfen kรถnnen, bis zu einem gewissen Punkt die beste Lรถsung zu finden. Der Greedy-Algorithmus wird in vielen Sprachen hรคufig zur Problemlรถsung eingesetzt, und zwar als Greedy-Algorithmus Python, C, C#, PHP, Javausw. Die Aktivitรคtsauswahl des Greedy-Algorithmusbeispiels wurde als strategisches Problem beschrieben, bei dem mit dem Greedy-Ansatz ein maximaler Durchsatz erzielt werden konnte. Abschlieรend wurden die Nachteile der Verwendung des Greedy-Ansatzes erlรคutert.













