Sortierprogramm für LinkedList

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
flori65817
User
Beiträge: 9
Registriert: Mittwoch 27. Mai 2020, 11:41

Hallo liebes Forum ,wir sollen als Übung ein Programm schreiben was eine Textdatei einließt daraus dann eine LinkedList erstellt und die dann mittels Bubblesort Algorithmus sortiert.
Leider fehlt mir dazu die nötigen Kenntnisse ,ich würde mich um eure Hilfe freuen.


Als Vorgabe haben wir diese Klasse bekommen :

class Fahrzeug :
def __init__(self, Farbe, Marke) :
self.Farbe = Farbe
self.Marke = Marke
self.vorgaenger = None
self.nachfolger = None
print("Neues Fahrzeug definiert: %s " % (self.Marke))

def anhaengen(self, cur):
cur.vorgaenger = self
self.nachfolger = cur

def hatVorgaenger(self):
if self.vorgaenger == None:
return False
else:
return True

und dazu diese txt Datei:

BMW
rot
VW
blau
Toyota
gruen
Honda
tuerkis
VW
schwarz
Subaru
braun
BMW
blau

Ich verstehe wie man normale TxT Datein einließt aber nicht wie ich die 1 Zeile zB der Marke zuordne und die 2 Zeile der Farbe.Es soll auch so sein das man auch andere Fahrzeuglisten die länger sind nehmen kann und man darf die TxT Datei nicht als Liste einlesen und soll direkt Objekte erstellen ,dann sollen die Objekte vor der Sortierung Angezeigt werden und dann nach der Sortierung mit Bubblesort soll das Ergebnis angezeigt werden.

Ich hoffe es gibt einen Fachmann der mit helfen kann :D :P
Benutzeravatar
__blackjack__
User
Beiträge: 13110
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@flori65817: Dateiobjekte sind Iteratoren über die Zeilen, das heisst man kann die nicht nur in einer ``for``-Schleife benutzen, sondern auch mit der `next()`-Funktion die jeweils nächste Zeile abfragen.

Oder man verwendet die `zip()`-Funktion um aus dem Iterator der einzelne Zeilen liefert, einen zu machen, der immer zwei Zeilen zusammen als Tupel liefert.

Zu der Fahrzeug-Klasse: Namen werden in Python klein_mit_unterstrichen geschrieben. Ausnahmen sind Konstanten KOMPLETT_GROSS und Klassen (MixedCase). `Farbe`, `Marke`, und `hatVorgaenger()` entsprechen also nicht den Konventionen.

Namen sollten keine kryptischen Abkürzungen enthalten und schon gar nicht nur daraus bestehen. Was soll `cur` denn überhaupt bedeuten?

``%`` zur Formatierung von Zeichenketten würde ich nicht mehr verwenden. Dafür gibt es die `format()`-Methode auf Zeichenketten, beziehungsweise ab Python 3.6 f-Zeichenkettenliterale. Ein `print()` gehört da aber sowieso nicht an der Stelle in die `__init__()`. Das wäre eine Ausgabe für's Logging.

`hat_vorgaenger()` ist unnötig umständlich. Der Vergleich ergibt ja schon einen Wahrheitswert und den Vergleich sollte man einfach so formulieren, dass man diesen Wahrheitswert einfach zurückgeben kann:

Code: Alles auswählen

class Fahrzeug:
    def __init__(self, farbe, marke):
        self.farbe = farbe
        self.marke = marke
        self.vorgaenger = None
        self.nachfolger = None
        # print(f"Neues Fahrzeug definiert: {self.marke}")

    def hat_vorgaenger(self):
        return self.vorgaenger is not None

    def anhaengen(self, fahrzeug):
        fahrzeug.vorgaenger = self
        self.nachfolger = fahrzeug
Nach was soll eigentlich sortiert werden?
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
flori65817
User
Beiträge: 9
Registriert: Mittwoch 27. Mai 2020, 11:41

Danke @__blackjack__ für die schnelle Antwort, unser Lehrer hat uns die Klasse so vorgegeben es soll nach der Marke sortiert werden und es soll eine linked list sein.
ich habe aber probleme die Txt datei einzulesen und die objekte zu erzeugen .......
Sirius3
User
Beiträge: 17750
Registriert: Sonntag 21. Oktober 2012, 17:20

