Algorytmy.
Trivial:
Czy jest na forum ktoś dobry z algorytmiki? Mam problemy z takim oto zadaniem:
Rozważmy sortowanie n liczb z tablicy A następującą metodą. Znajdujemy najmniejszy element
tablicy A i wstawiamy na pierwsze miejsce w pewnej tablicy B. Następnie znajdujemy drugi
najmniejszy element z A i wstawiamy na drugie miejsce w B. W ten sposób postępujemy dla
wszystkich n elementów tablicy A. Napisz dla tego algorytmu − który jest znany jako
sortowanie przez selekcję − program. Podaj pesymistyczny i optymistyczny czas działania
tego algorytmu, używając notacji Θ.
Głównie chodzi mi o to, jak wyszukać drugi najmniejszy element w tablicy A.
Wszelka pomoc mile widziana.
8 kwi 13:59
...: po wyszukaniu pierwszej liczby komórkę, gdzie ona się znajdowała zamieniasz na NULL i
wyszukujesz kolejny raz
8 kwi 14:07
Trivial:
Ze zmianą to wiem. A bez zmiany wartości?
8 kwi 14:14
b.: jesli liczby sa rozne, to mozna po prostu szukac najmniejszego elementu w A, ktory bedzie
wiekszy od ostatniego elementu w B
a w ogolnym przypadku trzeba troche na okolo, eleganckiego wariantu powyzszej metody nie mam.
Mozna np. szukac najpierw w A elementow rownych ostatniemu elementowi w B (i je dopisywac do
B).
Mozna tez juz przy okazji szukania najmniejszego elementu w A, ktory bedzie wiekszy od B
zliczac powtorzenia, ale to pewnie na jedno wyjdzie.
W kazdym razie, czas dzialania pogarsza sie co najwyzej 2 krotnie...
8 kwi 14:23
Trivial:
Ciekawy pomysł. A czy w ogólnym przypadku nie wystarczy dać warunku słabej nierówności?
8 kwi 14:29
b.: i tak bedziesz mial klopot z liczbami pojawiajacymi sie wielokrotnie (mozna oczywiscie dac
slaba nierownosc i zliczac, ile bylo rownosci −− sposob 2)
8 kwi 14:37
Trivial:
SELECTION−SORT(A)
1. utwórz tablicę B[n]
2. iMin ← 1
3. for i ← 1 to n
4. do if A[i] ≤ A[iMin]
5. then iMin ← i
6. B[1] ← A[iMin]
7. for j ← 1 to n−1
8. do for i ← 1 to n
9. do if A[i] ≤ A[iMin] and A[i] ≥ B[j]
10. then B[j+1] ← A[iMin]
Co myślisz o takim algorytmie?
8 kwi 14:46
Trivial:
SELECTION−SORT(A)
1. utwórz tablicę B[n]
2. iMin ← 1
3. for i ← 1 to n
4. do if A[i] ≤ A[iMin]
5. then iMin ← i
6. B[1] ← A[iMin]
7. for j ← 1 to n−1
8. do for i ← 1 to n
9. do if A[i] ≤ A[iMin] and A[i] ≥ B[j]
10. then iMin ← i
11. B[j+1] ← A[iMin]
Sorry tak miało być.
8 kwi 14:49
b.: musisz uaktualniac iMin w petli. Napisz, jak to zamierzasz zrobic, wtedy sie wypowiem
8 kwi 14:51
b.: aha, juz patrze
8 kwi 14:51
Trivial:
SELECTION−SORT(A)
1. utwórz tablicę B[n]
2. iMin ← 1
3. for i ← 1 to n
4. do if A[i] ≤ A[iMin]
5. then iMin ← i
6. B[1] ← A[iMin]
7. for j ← 1 to n−1
8. do iMin ← j+1
9. for i ← 1 to n
10. do if A[i] ≤ A[iMin] and A[i] ≥ B[j]
11. then iMin ← i
12. B[j+1] ← A[iMin]
Kolejne błędy...
8 kwi 14:52
b.: dla A=[1,2,3]
dostaniemy
B=[1,1,1]
8 kwi 14:56
Trivial:
Chyba linijka ósma jest zupełnie niepotrzebna, no i trzeba zmienić w linijce dziesiątej:
A[i] > B[j]...
No nie wiem. W takim razie załóżmy, że są to tablice różnowartościowe.
8 kwi 15:03
Trivial: w linijce 8 powinno być iMin ← 1.
8 kwi 15:04
Trivial:
Złożoność oczywiście Θ(n2)?
8 kwi 15:06
b.: tak, zlozonosc rzedu n2
w linijce 8 powinno być iMin ← 1, zgadza sie,
no i jak zamiesz druga nierownosc w 10. na ostra, to bedzie dzialalo dla roznowartosciowych
8 kwi 15:08
Trivial:
OK. W takim razie dziękuję za pomoc.
8 kwi 15:09
b.: wersje dla dowolnych mozna dostac np. dodajac takie wiersze:
6.5. lastiMin ←iMin
11.5. lastiMin ←iMin
oraz modyfikujac 10:
10. do if A[i] ≤ A[iMin] and (A[i] > B[j] or (A[i]=B[j] and i>lastiMin))
8 kwi 15:14
b.: (ten wiersz 11.5 powinien byc na tym samym poziomie wciecia co wiersz 12.)
8 kwi 15:15
Trivial:
w takim razie chyba trzeba zmienić na silną nierówność.
10. do if A[i] < A[iMin] and ...
8 kwi 15:22
Trivial: Mimo wszystko ten algorytm nie będzie zbyt wydajny.
8 kwi 15:23
b.: nie, tej pierwszej nierownosci nie zmieniamy, bo szukamy najmniejszego elementu w slabym sensie
(moze byc kilka najmniejszych elementow), ale ograniczamy poszukiwania
do elementow wiekszych od B[j], albo rownych B[j], ale o indeksie i wiekszym od ostatniego iMin
8 kwi 15:25
Trivial:
tak samo w linijce 4.: if A[i] < A[iMin]
Mam rację, czy nie ma to znaczenia?
8 kwi 15:25
Trivial:
Ale mając tablicę A = (2, 2, 1)
najpierw wyszukamy iMin = 3, czyli B = (1, .., ..)
potem wyszukamy iMin = 2, czyli B = (1, 2, ..)
a potem wyszukamy iMin = 2 no i mamy kłopot.
8 kwi 15:28
b.: nie bedzie zbyt wydajny jesli chodzi o liczbe porownan w jednym okrazeniu petli, to prawda
ale to tylko kwestia stalego czynnika, gorsza sprawa jest zlozonosc rzedu n
2 
(na co nic
sie tu nie poradzi)
za to jest dobry jesli chodzi o liczbe podstawien elementow tablicy (tylko n) − wiec mialby
zastosowanie, gdyby elementami tablicy byly duze struktury (drogie kopiowanie), ale
sortowalibysmy tylko po jednym elemencie tej struktury (tanie porownywanie)
8 kwi 15:28
b.: masz racje!
powinna byc ostra nierownosc, tak jak pisales o 15:25
8 kwi 15:29
b.: (na co nic sie tu nie poradzi) −> w sensie, w tym algorytmie typu 'selection sort', bo sa inne
o mniejszej asymptotycznej zlozonosci
8 kwi 15:30
Trivial:
Jeszcze mam takie pytanie. Czy znajomość tego typu rzeczy przydaje się "w praktyce" w
programowaniu?
8 kwi 15:33
b.: znajomosc konkretnych algorytmow sortowania nie jakos bardzo, bo w wielu nowych jezykach jest
efektywna metoda sortowania dostarczana przez biblioteke i nie trzeba sie o to martwic (no
chyba ze sortowanie jest naprawde kluczowe dla programu, to wtedy moze byc potrzeba napisania
samemu/znalezienia bardziej odpowiedniego algorytmu do danej sytuacji; nie zawsze ten z lepsza
zlozonoscia asymptotyczna bedzie lepszy w praktyce).
Szczegolnie w jezykach wysokiego poziomu, typu js, python, nie warto pisac samemu czegos, co
jest dostarczane standardowo.
Ale mysle, ze napisanie sobie samemu takiej funkcji raz w zyciu jest rozwijajace − zobacz ile
bledow tu zrobilismy
8 kwi 15:41
Trivial:
OK. Jeszcze raz dzięki za pomoc... Sam pewnie bym tego tak szybko nie wymyślił.

