Verkettete Liste

Erstmal danke für deine Mühe das Programm schnell zu schreiben und können wir vielleicht mein Programm auch behandeln, denn ich will wissen wie das mit meiner Möglichkeit auch gehen könnte.

Kannst du mir vielleicht auf die Sprünge helfen wie ich mein Problem umgehen kann oder vereinfachen kann(außer mit deiner methode)?
 
Soll der Code so aussehn? Mit den viele Ifs und gleichen Codebefehlen mehrfach? Und die 2. if geht er immer rein, weis aber nicht wie ich das verhindern könnte.
Na klar ich könnte eine Variable nehemn und die in der 1. if hochzählen und dann vergleichen in der 2. if ob di variable noch den anfangswert hat, wenn nicht dann nicht reingehn, ansonsten schon. Aber eine elegante Lösung ist das auch nicht.

Ich hab folgende Sonderfälle behandelt: change1=1. Element und change2=1. Element.

Aber es gibt noch 2: change1 = letztes Element und change 2= letztes Element.

Da werden es noch mehr ifs und noch mehr gleicher Befehlcode an verschiedenen Stellen.

Soll das der Sinn sein dahinter?

Wie kann ich das anders lösen? Ich kann mir nicht vorstellen das dies passen würde.

C++:
spielzug* change_pointer(spielzug* liste, spielzug* change1, spielzug* change2) //liste zeigt auf das 1. Element der Kette, temp1 zeigt auf das element in der kette das mit einen anderen Element in der kette, wo change2 draufzeigt, vertauscht werden muss
{
  spielzug* after1 = NULL;//element nach temp1
  spielzug* before1 = NULL;//element bevor temp1
	spielzug* after2 = NULL;//element nach change2
  spielzug* before2 = NULL;//element bevor change2
	spielzug* temp2 = NULL;//pointer zum zwischenspeichern von change2
	spielzug* temp1 = NULL; //pointer zum zwischenspeichern von change1
	
 
	before1 = change1->prev;
	after1 = change1->next;
	before2 = change2->prev;
	after2 = change2->next;
	temp1=change1;
	temp2=change2;
	
  if(change2->prev == NULL)
	{
    temp2->prev=before1;
		after1->prev=temp2;
		temp2->next=after1;

		temp1->prev=before2;
		temp1->next=after2;
		after2->prev=temp1;
	}

	if(change1->prev == NULL && change2->prev != NULL) // hier geht er immer rein, aber soll nicht rein gehn...
	{
    before2->next = temp1;
	  temp1->prev = before2;
	  temp1->next = after2;
	  after2->prev = temp1;

		temp2->prev=before1;
		temp2->next=after1;
		after1->prev=temp2;
	}
  
	if(change1->prev != NULL || change2 != NULL)
	{
    before2->next = temp1;
	  temp1->prev = before2;
	  temp1->next = after2;
	  after2->prev = temp1;

		
	  before1->next = temp2;
	  temp2->prev = before1;
	  temp2->next = after1;
	  after1->prev = temp2;
	}

	if(change1->prev == NULL)
	{
	  liste=temp1;
	}

	if(change2->prev == NULL)
	{
	  liste=change2;
	}

	return(liste);
}
 
Wie kann ich das anders lösen? Ich kann mir nicht vorstellen das dies passen würde.
Wie man es anders und ohne explizite Behandlung aller Sonderfälle lösen kann, habe ich dir ja schon gezeigt.

Ich glaube dein Verständnisproblem liegt darin, dass du nicht verstehst, was bei der Kopie eines Zeigers passiert. Ein Zeiger ist lediglich ein Verweis auf eine Speicherstelle, quasi eine Hausnummer. Kopierst du einen Zeiger, verweist die Kopie immer noch auf dieselbe Speicherstelle (die kopierte Hausnummer zeigt immer noch auf dasselbe Haus), und es wird kein Speicher kopiert (kein neues Haus gebaut). Als konkretes Beispiel:

C:
int* a = malloc(sizeof(int)); // Neuen Speicher reservieren
int* b = a; // a und b zeigen jetzt auf ein und denselben Speicher, keine Kopie!
*a = 42;
printf("*a=%d *b=%d\n", *a, *b); // Ergibt *a=42 *b=42
*b = 4711;
printf("*a=%d *b=%d\n", *a, *b); // Ergibt *a=4711 *b=4711

Wenn du unter diesem Aspekt deinen Code betrachtest, dann wirst du sehen, dass der recht unsinnige Sachen macht. Als Beispiel mal deine erste Sonderfallbehandlung, wobei ich die Variablen durch die rechten Seiten der Zuweisungen ersetzt habe:

C:
if(change2->prev == NULL)
{
    change2->prev = change1->prev; // 1. OK
    change1->next->prev = change2; // 2. Was ist, wenn change1->next == NULL?
    change2->next = change1->next; // 3. change2->next wird überschrieben und
                                   //    nirgends gesichert, ist also verloren!
 
    change1->prev = change2->prev; // 4. Sinnlos, da wegen 1. bereits
                                   // change1->prev == change2->prev gilt
    change1->next = change2->next; // 5. Sinnlos, da wegen 2. bereits
                                   // change1->next == change2->next gilt
    change2->next->prev = change1; // Was ist, wenn change2->next == NULL?
}

Deine Variablen sind also recht sinnlos und tragen höchstens zur Verwirrung bei.

Mein Rat: mach dir bewusst, wie Zeiger funktionieren, schreib die Funktion von Grund auf komplett neu, verwende keine Hilfsvariablen als „Abkürzung“, kommentiere jeden Codeblock (was willst du damit erreichen), formatiere den Code einheitlich (kein „Flattersatz“ am linken Rand) und dann schauen wir weiter.

Grüße,
Matthias
 
Ok, danke.

Ich hab jetzt die Fälle behandelt.

Was sagt ihr dazu könnte es so funktionieren?

C++:
spielzug* change_pointer(spielzug* liste, spielzug* change1, spielzug* change2) //liste zeigt auf das 1. Element der Kette, change1 zeigt auf das element in der kette das mit einen anderen Element in der kette, wo change2 draufzeigt, vertauscht werden muss
{
  spielzug* after1 = NULL;//element nach change1
  spielzug* before1 = NULL;//element bevor change1
	spielzug* after2 = NULL;//element nach change2
  spielzug* before2 = NULL;//element bevor change2
	spielzug* temp = NULL;//pointer zum zwischenspeichern von change2
	
	before1 = change1->prev;//sichern des elements bevor change1
	after1 = change1->next;//sichern des elements nach change1
	before2 = change2->prev;//sichern des elements bevor change2
	after2 = change2->next;//sichern des elements nach change2


	if(before1 == NULL && after2 == NULL)
	{
	  before2->next=change1;
		change1->prev=before2;
		change1->next=NULL;

		after1->prev=change2;
		change2->next=after1;
		change2->prev=NULL;
	}

	if(before2 == NULL && after1 == NULL)
	{
	  before1->next=change2;
		change2->prev=before1;
		change2->next=NULL;

		after2->prev=change1;
		change1->next=after2;
		change1->prev=NULL;
	}

	if(after1 == NULL && before2 != NULL)
	{
	  before1->next=change2;
		change2->prev=before1;
		change2->next=NULL;

		before2->next=change1;
		change1->prev=before2;
		after2->prev=change1;
		change1->next=after2;
	}

	if(after2 == NULL && before1 != NULL)
	{
	  before2->next=change1;
		change1->prev=before2;
		change1->next=NULL;

		before1->next=change2;
		change2->prev=before1;
		after1->prev=change2;
		change2->next=after1;
	}

	if(before1 == NULL && after2 != NULL)//wenn change1 = 1. Elemente --> geht er in die if, sonst nicht.
	{
		/*vertauscht die beiden elemente*/
	  before2->next=change1;
		change1->prev=before2;
		after2->prev=change1;
		change1->next=after2;

		change2->prev=NULL;
		change2->next=after1;
		after1->prev=change2;

		liste=change2;
	}
  
	if(before2 == NULL && after1 != NULL)
	{
		before1->next=change2;
		change2->prev=before1;
		after1->prev=change2;
		change2->next=after1;

		change1->prev=NULL;
		change1->next=after2;
		after2->prev=change1;

		liste=change1;
	}

	if(after1 != NULL && after2 != NULL && before1 != NULL && before2 != NULL)
	{
		/*vertauscht die beiden elemente*/
		before2->next = change1;
		change1->prev = before2;
		change1->next = after2;
		after2->prev = change1;

		before1->next = change1;
		change2->prev = before1;
		change2->next = after1;
		after1->prev = change2;
	}
	return(liste);
}
 
Aber seht euch doch meine Code an, also ich persönlich finde ihn s******, weil es ist viel zu viel Code und im Prinzip spielt sich fast immer das selber ab.

Kann mir den einer nen Tipp bitte geben wie ich das etwas einfacher machen kann?

Danke!
 
Zurück