Weißt Du denn, wie man eine Datei zeilenweise einliest?
Wenn man nichts über Iteratoren wüßte, dann würde man in einer for-Schleife einen Zähler (per enumerate) mitzählen lassen und bei jeder ungeraden Zeile sich den Typ merken und bei jeder geraden Zeile ein Fahrzeug mit Typ und Farbe erzeugen.

Das geht halt mit Iterator und zip eleganter:

Code: Alles auswählen

zahlen = iter([1,2,3,4,5,6])
for a, b in zip(zahlen, zahlen):
    print(a,b)
Und ein Dateiobjekt ist ja ein Iterator.
flori65817
User
Beiträge: 9
Registriert: Mittwoch 27. Mai 2020, 11:41

Hallo Sirius3 vielen dank für deine Antwort also den Code den du geschrieben hast verstehe ich aber ich schaffe es noch nicht das auf meinen Fall anzuwenden den ich soll direkt aus der TxT Datei ,Objekte erzeugen die die Attribute Marke und Farbe haben kannst du mir da nochmal auf die Sprünge helfen ?
Ich freue mich das es hier Leute gibt die einen versuchen zu helfen das ist echt nett :)
Sirius3
User
Beiträge: 17750
Registriert: Sonntag 21. Oktober 2012, 17:20

Das soll ja ein Beispiel sein, das nicht direkt Deine Hausaufgaben löst.
Die Übertragung auf Dein Problem solltest Du schon selbst hinbekommen.
Zeig doch mal, was Du versucht hast.
flori65817
User
Beiträge: 9
Registriert: Mittwoch 27. Mai 2020, 11:41

also es soll niemand meine Hausaufgaben lösen ich brauche eben Hilfe ich Sitze da wirklich schon Seit tagen und probiere aber es kommt nichts bei raus....

Code: Alles auswählen

class Fahrzeug :
	def __init__(self, Farbe, Marke) :
		self.Farbe = Farbe
		self.Marke = Marke
		self.vorgaenger = None
		self.nachfolger = None		
		print("Neues Fahrzeug : %s %s " % (self.Marke,self.Farbe))
				
	def anhaengen(self, cur):
		cur.vorgaenger = self
		self.nachfolger = cur

	def hatVorgaenger(self):
		if self.vorgaenger == None:
			return False
		else:
			return True
		




file = open("fahrzeugliste.txt")
for line in file:
    Fahrzeugliste = line.split()
    FahrzeugMarke = str(Fahrzeugliste[0])                    
    Fahrzeugliste = line.split()
    FahrzeugFarbe = str(Fahrzeugliste[0])
    file.readline()
    print ("Marke: "+FahrzeugMarke,"Farbe: "+FahrzeugFarbe)                
file.close()
print("\n")








f = None				
for i in range(10):	
	fNeu = Fahrzeug(FahrzeugFarbe,FahrzeugMarke)
	if f == None:		
		f = fNeu
	else:
		f.anhaengen(fNeu)
		f = fNeu

while f.hatVorgaenger():
	print("Vorgänger von %s ist %s." % (f.Marke, f.vorgaenger.Marke))
	f = f.vorgaenger
print("bin wieder vorn angekommen bei: %s " % (f.Marke,f.Farbe))

es soll einfach die text datei einlesen und die objekte automatisch erzeugen das bekomme ich einfach nicht hin
Sirius3
User
Beiträge: 17750
Registriert: Sonntag 21. Oktober 2012, 17:20

Was ist der Inhalt von `Fahrzeugliste`? Und warum glaubst Du, dass beim ersten Mal die Marke und beim zweiten Mal die Farbe in der selben Variable steht? split aufzurufen und dann nur das erste Element der Liste zu benutzen ist schon seltsam, erst recht wenn man weiß, dass es nur ein Element pro Zeile gibt. Was denkst Du macht das readline am Ende?

Die for-Schleife läßt sich auf das hier verkürzen:

Code: Alles auswählen

with open("fahrzeugliste.txt") as file:
    for line in file:
        fahrzeug_marke = fahrzeug_farbe = line.strip()
        unbenutzt = file.readline()
        print(f"Marke: {fahrzeug_marke} Farbe: {fahrzeug_farbe}")
Das sollte nochmal deutlicher machen, dass Marke und Farbe identisch sind.
Und wie könnte nun meine for-Schleife mit Deiner kombiniert werden?
flori65817
User
Beiträge: 9
Registriert: Mittwoch 27. Mai 2020, 11:41