Zaraz jeszcze zaimplementuję i sprawdzę, czy algorytm rzeczywiście działa.
8 kwi 15:43
Trivial:
Działa.

/* sort.c */
#include <stdio.h>
#define ROZMIAR 10
void sSort(const int*, int*);
void show(const int*);
int main(void) {
int tab[ROZMIAR] = {1, 2, 3, 3, 2, 1, −1};
int tab2[ROZMIAR];
sSort(tab, tab2);
puts("Tablica przed sortowaniem to:");
show(tab);
puts("A po sortowaniu to:");
show(tab2);
getchar();
return 0;
}
void sSort(const int A[], int B[]) {
int lastiMin, i, j;
int iMin = 0;
for (i=0; i<ROZMIAR; i++)
if (A[i] < A[iMin])
iMin = i;
B[0] = A[iMin];
lastiMin = iMin;
for (j=0; j<ROZMIAR−1; j++) {
iMin = 1;
for (i=0; i<ROZMIAR; i++)
if ( A[i] < A[iMin] &&
(A[i]>B[j] || (A[i] == B[j] && i > lastiMin)) )
iMin = i;
B[j+1] = A[iMin];
lastiMin = iMin;
}
}
void show(const int A[]) {
int i;
for (i=0; i<ROZMIAR; i++)
printf("%d ", A[i]);
putchar('\n');
}
8 kwi 16:03
Trivial: A jednak nie działa.
8 kwi 16:04
Trivial:
W tablicy wynikowej trójek brak.
8 kwi 16:07
8 kwi 16:29