Sortowanie stogowe
Benny: Nie wiem czemu, ale nie działa mi sortowanie stogowe.
void Przesiewanie(int l, int p, int A[100])
{
int x,i,j;
x=A[l];
i=l;
j=(2*i)+1;
while(j<=p)
{
if(j<p && A[j]<A[j+1])
j++;
if(x<A[j])
{
A[i]=A[j];
i=j;
j=(2*i)+1;
}
}
A[i]=x;
}
void BudujStog(int n, int A[100])
{
for(int i=(n−2)/2;i>=0;i−−)
Przesiewanie(i,n−1,A);
}
void SortowanieStogowe(int n, int A[100])
{
BudujStog(n,A);
int x;
for(int i=n−1;i>=1;i−−)
{
x=A[0];
A[0]=A[i];
A[i]=x;
Przesiewanie(0,i−1,A);
}
}
23 paź 14:30
Mariusz:
Piszesz to na podstawie pseudokodu Cormena ?
Jeśli tak to powinien działać
Heapify(A,i)
l←2i
r←2i+1
if (l≤heapsize[A]) and (A[l]>A[i])
then largest←l
else largest←i
if(r≤heapsize[A])and (A[r]>A[largest])
then largest←r
if largest ≠i
then zamien A[i]↔A[largest]
Heapify(A,largest)
Buildheap(A)
heapsize[A]←length[A]
for i←length[A]/2 downto 1
do Heapify (A,i)
Heapsort(A)
Buildheap(A)
for i←length[A] downto 2
do zamien A[1]↔A[i]
heapsize[A]←heapsize[A]−1
Heapify(A,1)
Jak napisałem według tego pseudokodu to sortowanie działa
Przykładowy kod masz w numerical recipes in c
23 paź 14:52
Benny: Szczerze to niczego nie zrozumiałem. Miałem taki program napisany na wykładzie przez
prowadzącego, który twierdzi, że to powinno działać.
23 paź 19:40
Mariusz:
Sprawdzałeś czy nie masz gdzieś nieskończonej pętli ?
np czy warunek w pętli while kiedykolwiek będzie fałszywy ?
Prześledź zmienne przy użyciu debuggera
24 paź 01:40
Mariusz:
Do if(x<A[j]) zapomniałeś dopisać else w którym dajesz warunek kończący pętlę
24 paź 02:00
Mariusz:
Co gdyby p było największą liczbą możliwą do zapisania na 32 bitach ?
Z tego co zauważyłem to j jest indeksem więc w C jest nieujemne
Można zmodyfikować warunek pętli while z j<=p na j<=p&&j>=0
Wtedy w else z instrukcji warunkowej if(x<A[j]) można by było dać ulubioną liczbę ujemną
Zastanawiam się też nad opakowaniem instrukcji A[i]=x;
instrukcją warunkową if
24 paź 08:42
jc: Mój dawny i działający kod poniżej.
Sprawdzaj swój kod, aż znajdziesz usterkę. Albo zrób przerwę i napisz od nowa.
Sugerowałbym indeksować tablicę od 1 zamiast od zera. Tak jest łatwiej.
−−−−−−−
/* sortowanie kopcowe */
#include<stdio.h>
const int n = 10;
int x[]={0,3,2,5,7,3,2,9,1,7,8};
void wdol(int k, int n){
int m = 2*k;
int t = x[k];
while(m <= n){
if ( n > m and x[m] < x[m+1] ) m++;
if ( t >= x[m] ) break;
x[k] = x[m];
k = m;
m = 2*k;
}
x[k] = t;
}
int main(){
int t;
for(int i=1; i<=n; i++) printf(" %d ", x[i] );
printf("\n");
for(int i = n/2; i >= 1; i−−) wdol(i,n);
for(int i = n; i >= 2; i−−){
int t = x[1];
x[1] = x[i];
x[i] = t;
wdol(1,i−1);
}
for(int i=1; i<=n; i++) printf(" %d ", x[i] );
printf("\n");
}
24 paź 09:41
jc: Spojrzałem. Kiedy kończy Ci się pętla w Przesiewaniu?
Wydaje się, że dopiero, gdy dojdziesz do krawędzi. A często powinna skończyć się
wcześniej.
24 paź 09:48
Mariusz:
My na temat poprawiania pseudokodu Cormena już pisaliśmy
https://matematykaszkolna.pl/forum/319451.html
i z tego co zdążyłem zauważyć to w instrukcji warunkowej if(x<A[j])
zapomniał dać else
Ciekawe czy już nie za późno i czy Benny jeszcze odpisze
24 paź 10:00
Benny: Nigdy nie jest za późno. Z tym przesiewaniem to się właśnie zastanawiałem czy tam czegoś nie
brakuje, bo robiłem symulacje w zeszycie i się pętla nigdy nie kończyła. Czy w Dev−C++ jest
debugger?
24 paź 10:57
jc: Jest debugger− polecenie gdb. Nigdy nie używałem debuggera.
Mój kod działa, tylko trzeba zamienić and na &&.
Gdybyś kopiował, to pamiętaj, aby zamienić minusy na prawdziwe minusy.
24 paź 11:31
Benny: Jasne, ale pytam, bo może kiedyś się przydać. Gdzie to polecenie mam wklepać?
24 paź 11:35
Mariusz:
Benny twój kod też będzie się zatrzymywał w rozsądnym czasie gdy
do instrukcji if(x<A[j]) dopiszesz else
void Przesiewanie(int l, int p, int A[100])
{
int x,i,j;
x=A[l];
i=l;
j=(2*i)+1;
while(j<=p) {
if(j<p && A[j]<A[j+1]) j++;
if(x<A[j]) {
A[i]=A[j];
i=j;
j=(2*i)+1;
}
else j=p+1; //tej linijki kodu u ciebie zabrakło
}
A[i]=x;
}
void BudujStog(int n, int A[100]) {
for(int i=(n−2)/2;i>=0;i−−)
Przesiewanie(i,n−1,A);
}
void SortowanieStogowe(int n, int A[100]) {
BudujStog(n,A);
int x;
for(int i=n−1;i>=1;i−−) {
x=A[0];
A[0]=A[i];
A[i]=x;
Przesiewanie(0,i−1,A);
}
}
Oczywiście można warunek pętli while zmienić z j<=p na j<=p&&j>=0
Kod wyglądałby wtedy tak
void Przesiewanie(int l, int p, int A[100])
{
int x,i,j;
x=A[l];
i=l;
j=(2*i)+1;
while((j<=p)&&(j>=0)) {
if(j<p && A[j]<A[j+1]) j++;
if(x<A[j]) {
A[i]=A[j];
i=j;
j=(2*i)+1;
}
else j=−1; //tej linijki kodu u ciebie zabrakło
}
A[i]=x;
}
void BudujStog(int n, int A[100]) {
for(int i=(n−2)/2;i>=0;i−−)
Przesiewanie(i,n−1,A);
}
void SortowanieStogowe(int n, int A[100]) {
BudujStog(n,A);
int x;
for(int i=n−1;i>=1;i−−) {
x=A[0];
A[0]=A[i];
A[i]=x;
Przesiewanie(0,i−1,A);
}
}
Zazwyczaj skorzystaj z debuggera piszą ci którzy nie umieją bądź nie chcą pomóc
24 paź 12:21
Benny: Dzięki bardzo. Czyli po prostu dopisujemy ten warunek, żeby wyjść z pętli, tak?
24 paź 12:29
Mariusz:
Tak,
dokładniej rozbudowujemy ten warunek który już masz o to co by było
gdyby warunek się nie spełnił − wychodzimy wtedy z pętli
24 paź 12:51
jc: Benny, pytasz gdzie to polecenie mam wklepać?
Pytasz, jakbyś pierwszy raz dotykał komputera. W moim pierwszym komputerze faktycznie
nie było gdzie wpisywać poleceń, ale były poza systemem odpowiednie programy.
Skoro spytałeś o dev−c++, to pewnie używasz Windows. Polecenia możesz wpisywać
w programie cmd (choć może się coś zmieniło, Windowsa używałem epizodycznie
kilkanaście lat temu).
24 paź 12:54
Benny: Pytam, bo ja nie odpalam programu prosto z cmd tylko poprzez deva.
24 paź 12:58
jc: dev odpala cmd ... Nie musisz korzystać z pośrednika.
24 paź 13:11
jc: Szukaj, może dev ma odpowiedni przycisk.
24 paź 13:12
Mariusz:
Na pasku menu między wykonuj a narzędzia
Na dole tam gdzie informacje kompilatora (ostrzeżenia i błędy)
między logiem kompilatora a znajdź wyniki
U mnie na początku działał a teraz coś nie reaguje na próby uruchomienia
24 paź 15:07
Mariusz:
jc pisałeś kiedyś listę , przydałaby mi się do czytania małych plików
(zwłaszcza jeśli jakiś algorytm wymaga abyśmy przeczytali go wiele razy)
Jeśli chodzi o język to Pascal albo C
chociaż w C występował mi błąd segmentation fault i nie wiem jak się go pozbyć
Benny ty jak skończysz z sortowaniami to pewnie też zajmiesz się
listami , stosami , kolejkami czy grafami
Chociaż sortować można też listę czy plik lecz tam wygodniejsze jest sortowanie przez scalanie
24 paź 15:23
Mariusz:
Sortowanie listy polega na zamianie wskaźników
24 paź 15:25
Mariusz:
Na stack overflow widziałem procedurę przesiewającą napisaną zgodnie z pseudokodem
Cormena ale iteracyjnie
Instrukcji break najłatwiej się pozbyć wprowadzając zmienną logiczną i modyfikując warunek
wejścia do pętli
Na youtube widziałem całkiem ładnie napisany kod procedury przesiewającej
11 gru 05:59
Mariusz:
Tę procedurę przesiewającą można znaleźć np w książce Wirtha
W kodzie zamieszczonym u Wirtha była jeszcze instrukcja skoku
którą prowadzący usunął nie modyfikując warunku na wyjście z pętli
Tak jak napisałem wcześniej jeżeli chcemy wyeliminować instrukcję skoku
to najlepiej wprowadzić zmienną logiczną i zmodyfikować warunek dla pętli while
Wirth napisał że ta procedura przesiewająca została zaproponowana przez Floyda
27 mar 07:24
Mariusz:
Benny
"Szczerze to niczego nie zrozumiałem.
Miałem taki program napisany na wykładzie przez prowadzącego,
który twierdzi, że to powinno działać."
Gdyby prowadzący dał specjalnie nie działający (imiesłów dlatego pisownia rozłączna)
kod dla was do poprawienia to byłoby to zrozumiałe ale gdy podał ten kod jako przykład
to powinien on działać , no ale w wielu skryptach widziałem błędne przykłady
Myślę że prowadzący przepisał kod funkcji przesiewającej z książki Wirtha
usuwając instrukcję skoku i nie proponując nic w zamian
Gdybyś przeczytał kod funkcji przesiewającej linia po linii to sam doszedłbyś do tego
kiedy i dlaczego otrzymujesz nieskończoną pętlę
6 gru 06:14
Mariusz:
Zaprezentowany algorytm można uogólnić na inne wskaźnikowe struktury danych np listy
wykorzystując drzewo binarne (binarne drzewo poszukiwań)
Mamy daną listę
(dla listy jednokierunkowej jeden wskaźnik byłby wykorzystywany tylko przez drzewo)
Dopóki nie przejdziemy całej listy wstawiamy jej węzły do drzewa zachowując przy tym warunek
węzeł z mniejszym lub równym kluczem trafia do lewego poddrzewa
Przechodzimy drzewo przeszukując je wgłąb
Zapisujemy drzewo binarne w postaci listy
Tutaj jc mógłby coś więcej napisać skoro chwalił się że wykłada i że drzewka pisał
13 maj 23:20