ich sag für den Part schon mal danke ich habe das jetzt etwas zusammen gemixt
das sieht so aus:

Code: Alles auswählen

 #Daten soll eingelesen werden    
    def Dateneinlesen():
        with open("fahrzeugliste.txt") as Fahrzeugliste:
            content = Fahrzeugliste.readlines()
            
        zahlen = iter(content)
        for Marke,Farbe in zip(zahlen,zahlen):
            Fahrzeug.Marke = Marke.strip()
            Fahrzeug.Farbe = Farbe.strip()
            f = None				
            fNeu = Fahrzeug(Fahrzeug.Farbe,Fahrzeug.Marke)
            if f == None:		
                f = fNeu
            else:			
                f.anhaengen(fNeu)
                f = fNeu
            while f.hatVorgaenger():
                f = f.vorgaenger    
            print("Marke: %s  Farbe: %s" % (f.Marke,f.Farbe))


jetzt brauche ich noch tipps wie ich den Bubblesort Algoritmus darauf anpassen kann

ich habe als Grundlage das hier:

Code: Alles auswählen

#Sortiermethode 
    def sortierung(self):
        pruefvar = True
        Anzahl = 0
        #Such-/Sortierschleife
        while(pruefvar):
            pruefvar = False
            # Benachbarte Elemente werden überprüft und sollen nun ausgetaucht werden
            for i in range(len(Fahrzeugliste)-Anzahl -1):
                if Fahrzeugliste[i] > Fahrzeugliste [i+1]:
                # Elemente werden ausgetausch
                    Fahrzeugliste[i], Fahrzeugliste[i+1] = Fahrzeugliste[i+1], Fahrzeugliste
                    pruefvar = True
        # Anzahl wird um 1 erhöht
        Anzahl += 1
Sirius3
User
Beiträge: 17750
Registriert: Sonntag 21. Oktober 2012, 17:20

Du sollst doch nicht erst die ganze Datei in eine Liste einlesen.
Das setzen von Klassenkonstanten auf `Fahrzeug` ist auch falsch. Warum benutzt Du keine lokalen Variablen? Bzw. warum überhaupt das Ergebnis von strip nochmal an eine Variable binden?
Wenn eine Zeile sowohl im if- als auch im else-Block vorkommt, kann man die auch nach dem else-Block schreiben. Auf None prüft man nicht mit == sondern mit is. Und da der if-Block leer sein wird, `is not`. Nach Konstruktion hat `f` niemals einen Nachfolger.
Funktionen- und Variablennamen schreibt man immer noch klein. So schwer kann die Umsetzung doch nicht sein.

Du sollst doch mit der verketteten Liste sortieren und nicht mit irgendeiner normalen Liste. Alles was eine Funktion braucht, sollte sie über ihre Argumente bekommen. Fahrzeugliste kommt aber aus dem nichts.
flori65817
User
Beiträge: 9
Registriert: Mittwoch 27. Mai 2020, 11:41

Oh dann bin ich völlig falsch ich habe jetzt einfach keine Idee mehr ich sitze wirklich seit Wochen daran .......
Wie wäre es den Richtig?
Sirius3
User
Beiträge: 17750
Registriert: Sonntag 21. Oktober 2012, 17:20

Bei `Dateieinlesen` (eigentlich `datei_einlesen`) habe ich doch schon genau geschrieben, was Du ändern solltest. `Fahrzeugliste` (eigentlich `eingabezeilen`, weil das noch keine Fahrzeugliste ist, die willst Du ja erst erzeugen) ist schon ein Iterator. Also ist weder `content` noch `zahlen` (ein bescheuerter Name für Eingabezeilen von Marke und Farbe) nötig. Einfach weglassen.
`f` ist ein kryptischer Name. In Wirklichkeit ist das ja das aktuelle Ende der Verketteten Liste (oder ist es der Anfang?) Dann nenn das auch so. fNeu sollte auch `neues_fahrzeug` heißen, damit der Leser gleich sieht, was denn das ist. In einem n. T. schr. Du doch auch nicht m. lauter Abk.

Dann zur eigentlichen Aufgabe: Sortieren mit Bubblesort: Beschreib doch mal in Worten, wie der Bubblesort-Algorithmus funktioniert.

