anntoinet napisała mi na PW prośbę o wyjaśnienie algorytmu. Postanowiłem jednak odpowiedzieć tu bo może się to przydać również innym.
Rospisałem trochę kod i dodałem komentarze(na forum wygląda troche nieczytelnie, lepiej wkleić w jakiś edytor z kolorowaniem składni)
void sortuj(SLista* &lista) //wskaźnik do początku listy przekazywany jest przez referencję, to znaczy, że funkcja może modyfikować zmienną wskaźnikową znajdującą się na zewnątrz niej
{
SLista* posortowana = 0; //lista posortowana jest początkowo pusta
while(lista != 0) //elementy będą przenoszone z pierwotnej listy do posortowanej, dopóki pierwotna lista nie jest pusta
{
SLista *max = lista, //przyjmujemy na początek, że największym elementem jest pierwszy
*przed_max = 0; //ponieważ lista jest jednokierunkowa to musimy zapamiętać też wskaźnik na poprzedni element
//przed pierwszym elementem nie ma innego elementu, dlatego pusty wskaźnik
for(SLista *p = lista, *i = lista->next; // (i) przeszukiwanie zaczynamy od drugiego elementu bo pierwszy już został uznany tymczasowo za największy
// (p) potrzebny jest też wskaźnik do poprzedniego elementu, przed drugim elementem znajduje się pierwszy element ;)
i != 0; //dopóki nie dojdziemy do końca listy
p = i, i = i->next) //obecny element staje się poprzednim, a następny obecnym
{
if(i->x2 >= max->x2) //jeśli obecny element jest wiekszy lub równy od poprzednio uznanego za największy
{
max = i; //to uznajemy obecny za największy
przed_max = p; //i zapamiętujemy też jego poprzednika
}
}
//usuwanie największego z pierwotnej listy
if(przed_max != 0) //jeśli jest element poprzedni względem największego
przed_max->next = max->next; //to jako następnik poprzednika ustawiamy następnik naszego największego, największy element już nie należy do pierwotnej listy
else //element nie ma poprzednika tylko jeśli jest pierwszy
lista = max->next; //więc jako początek pierwotnej listy ustawiamy drugi element; może być też 'lista = lista->next;' bo w tym przypadku max jest równe lista
//wstawienie największego elementu na początek posortowanej listy
max->next = posortowana; //następnikiem najwiekszego będzie obecny pierwszy posortowanej
posortowana = max; //a na początek posortowanej ustawimy nasz największy
}
lista = posortowana; //na koniec jako początek listy ustawiamy początek posortowanej
}
Jest to właściwie ten sam algorytm, którego opis podałaś w pierwszym poście. Ogólnie taka metoda nazywa się sortowaniem przez wybór.
Ponieważ kolejne elementy dodawane są na początek listy posortowanej to trafiają tam w odwrotnej kolejności.
W wyszukiwaniu największego elementu jest warunek “większy lub równy”, przez co wybierany jest ostatni największy, dzięki czemu elementy o tej samej wartości znajdują się w liście posortowanej w tej samej kolejności w jakiej znajdowały się w pierwotnej (sortowanie stabilne). Gdyby był użyty warunek “większy” to elementy o tej samej wartości byłyby w odwrotnej kolejności (ogólnie gdy elementy o tej samej wartości po posortowaniu mogą znajdować się w innej kolejności to sortowanie określa się jako niestabilne).
Gdyby kolejne elementy były dodawana na koniec listy posortowanej to należałoby wyszukiwać najmniejszy element aby lista była sortowana rosnąco.