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.
Co najwyżej brązowa łopata