Sortowanie kopcowe zwracające dziwne wyniki.

0

Witam.
Mam problem z implementacją algorytmu sortowania kopcowego, mianowicie mój kod czasami zwraca posortowane częściowo (co jakiś czas w wydruku pojawiają się wartości w dziwnych miejscach, coś w stylu (1,3,4,4,146,160,5,7,10.)

#include <stdio.h>
#include <stdlib.h>

//g-rodzic|g*2+1-lewy syn|g*2+2-prawy syn
void wier( int g, int wielkosc, int tab[])
{
   int mak;
    if ((g*2+2)<=wielkosc)  //Jezeli nie jestesmy w ostatnim wezle, badz ostatni ma dwoch synow.
    {
        if(tab[g*2+1]>tab[g*2+2]) //Jezeli lewy syn jest wiekszy od prawego.
        {
            if(tab[g*2+1]>tab[g])//I Jeżeli jest wiekszy od rodzica.
            {
                mak=tab[g];
                tab[g]=tab[g*2+1];
                tab[g*2+1]=mak;
                wier(g*2+1,wielkosc,tab);//Popraw w glab lewego syna.
            }

        }
        else  if(tab[g*2+1]<tab[g*2+2]) //Jezeli prawy syn jest wiekszy od lewego.
        {
            if(tab[g*2+2]>tab[g])//I jezeli jest wiekszy od rodzica
            {
                mak=tab[g];
                tab[g]=tab[g*2+2];
                tab[g*2+2]=mak;
                wier(g*2+2,wielkosc,tab);//Popraw w glab prawego syna
            }

        }

   }
   else if((g*2+1)==wielkosc) //Jezeli jestesmy w ostatnim wezle i ostatni ma tylko jednego syna.
        {
            if(tab[g*2+1]>tab[g])//I jest on wiekszy od rodzica
            {
                mak=tab[g];
                tab[g]=tab[g*2+1];
                tab[g*2+1]=mak;
            }

        }




}

void kopcuj( int n, int tab[])
{
    int a;
    for(a=((n-1)/2); a>=0; a-=1) //Zaczynajac od ostatniego rodzica, do zerowego)
    {
        wier(a,n,tab);


    }

}

void sort( int n, int tab[])
{
    int tmp;


    tmp=tab[0];
    tab[0]=tab[n];
    tab[n]=tmp;    //zamien pierwszym element z ostatnim.


    if(n>0)
    {
        wier(0,n-1,tab);//popraw pokrewienstwa, nie liczac ostatniego elementu tablicy jako kopca.
        //wier(0,n-1,tab);//popraw pokrewienstwa, nie liczac ostatniego elementu tablicy jako kopca.

        sort(n-1,tab);//Wywolaj sie rekurencyjnie dla mniejszego kopca

    }


}

int main()
{
     int n,t;
    scanf("%i",&n); //pobierz liczbe elementow
     int tab[n]; 

    for(t=0; t<n; t+=1)
    {
        scanf("%i",&tab[t]); //pobieraj elementy
    }

    kopcuj(n-1,tab); //zrob z nich kopiec
    sort(n-1,tab); // i posortuj go

    for(t=0; t<n; t+=1)
    {
        printf("\n%i",tab[t]);
    }
    return 0;// // // // // // // 0
}

 

Początkowy fragment wydruku dla 100tys.

 
300080
323300
342751
414118
1716365491   //
1716365491  //
360861850  //
360861850 //
431231
441294
445515
451620
471514
526076

Oczywiście moje pytanie brzmi co robię źle (i dlaczego jestem niemal pewien, że robię dobrze).
'Błedy te nie pojawiają się zawsze.
Początkowo myślałem, że po prostu przekraczam zakres zmiennej ale przecież wszystkie generowane wartości mieszczą się w incie, a rozszerzenie do long longa w żaden sposób nie poprawia. (Co zresztą zdziwiłbym się, gdyby zadziałało.)
Pozdrawiam i z góry dziękuję za pomoc.

0

Co zrobiłeś źle? Napisałeś to w wersji "dla maszyny" a nie "dla czlowieka" i nikt tego nawet patykiem nie tknie. Przepisz to teraz porządnie. Każda linijka gdzie masz komentarz powinna zostać zamieniona na wywołanie odpowiedniej malutkiej funkcji o sensownej nazwie.

0

Nie jestem pewien co masz na myśli pisząc bym wszystkie linijki z komentarzem zamienił na funkcję, szczególnie że większość komentarzy jest przy ifach, które trudno byłby zamienić na funkcje. Miałem właściwie nadzieję, że komentarze wystarczą do zrozumienia działania. Jedyna funkcja jaka przychodzi mi do głowy, która by nie komplikowała programu bardziej, to funkcja zamieniająca dwa pola w tabeli.
Chyba, że masz na myśli nazwy istniejących funkcji, to według mnie po 'kopcuj' można się domyślić że tworzy ona kopiec z podanej tabeli, a 'sort' sortuje ją. Jedyne do czego mógłbym się w nazwach przyczepić to 'wier', tu fakt mogłem lepiej wytłumaczyć o co chodzi więc zrobię to tutaj: funkcja ta ustawia porządek kopcowy dla danego wierzchołka (g) tabeli tab[] o wielkości wielkosc zakładając, że synowie tego wierzchołka są już w porządku kopcowym.

0

Ale ja doskonale wiem jak działa kopiec. Poprawny kod powinien wyglądać np. tak:

void heapSort(int* tab, int n)
{
    int* heap = makeHeap(tab,n);
    for (int i=0;i<n;i++){
        int minimum = getMinimum(heap);
        tab[i]=minimum;
        fixHeap(heap,n-i);
    }
}

Czemu ten kod jest lepszy? Bo od razu widać czy algorytm jest poprawny czy też nie. Bo jest teraz podzielony na poziomy abstrakcji -> patrząc na funkcje heapSort() mogę od razu stwierdzić czy błąd jest już na tym etapie czy dopiero na którymś z niższych poziomów.
Przepisz swój kode w taki sposób i wtedy może ktoś się zainteresuje.

0

Jednak rozbicie wszystkiego na mniejsze funkcje okazało się opłacalne, kod wydaje się działać wystarczająco prawidłowo. Chociaż teraz jak dla mnie podejrzanie długo pracuje.
Edit. Zdecydowanie, prędkość jest ok 1000 razy mniejsza niż powinna, a wątpię by to, że łączę się z serwerem przez terminal miało jakiś wpływ, chyba że serwer przydziela mi tak mało.

#include<stdio.h>

void wczytaj(int,int[]);
void wypisz(int,int[]);
void zamien(int,int,int[]);
void heapify(int,int,int[]);
void buildheap(int,int[]);
void heapsort(int,int[]);
int lewy(int);
int prawy(int);
int rodzic(int);

int main()
{
    int size;
    scanf("%i",&size);
    int tab[size];
    wczytaj(size,tab);
    heapsort(size-1,tab);
    wypisz(size,tab);
    return 0;
}

void wczytaj(int ile, int tablica[])
{
    int a=0;
    for(; a<ile; a+=1)
    {
        scanf("%i",&tablica[a]);
    }
}
void wypisz(int ile, int tablica[])
{
    int a=0;
    for(; a<ile; a+=1)
    {
        printf("\n%i",tablica[a]);
    }
}
int lewy(int i)
{
    return (i*2+1);
}
int prawy(int i)
{
    return (i*2+2);
}
int rodzic(int i)
{
    return ((i-1)/2);
}
void heapify(int ind, int wielkosc, int tablica[])
{
    int l=lewy(ind);
    int r=prawy(ind);
    int largest;

    if (l<=wielkosc&&tablica[l]>tablica[ind]) largest=l;
    else largest=ind;
    if (r<=wielkosc&&tablica[r]>tablica[largest]) largest=r;
    if (largest!=ind)
    {
        zamien(ind,largest,tablica);
        heapify(largest,wielkosc,tablica);
    }
}
void zamien(int a, int b, int tablica[])
{
    int temp;
    temp=tablica[a];
    tablica[a]=tablica[b];
    tablica[b]=temp;
}
void buildheap(int size,int tablica[])
{

    int ojc=rodzic(size);

    for(; ojc>=0; ojc-=1)
    {
        heapify(ojc,size,tablica);
    }
}

void heapsort(int size, int tablica[])
{

    buildheap(size,tablica);
    zamien(0,size,tablica);
    if (size>1)
    {
        heapify(0,size-1,tablica);
        heapsort(size-1,tablica);
    }
}

 

1 użytkowników online, w tym zalogowanych: 0, gości: 1