PS: das hat jetzt nichts mehr mit Deinem Problem zu tun, aber um nochmal deutlich zu machen, was gute Namensgebung bedeutet, am Beispiel der Funktion `sortierung`.
1. Funktionen sollten Tätigkeiten ausdrücken. Was macht die Funktion? `sortieren`.
2. Was sortiert die Funktion: `elemente`. Dass das Fahrzeuge sind, spielt hier ja gar keine Rolle, außer dass die Funktion erwartet, dass die Elemente eine Ordnung haben (was deine jetzige Fahrzeugklasse nicht hat).
3. Was prüft die `pruefvar`? Ob alle Elemente schon in sortierter Reihenfolge vorliegen. Also `ist_alles_sortiert`.
4. Hier merkt man, dass man die while-Schleife (die übrigens keine Klammern für die Bedingung braucht) erst starten kann, wenn man der Prüfvariable einen Wert gibt. Das ist schlecht. Denn die Sortierung muß immer einmal durchlaufen werden. Also eine while-True-Schleife mit End-Abbruchbedingung.
5. `Anzahl` wird nicht wirklich verwendet, weil falsch eingerückt. Es ist auch nicht klar, welche Anzahl denn damit gemeint ist. Also anzahl_der_bereits_sortierten_elemente. Auch hier wäre das Umdrehen der Bedeutung `anzahl_zu_sortierender_elemente` besser, lass ich aber der Einfachheit mal ganz weg.

Code: Alles auswählen

def sortieren(elemente):
    while True:
        ist_alles_sortiert = True
        # Benachbarte Elemente werden überprüft und sollen nun ausgetaucht werden
        for i in range(len(elemente) - 1):
            if elemente[i] > elemente[i+1]:
                # Elemente werden ausgetausch
                elemente[i], elemente[i+1] = elemente[i+1], elemente[i]
                ist_alles_sortiert = False
        if ist_alles_sortiert:
            break
Und schon ist der Code viel lesbarer.
Benutzeravatar
__blackjack__
User
Beiträge: 13110
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@flori65817: Du solltest Schritt für Schritt vorgehen. Solange das laden aus der Datei nicht klappt, brauchst Du die Funktion zum Sortieren ja gar nicht erst anfangen, denn dann hast Du ja noch gar nichts zum Sortieren. Streng genommen kann man zum Testen vom Sortieren natürlich auch Daten per Code zusammenbasteln, aber dann braucht man die Funktion zum Laden nicht vorher schreiben. Der Punkt ist, wenn Du beide Funktionen geschrieben hast und beide so gar nicht funktionieren, hast Du etwas bei der Entwicklung falsch gemacht. Man schreibt nicht mehrere Funktionen von denen man weiss das sie nicht funktionieren, sondern fängt die nächste immer erst an wenn die davor auch wirklich funktioniert.

Was Du generell auch benötigst, sowohl für das Programm als auch für die Entwicklung, wäre eine Funktion die eine verkettete Autoliste ausgibt. Um das Ergebnis auszugeben, und auch um Zwischenschritte zu überprüfen. Also beispielsweise um die Daten nach dem Laden mal auszugeben, um zu testen ob das laden in eine verkettete Liste überhaupt korrekt funktioniert hat.

Und dann sind Namen wichtig. Das ist nichts was man nachträglich vielleicht mal überdenkt, nein, gute, passende, und vor allem korrekte Namen sind schon während der Entwicklung wichtig. Namen sind keine Kosmetik. Wenn man nämlich Probleme hat für etwas einen passenden Namen zu finden, dann deutet das in der Regel auf Probleme hin. Zum Beispiel das man Werte zu einem Objekt zusammenfasst die gar nicht zusammengehören, oder das man das Problem noch nicht richtig verstanden hat, oder die Lösung nicht richtig verstanden hat. Namen wie `f` und `fNeu` sind keine guten Namen. Und `zahlen` ist *richtig* schlecht, weil so richtig falsch, denn der Iterator liefert gar keine Zahlen.

`pruefvar` sagt nichts darüber aus was mit dieser Variable geprüft wird.

Es sind überflüssige Kommentare im Code. Faustregel: Kommentare beschreiben nicht *was* der Code macht, denn das steht dort ja bereits als Code, sondern warum der das so macht. Sofern das nicht offensichtlich ist. Offensichtlich ist in der Regel auch alles was in der Dokumentation von Programmiersprache und verwendeten Bibliotheken steht, denn das muss man im eigenen Programm ja nicht noch mal (ab)schreiben.

