#include<iostream>
using namespace std;

//struct ListenElement
//{
//	int wert; // unser eigentlicher Datentyp
//	ListenElement *next; // Zeiger auf das nächste ListenElement
//	// Zeiger werden mit einem vorangestellten * markiert
//};

struct ListenElement; // dies kündigt dem Compiler an,
// dass es ein struct ListenElement geben wird
// die genaue Definition des structs kommt später

// damit ist jetzt folgendes typedef möglich
typedef ListenElement* ListenPtr;
// definiert uns ListenPtr als Typ eines Zeigers auf ein ListenElement

struct ListenElement
{
	int wert;
	ListenPtr next;
};


// letzte Woche ... (Termin 31.1.2012)
// ListenElement* zahlEinlesenMitListen(void)
//{
//	// liest Zahlen ein und gibt den Zeiger auf das erste Element zurück
//	// (Zahlen sind in der Liste in umgekehrter Reihenfolge der Eingabe)
//  ...
//  return anker;
//}

void ListeMitZahlenAusgeben(ListenElement *anker)
{
	// Idee: solange Elemente da sind, diese ausgeben, ansonsten jeweils auf das nächste Element
	// in der Liste vorrücken

	//ListenElement *aktElem = anker;
	ListenPtr aktElem = anker;
	while (aktElem != NULL)
	{
		cout << "Naechste Element ist die " << aktElem->wert << endl;
		// nun noch auf das nächste Element vorrücken
		aktElem = aktElem->next;
	}
	// alternative: rekursive Lösung
	// if (aktElem != NULL)
	// {
	//   cout << "Nächste Element ist die " << aktElem->wert << endl;
	// }
	// else
	// {
	//   ListeMitZahlenAusgeben(aktElement->next);
	// }
	// da aktElement nie was zugewiesen wird, könnte man bei der rekursiven Variante
	// auch die Variable anker direkt verwenden
}

void fuegeZahlAmAnfangDerListeEin(const int zahl, ListenPtr & anker)
// selbst ausprobieren, ob es ohne das typedef ListenElement* ListenPtr
// dann ListenElement * & anker oder ListenElement & * anker heißen müsste
{
	// fügt zahl als neues erstes Element der Liste ein, auf die anker zeigt
	// anker wird entsprechend verändert
	//
	// Idee: erzeuge neues ListenElement und füge dies als neues Element
	// mit der als Parameter übergebenen Zahl am Anfang der Liste, auf
	// die anker zeigt, ein
    ListenPtr neu = new ListenElement;
	neu->wert = zahl;
	neu->next = anker;
	anker = neu;
}

void fuegeZahlSortiertInDieListeEin(const int zahl, ListenPtr & anker)
// für die Fälle, dass die Liste vorher leer war oder zahl das neue kleinste
// Element ist, muss anker veränderbar sein
// Folgende Fälle sind zu untersuchen:
// - ist die Liste leer?
// - ist zahl das neue kleinste Element?
// - sonstiges
// wir gehen hier der Einfachheit halber davon aus, dass alle Element verschieden sind
// selbst überlegen, wie man das Einfügen gleicher Elemente verhindert
{
	if (anker == NULL)
	{
		// neues erstes Element erzeugen, Variable anker kann direkt verändert werden
		anker = new ListenElement; // erzeuge neues ListenElement
		anker->wert = zahl; // zahl in das ListenElement eintragen
		anker->next = NULL; // Element ist das einzige bis dahin
	}
	else if (zahl < anker->wert) // ist zahl das neue kleinste Element
	{
		// so ähnlich wie bei anker == NULL, aber bisherige Liste nicht verloren gehen darf
		ListenPtr neu = new ListenElement;
		neu->wert = zahl;
		neu->next = anker; // analog zum Einfügen am Anfang einer Liste
		anker = neu;
	}
	else
	{   // neues Element ist nicht zu Beginn der Liste, wir dürfen anker also nicht verändern
		// wir benötigen einen Pointer zum Durchlaufen der Liste
		ListenPtr current = anker->next; // das Element bei anker ist wie oben
		// festgestellt in jedem Fall kleiner als zahl, Test kann also bei der zweiten
		// Zahl beginnen
		//
		// while (current->wert < zahl) läuft ein Element zu weit ...
		// 1. Lösungsmöglichkeit: merke mit einer weiteren Variablen die Adresse,
		// auf die current zeigt, im jeweils vorherigen Schleifendurchlauf
		ListenPtr prev = anker;
		while (current!=NULL && current->wert < zahl) // Weiterlaufen, bis zum letzten ListenElement, das kleiner als zahl ist
		// aufpassen: dies funktioniert nur, weil der Compiler für den Fall,
		// dass current == NULL ist, den Ausdruck current->wert < zahl nicht mehr auswertet
		// und so also auf current->wert nicht zugreift!
		// die 4 Zeilen für das Erzeugen und "Einfügen" des neuen Elements funktionieren
		// gleichermaßen für die Fälle, dass ein Element eingefügt oder am Ende als neues
		// größtes Element angefügt wird (selbst nochmal überlegen)
		{
			prev = current;
			current = current->next;
		}
		// cout << "prev zeigt auf die " << prev->wert << endl;
		// prev zeigt auf das Element, hinter dem die neue zahl einzufügen ist
		// current zeigt auf das Element, was hinter der neuen zahl stehen soll
		ListenPtr neu = new ListenElement; // neues Element erzeugen, um dort zahl einzufügen
		neu->wert = zahl;
		neu->next = current;
		prev->next = neu;
	}
	// es gibt noch mindestens 2 sinnvolle weitere Möglichkeiten (und zwei Dutzend kompliziertere)
	// Aufgabe: finden Sie mindestens eine weitere und implementieren Sie diese
	// Ideen dazu: ersetze current durch prev->next
	// weitere Idee: sortiertesEinfügen(zahl,anker) = neues erstes Element oder sortiertesEinfügen(zahl,anker->next)
}


int main(void)
{
	ListenPtr anker = NULL; // WICHTIG: initialieren der Liste nicht vergessen!
    int zahl;
	cout << "Gib eine Zahl ein (Abbruch mit 0): ";
	cin >> zahl;
	while (zahl != 0)
	{
		// fuegeZahlAmAnfangDerListeEin(zahl,anker);
		fuegeZahlSortiertInDieListeEin(zahl,anker);
		cout << "Gib eine Zahl ein (Abbruch mit 0): ";
		cin >> zahl;
	}
    ListeMitZahlenAusgeben(anker);

	return 0;
}