Forum: PC-Programmierung C: verkettete Liste


von olaf (Gast)


Lesenswert?

Hallo Jungs,

hab da ne Frage, ich steh' im Moment grausam auf dem Schlauch.

Ich habe eine verkettete Liste (in C) von Elementen, die ich sortieren 
möchte. Dazu habe ich mir Bubblesort angedacht.
Die Liste ist doppelt verkettet. Um sie zu sortieren, möchte ich erst 
eine einfache Funktion bauen, die zwei Elemente vertauscht. Aber ich 
blick das grade nicht, probiere schon seit 2 Stunden herum und vermurkse 
mir immer meine Liste. WIE tausche ich zwei Elemente in einer doppelt 
verketteten C-Liste? Kann mir einer einen Tipp geben? allzu trivial 
scheint es ja nicht zu sein.

Das einzige, was ich über die Liste weiss:
ich kriege einen Pointer auf ein Element, und dieses ist mit seinem 
Nachfolgerelement, sofern existent, zu tauschen.

Bin mal gespannt - ich habe es nicht fertiggebracht.

: Verschoben durch User
von Norbert (Gast)


Lesenswert?

Wenn du zwei Elemente tauschen willst, so musst du vier Elemente 
'anfassen'/modifizieren.

1 <-> 2 <-> 3 <-> 4

Wenn du 2 und 3 tauscht, müssen in 1 und 4 die vorwärts bzw. rückwärts 
gerichteten Zeiger ebenso angepasst werden.

von skyperhh (Gast)


Lesenswert?

Wenn Du nur einen Pointer hast, der auf das nächste Element zeigt, dann 
hast Du "nur" eine Einfach verkettete Liste ... bei der mußt Du pro 
Element zwei Pointer anpassen: 1.) Den Pointer vor dem Element welches 
Du tauschen willst und den Pointer im Element...

Wenn Du eine Doppelt verkettete Liste hast, dann sind es pro tauschenden 
Element schon vier Pointer die Du anpassen mußt... zwei pro Element plus 
dem Eintrag vor dem tauschenden und Element und dem dahinter...

von Yalu X. (yalu) (Moderator)


Lesenswert?

Am besten malst du dir anhand eines Beispiels auf, wie die Verpointerung
vor und nach dem Tausch auszusehen hat. Dann siehst du sofort, welche
Pointer du wohin verbiegen musst.

Noch ein wichtiger Tipp:

Je nachdem, wie du die beiden Enden der Liste implementiert hast, ist
beim Vertauschen der ersten beiden oder der letzten beiden Elemente
evtl. eine Sonderbehandlung erforderlich.

Lass doch mal deine bisherigen Bemühungen sehen, vielleicht fehlt ja bis
zum perfekten Ergebnis gar nicht mehr so arg viel.

von olaf (Gast)


Lesenswert?

Also, ich habe folgende Situation:

Die Elemente der Liste sind doppelt verkettet - wie bereits erwähnt. Den 
Anfang der Liste habe ich. Nun möchte ich die Liste sortieren, und 
übergebe dazu einer Funktion den Start der Liste, also das 1. Element. 
Die Sortier- bzw. Tauschfunktion kennt also nur ein einziges Element, 
aber via prev und next kann sie ja auch Vorgänger und Nachfolger 
zugreifen.

Also echt, das Problem klingt sowas von trivial, ich schäme mich schon 
fast, zu fragen, weil eigentlich sollte man meinen, es sei wirklich 
einfach! aber ich kriege immer "Kurzschlüsse" in meiner Liste -_-

Dass ist 4 Elemente anfassen muss ist klar, und auch der Anfang und das 
Ende der Liste wird eine Spezialbehandlung benötigen, weil im einen Fall 
prev == NULL ist (ANfang) bzw. next == NULL (Ende der Liste).

von Norbert (Gast)


Lesenswert?

Spar dir die Sonderbehandlung und lass die Kette mit einem leeren 
Element Beginnen und Enden. Macht das Leben einfacher.

Alt:
1 --> 2 --> 3 --> 4
1 <-- 2 <-- 3 <-- 4

Neu:
1 --> 3 --> 2 --> 4
1 <-- 3 <-- 2 <-- 4