Kommentare vor einer Funktion oder Methode die beschreiben was die Funktion/Methode macht, gehören da nicht hin sondern als Docstring zu der Funktion/Methode. Natürlich nur wenn sie nicht trivial und offensichtlich und damit überflüssig sind.

Weder `Dateneinlesen()` noch `sortierung()` gehören in die Klasse, denn das sind keine Operationen auf einem einzelnen `Fahrzeug`. Beide verwendet das Objekt auf dem sie aufgerufen wurden ja auch gar nicht. `Dateneinlesen()` bekommt das noch nicht einmal als Argument und `sortierung()` verwendet das `self`-Argument nicht.

`Dateneinlesen()` hält sich von der Schreibweise nicht mal an die unpythonische camelCase-Schreibweise. Das wäre dann `datenEinlesen()`. Daten ist ziemlich allgemein, da werden Fahrzeuge gelesen. Das kann man ruhig im Namen erwähnen, denn dann enthält der mehr Information für den Leser.

Funktions und Methodennamen beschreiben üblicherweise die Tätigkeit die sie durchführen. `sortierung()` ist keine Tätigkeit, das wäre `sortieren()`.

Richtig wäre es die Hinweise umzusetzen die hier gegeben wurden und erst einmal den ersten grösseren Schritt zu implementieren: Das laden der Fahrzeuge aus der Datei. Dazu wäre es nützlich die auch ausgeben zu können um das laden zu überprüfen, also brauchst Du vorher/gleichzeitig eine Funktion, welche eine gegebene Fahrzeugliste ausgibt.

Wenn ich das implementieren müsste, ohne die Einschränkungen einer Hausaufgabe, würde ich die externen Module `attr` und `prettyprinter` verwenden um zumindest bei der Entwicklung eine gute, eindeutige Ausgabe der verketteten Liste zu bekommen ohne die selber programmieren zu müssen. Teilausschnitt einer solchen Lösung:

Code: Alles auswählen

#!/usr/bin/env python3
from attr import attrib, attrs
from prettyprinter import cpprint, install_extras

install_extras(["attrs"])


@attrs
class Fahrzeug:
    marke = attrib()
    farbe = attrib()
    vorgaenger = attrib(default=None)
    nachfolger = attrib(default=None)

    def hat_vorgaenger(self):
        return bool(self.vorgaenger)

    def hat_nachfolger(self):
        return bool(self.nachfolger)

    def anhaengen(self, fahrzeug):
        fahrzeug.vorgaenger = self
        self.nachfolger = fahrzeug

    ...


def lade_fahrzeuge(dateiname):
    ...


...


def main():
    print("Lade Fahrzeuge...")
    fahrzeuge = lade_fahrzeuge("test.txt")
    cpprint(fahrzeuge)
    ...


if __name__ == "__main__":
    main()
Du müsstest hier das `cpprint()` durch eine eigene Funktion zur Ausgabe der Fahrzeuge ersetzen. Und beim Laden der Fahrzeuge aus der Datei solltest Du auch eine Datei berücksichtigen die keine Daten enthält, also überlegen was `lade_fahrzeuge()` in dem Fall machen soll. Zwei sinnvolle Alternativen wären: a) Ausnahme auslösen oder b) `None` zurück geben. Und falls man `None` zurück gibt, sollte auch der restliche Code von der Annahme ausgehen, dass eine leere (verkettete) Autoliste durch diesen Wert repräsentiert wird.

Wenn man `lade_fahrzeuge()` implementiert, dann bekomme ich für die Beispieldaten diese Ausgabe:

Code: Alles auswählen

Lade Fahrzeuge...
Fahrzeug(
    marke='BMW',
    farbe='rot',
    nachfolger=Fahrzeug(
        marke='VW',
        farbe='blau',
        vorgaenger=<Recursion on Fahrzeug with id=140331913104408>,
        nachfolger=Fahrzeug(
            marke='Toyota',
            farbe='gruen',
            vorgaenger=<Recursion on Fahrzeug with id=140331913007288>,
            nachfolger=Fahrzeug(
                marke='Honda',
                farbe='tuerkis',
                vorgaenger=<Recursion on Fahrzeug with id=140331913010816>,
                nachfolger=Fahrzeug(
                    marke='VW',
                    farbe='schwarz',
                    vorgaenger=<Recursion on Fahrzeug with id=140331913010368>,
                    nachfolger=Fahrzeug(
                        marke='Subaru',
                        farbe='braun',
                        vorgaenger=<Recursion on Fahrzeug with id=140331913009304>,
                        nachfolger=Fahrzeug(
                            marke='BMW',
                            farbe='blau',
                            vorgaenger=<Recursion on Fahrzeug with id=140331913007848>
                        )
                    )
                )
            )
        )
    )
)
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
flori65817
User
Beiträge: 9
Registriert: Mittwoch 27. Mai 2020, 11:41

Also Danke für eure Antworten aber damit komme ich nicht so richtig weiter vlt bin ich auch zu Dumm und _blackjack_ du hast den Code jetzt wahrscheinlich so fachmännisch verändert das ich garnichts mehr verstehe , ich darf auch an der Klasse Fahrzeug nichts ändern außer in diese Klasse die Sortierung mit einzubauen aber ich hake immer noch beim einlesen und erstellen von objekten an..... trotz der vielen hilfestellungen...
Benutzeravatar
__blackjack__
User
Beiträge: 13110
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@flori65817: Wie gesagt *in* die Klasse baust Du keine Sortierung ein, weil die dort nicht rein gehört. Zum Sortieren schreibst Du einfach eine Funktion ausserhalb der Klasse.

So viel Code habe ich da ja gar nicht stehen, also auch nicht so viel verändert. An der Klasse habe ich faktisch eigentlich nur die Namen verändert damit sie den Konventionen entsprechen und bei `cur` → `fahrzeug` damit das verständlicher ist. Zur `hat_vorgaenger()` habe ich vereinfacht und analog eine `hat_nachfolger()` hinzugefügt. Semantisch ändert sich dadurch ja nichts gegenüber der vorgegebenen `Fahrzeug`-Klasse, da gibt es also auch nicht viel zu verstehen.

Dann habe ich eine Hauptfunktion hinzugefügt die den wirklich einfachen Code für den ersten Schritt zeigt: einlesen und ausgeben der Daten in der Datei. Für das Ausgeben habe ich `prettyprinter.cpprint()` verwendet, weil das im Zusammenspiel mit einer mit `attr` erstellten Klasse sehr schon die Objektstruktur zeigt, und das ohne das man selbst viel dafür programmieren muss. Das ist beim Entwickeln halt sehr nützlich das man sich das nicht vorstellen muss oder selbst etwas zur Anzeige davon programmieren muss. An der Stelle von `cpprint()` müsstest Du Dir halt selbst eine Funktion schreiben, die eine Fahrzeugliste ausgibt. Das hatte ich ja bereits geschrieben. Die Ausgabe muss ja auch nicht die Objektstruktur sichtbar machen, es reicht auch einfach die Daten von einem Auto pro Zeile auszugeben. Die Funktion könntest Du `zeige_fahrzeuge()` nennen. Und damit solltest Du vielleicht auch anfangen mit so einer Funktion.

Also im ersten Schritt sähe das Hauptprogramm dann so aus:

Code: Alles auswählen

def main():
    aston_martin = Fahrzeug("Aston Martin", "silber")
    bentley = Fahrzeug("Bentley", "schwarz")
    vauxhall = Fahrzeug("Vauxhall", "blau")
    
    ...
    fahrzeuge = ...
    
    zeige_fahrzeuge(fahrzeuge)
Bei den Auslassungspunkten fehlt Code der eine kleine verkettete Liste mit Fahrzeugen erstellt. Da kann man vielleicht sogar eine Hilfsfunktion schreiben die ein „iterable“ aus `Fahrzeug`-Objekten verkettet, denn die kann man bei `lade_fahrzeuge()` wiederverwenden.

Wenn ich da Code einsetze der drei `Fahrzeug`-Objekte verkettet, sieht die Ausgabe so aus:

Code: Alles auswählen

Aston Martin (silber)
Bentley (schwarz)
Vauxhall (blau)
Fang doch damit einfach mal an. Code der in der Hauptfunktion drei `Fahrzeug`-Objekte erstellt, die verkettet, und dann eine Funktion `zeige_fahrzeuge()` mit der verketteten Liste aufruft, die für jedes Auto Marke und Farbe in einer Zeile ausgibt. Bevor das nicht läuft, braucht man weder mit dem Laden anfangen, geschweige denn sich am Sortieren versuchen.