Wenn du Element E2 und E3 tauscht:
E1 zeigte vorwärts auf E2, nun auf E3
E2 zeigte vorwärts auf E3, nun auf E4
E3 zeigte vorwärts auf E4, nun auf E2
E4 zeigte rückwärts auf E3, nun auf E2
E3 zeigte rückwärts auf E2, nun auf E1
E2 zeigte rückwärts auf E1, nun auf E3

Hoffe ich habe keinen Dreher drin;-)

von D. I. (Gast)


Lesenswert?

Hast du den Bubblesort freiwillig gewählt? Für Listen gäbe es 
geeignetere Algorithmen.

von Karl H. (kbuchegg)


Lesenswert?

olaf schrieb:

> Also echt, das Problem klingt sowas von trivial, ich schäme mich schon
> fast, zu fragen, weil eigentlich sollte man meinen, es sei wirklich
> einfach! aber ich kriege immer "Kurzschlüsse" in meiner Liste -_-

Wie Yalu schon sagte.

Mal
es
dir
auf
!


Das Problem klingt trivial und wenn man den Bogen raushat ist es auch 
nicht schwer, aber auf Anhieb kriegt man es im Kopf nicht hin. Daher 
muss man sich die Situation aufmalen



    +####+     +####+      +#####+     +#####+
    #N o------>#N  o------>#N o------->#N    #
    #P   #<------o P#<--------- P#<-------- P#
    +####+     +####+      +#####+     +#####+
                  ^           ^
                  |           |
                 frst       scnd


gegeben die beiden Pointer frst und scnd, wie und in welcher Reihenfolge 
muss welcher Pointer wohin umgesetzt werden, damit diese Endisituation


                      +--------------+
           +----------|-+            |
           | +--------|------------+ |
           | |        | |          | |
    +####+ | | +####+ | |  +#####+ | | +#####+
    #N o---+ +>#N  o--+ +->#N o----+ +>#N    #
    #P   #<+ +---o P#<+ +------ P#<+ +----- P#
    +####+ | | +####+ | |  +#####+ | | +#####+
           | |    ^   | |     ^    | |
           | |    |   | |     |    | |
           | |   frst | |   scnd   | |
           | |        | |          | |
           +-|--------|-+          | |
             |        +------------|-+
             +---------------------+

entsteht?

Und man sieht hier auch schon: da bleibt kein Stein auf dem anderen. 
Alle Pointer werden angefasst. Wenn du dir nicht zuvor auf einem Papier 
klar machst, in welcher Reihenfolge du das tun musst, damit nichts 
verloren geht, dann hast du schon verloren. Denn niemand kann das beim 
ersten mal ohne Hilfsmittel im Kopf ausknobeln.

Also: nachdem das Ziel jetzt klar ist, geh von der Ausgangssituation aus 
und verändere die Pointer, wie du denkst. Radiere bestehende 
Verbdindungen aus und zeichne die neuen ein - Schritt für Schritt. Damit 
du einen Pointer irgendwohin zeigen lassen kannst, brauchst du immer 
mindestens einen anderen Pointer, der im Moment genau dort hin zeigt. 
Denn dessen Pointerwert wirst du dann für den neu zu installierenden 
Pointer einfach übernehmen.
Dein einziger Ankerpunkt sind die Pointer frst und scnd. Alle 
Veränderungen lassen sich ausgehend von diesen beiden Pointern 
beschreiben.


Und nein: Es bringt auch nichts, dir das jetzt hier vorzubeten. Du musst 
das selber machen. Denn im eigentlichen Sinne geht es hier darum, dass 
du eine für dich funktionierende Technik erlernst, mit der du 
Manipulationen an dynamischen Datenstrukturen in den Griff kriegst. Das 
kannst aber nur du dir selber beibringen, so wie du auch nur radfahren 
gelernt hast, indem du es gemacht hast. Zusehen bringt da wie dort 
nichts.

von D. I. (Gast)


Lesenswert?

Oder die low-ball Lösung (auch wenn das nicht Sinn der Übung ist):

Vertausch nicht die Listenelemente sondern den Inhalt der Listenelemente 
;)
1
temp = first->val
2
first->val = second->val
3
second->val = temp

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.