Nächster Schritt wäre dann den Code zum verketten der drei `Fahrzeug`-Objekte in eine Funktion auszulagern und allgemeiner zu machen, so dass er für eine beliebige Anzahl von `Fahrzeug`-Objekten funktioniert (inklusive 0 Objekte). So dass die Hauptfunktion so aussieht, bei gleichbleibender Ausgabe:

Code: Alles auswählen

def main():
    fahrzeuge = verkette_fahrzeuge(
        [
            Fahrzeug("Aston Martin", "silber"),
            Fahrzeug("Bentley", "schwarz"),
            Fahrzeug("Vauxhall", "blau"),
        ]
    )
    zeige_fahrzeuge(fahrzeuge)
Dabei darauf achten das `verkette_fahrzeuge()` nicht nur mit Listen funktioniert, sondern jedes iterierbare Objekt verwenden kann. Also keine Indexzugriffe machen!

Wenn das funktioniert, dann kann man eine `lade_fahrzeuge()` schreiben die entweder auf `verkette_fahrzeuge()` basiert, oder diese Funktion benutzt, so dass der nächste Evolutionsschritt in der Hauptfunktion so aussieht:

Code: Alles auswählen

def main():
    fahrzeuge = lade_fahrzeuge("test.txt")
    zeige_fahrzeuge(fahrzeuge)
Wenn Du soweit bist hast Du die Hälfte schon fertig. Dann fehlt nur noch die Sortierfunktion.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
flori65817
User
Beiträge: 9
Registriert: Mittwoch 27. Mai 2020, 11:41

Danke ich versuche es nochmal , auch wenn ich noch nicht so den durchblick habe , ich melde mich dann einfach nochmal
flori65817
User
Beiträge: 9
Registriert: Mittwoch 27. Mai 2020, 11:41

ich muss mich zurück melden also ich versteh eure Gedankengänge aber ich kann es immer noch nicht umsetzten ,ich will hier niemanden zwingend irgendwelche Aufgaben zu lösen und ihr habt auch schon versucht viel zu erklären aber ich würde mich freuen wenn ihr mal eine Lösung nach den Vorgaben schreibt , es muss um Gotteswillen nicht das komplette Programm sein nur die Daten laden Objekte erzeugen und eine verkettete Liste soll entstehen .Vlt verstehe ich dann den Ablauf, ihr müsst das natürlich nicht und ich bin keiner der nur seine Aufgaben gemacht haben will! Ich möchte es verstehen und wenn ich einen Kompletten Code und die Aufgabenstellung dazu lese verstehe ich den Sinn besser .

Ich bedanke mich im Voraus für eine Lösung mit Erklärung :D
Benutzeravatar
__blackjack__
User
Beiträge: 13110
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@flori65817: Was ist denn am ersten Teilschritt „Verkettete Liste mit drei Autos erstellen und eine Funktion zur Ausgabe der Liste“ konkret das Problem? Wo genau kommst Du bei folgendem ”Lückentext” nicht weiter und warum? Was hast Du versucht? Was passiert beim Ablauf? Und an welcher Stelle verhält sich das dann nicht mehr so wie von Dir erwartet?

Code: Alles auswählen

#!/usr/bin/env python3

...


def zeige_fahrzeuge(fahrzeuge):
    ...


def main():
    zeige_fahrzeuge(None)  # Sollte nichts ausgeben.

    aston_martin = Fahrzeug("Aston Martin", "silber")
    print("----")
    zeige_fahrzeuge(aston_martin)  # Sollte "Aston Martin (silber)" ausgeben.

    bentley = Fahrzeug("Bentley", "schwarz")
    vauxhall = Fahrzeug("Vauxhall", "blau")
    ...
    fahrzeuge = ...
    print("----")
    zeige_fahrzeuge(fahrzeuge)  # Sollte alle drei Fahrzeuge+Farbe auf jeweils einer Zeile ausgeben.


if __name__ == "__main__":
    main()
`Fahrzeug` ist hier die Klasse die vorgegeben ist.

Bei Datenstrukturen wie verketteten Listen macht es irgendwann auch Sinn sich das mal aufzumalen um sie besser zu verstehen. Für mich ist das bis hier hin noch nicht nötig, aber für das vertauschen von zwei benachbarten Fahrzeugen beim Bubblesort hatte ich mir eine Zeichnung gemacht. Für Anfänger kann das für das traversieren der verketten Liste vielleicht schon hilfreich sein, sich eine Zeichnung zu machen.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Benutzeravatar
__blackjack__
User
Beiträge: 13110
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Das ganze mal in der Programmiersprache Vala gelöst:

Code: Alles auswählen

public class Vehicle {
    public string make { get; private set; }
    public string colour { get; private set; }
    public weak Vehicle? previous { get; private set; }
    public Vehicle? next { get; private set; }

    public bool has_previous { get { return this.previous != null; } }
    public bool has_next { get { return this.next != null; } }
    public bool is_first { get { return this.previous == null; } }
        
    public Vehicle (string make, string colour)
    {
        this.make = make;
        this.colour = colour;
    }

    public VehicleIterator iterator () { return new VehicleIterator (this); }
    
    public class VehicleIterator {
        private Vehicle? current_vehicle;
        
        public VehicleIterator (Vehicle vehicle)
            requires (vehicle.is_first)
        {
            this.current_vehicle = vehicle;
        }
        
        public Vehicle? next_value () {
            var result = this.current_vehicle;
            if (this.current_vehicle != null) {
                this.current_vehicle = result.next;
            }
            return result;
        }
    }

    public void append (Vehicle vehicle)
        requires (!vehicle.has_previous)
        requires (!this.has_next)
        ensures (vehicle.previous == this)
        ensures (this.next == vehicle)
    {
        vehicle.previous = this;
        this.next = vehicle;
    }
    
    public void swap_with_next ()
        requires (this.has_next)
    {
        if (this.has_previous) {
            this.previous.next = this.next;
        }
        if (this.next.has_next) {
            this.next.next.previous = this;
        }
        var next_but_one = this.next.next;
        this.next.previous = this.previous;
        this.next.next = this;
        this.previous = this.next;
        this.next = next_but_one;
    }
    
    public string to_string () { return @"$make ($colour)"; }
    
    public static Vehicle? read (FileStream stream) {
        Vehicle? vehicle = null;
        var make = stream.read_line ();
        if (make != null) {
            var colour = stream.read_line ();
            if (colour != null) {
                vehicle = new Vehicle (make.strip (), colour.strip ());
            }
        }
        return vehicle;
    }
}


public int compare_vehicles (Vehicle a, Vehicle b) {
    var result = strcmp(a.make, b.make);
    if (result == 0) result = strcmp(a.colour, b.colour);
    return result;
}


public bool vehicles_are_sorted (Vehicle? vehicles) {
    if (vehicles != null) {
        foreach (var vehicle in vehicles) {
            if (
                vehicle.has_next && compare_vehicles(vehicle, vehicle.next) > 0
            ) {
                return false;
            }
        }
    }
    return true;
}


public static void print_vehicles (Vehicle? vehicles) {
    if (vehicles != null) {
        foreach (var vehicle in vehicles) print ("%s\n", vehicle.to_string ());
    }
}


public static Vehicle? load_vehicles (string filename)
    requires (filename.length != 0)
{
    var stream = FileStream.open (filename, "r");
    assert_nonnull (stream);
    var first_vehicle = Vehicle.read (stream);
    if (first_vehicle != null) {
        var vehicle = first_vehicle;
        Vehicle? next_vehicle = null;
        while ((next_vehicle = Vehicle.read (stream)) != null) {
            vehicle.append (next_vehicle);
            vehicle = next_vehicle;
        }
    }
    return first_vehicle;
}


public static Vehicle? sort_vehicles (Vehicle? vehicles)
    ensures (vehicles_are_sorted (result))
{
    var first_vehicle = vehicles;
    if (first_vehicle != null) {
        var done = false;
        while (!done) {
            done = true;
            var vehicle = first_vehicle;
            while (vehicle.has_next) {
                if (compare_vehicles (vehicle, vehicle.next) > 0) {
                    if (vehicle.is_first) first_vehicle = vehicle.next;
                    vehicle.swap_with_next ();
                    done = false;
                } else {
                    vehicle = vehicle.next;
                }
            }
        }
    }
    return first_vehicle;
}


public static void main () {
    var vehicles = load_vehicles ("test.txt");
    if (vehicles != null) {
        print_vehicles (vehicles);
        print ("----\n");
        vehicles = sort_vehicles (vehicles);
        print_vehicles (vehicles);
    } else {
        print ("Die Datei enthielt keine Fahrzeuge.");
    }
}
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Antworten