[C] Sito Erastotenesa przy użyciu listy

kamil199217
Użytkownik
Użytkownik
Posty: 2
Rejestracja: 22 wrz 2010, o 17:44
Płeć: Mężczyzna
Lokalizacja: M-cz

[C] Sito Erastotenesa przy użyciu listy

Post autor: kamil199217 »

Witam, muszę napisać program wypisujący liczby przy użyciu sita Erastotenesa używając do tego list. Mam z tym dwa problemy. Pierwszy: przy dużym zakresie np. do 10 milionów sito jest wolniejsze od metody naiwnej, a drugi problem jest taki,że program wyświetla liczby, który nie są pierwszymi np. 119 czy 289. Byłbym ogromnie wdzięczny gdyby ktoś wskazał błędy w moim kodzie.

Kod: Zaznacz cały

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>
# define plik "plik.txt"
typedef struct lista{
        int klucz;
        struct lista *nast;
        struct lista *poprzedni;
}lista;
void wloz(lista **pocz, lista **ogon, int elem)
{
     lista *nowy;
     nowy= (lista *)malloc(sizeof(lista));
     nowy->klucz=elem;
     nowy->nast=NULL;
     nowy->poprzedni=NULL;

     if(*pocz==NULL){
         *pocz=nowy;
         *ogon=nowy;
         }
     else{
         nowy->poprzedni=(*ogon);
         (*ogon)->nast=nowy;
         (*ogon)=nowy;
         }

}
void zdejmij(lista **pocz, int elem)
{
     lista *tmp=(*pocz);
     if((*pocz)==NULL){
        printf("Brak el...");
        }
     else{
        while(tmp!=NULL && tmp->klucz!=elem)
        tmp=tmp->nast;
        if(tmp->nast!=NULL){
           tmp->poprzedni->nast=tmp->nast;
           free(tmp);}
        else{ tmp->poprzedni->nast=NULL;
           free(tmp);}
       }
}
void wypisz(lista *pocz){
clock_t start, stop;
float time;
FILE *fp;
start=clock();
fp=fopen("plik.txt", "a");
     if(pocz==NULL)printf("Brak el...");
     else while(pocz!=NULL){
         stop=clock();
time=(stop - start);
fprintf(fp,"%d", pocz->klucz);
 fprintf(fp,";");
fprintf(fp,"%0.3f
",time);     
pocz=pocz->nast;
     }
fclose(fp);
    system("pause");
     }

void sito()
{
    lista *pocz=NULL;
    lista *ogon=NULL;
    lista *wsk;
    lista *wsk2;
    lista *temp;
    int liczba,zakres;
    printf("Podaj zakres wyszukiwania: ");
    scanf("%d", &zakres);
    wloz(&pocz,&ogon,2);
    wloz(&pocz,&ogon,3);
    for(liczba=2;liczba<zakres;liczba++)
    {
        if ((liczba%2)!=0 && ((liczba%3)!=0))
    wloz(&pocz,&ogon,liczba);
    }
    wsk2=pocz->nast->nast;
    wsk=wsk2->nast;
    while(wsk2->klucz<=floor(sqrt(zakres))){
    while(wsk)
    {
       if(((wsk->klucz%(wsk2->klucz))==0))
       {
          temp=wsk->nast;
          zdejmij(&pocz,wsk->klucz);
          wsk=temp;
       }
       else
 wsk=wsk->nast;
    }
       wsk2=wsk2->nast;
       wsk=wsk2->nast;
       }
     wypisz(pocz);
}
int main()
{
    sito();
    return 0;
}
Ostatnio zmieniony 23 paź 2012, o 16:14 przez Afish, łącznie zmieniany 1 raz.
Powód: Brak tagów.
royas
Użytkownik
Użytkownik
Posty: 363
Rejestracja: 24 sie 2012, o 09:27
Płeć: Mężczyzna
Lokalizacja: Cieszyn
Pomógł: 80 razy

[C] Sito Erastotenesa przy użyciu listy

Post autor: royas »

Masz listę dwukierunkową.
Dwie dziwne sprawy są w zdejmij:
1. Aby usunąć dany element nie musisz przeglądać całej listy od początku w poszukiwaniu klucza, żeby potrafić go usunąć. Mając cały element do usunięcia masz od razy dostęp do jego poprzednika i następnika.
2. Usuwając element nie z końca listy poprawiasz tylko nast w poprzedniku, a zapominasz o poprzedni w następniku.
kamil199217
Użytkownik
Użytkownik
Posty: 2
Rejestracja: 22 wrz 2010, o 17:44
Płeć: Mężczyzna
Lokalizacja: M-cz

[C] Sito Erastotenesa przy użyciu listy

Post autor: kamil199217 »

Mam prośbę czy mógłbyś poprawić złe linijki kodu, ponieważ sam nie jestem w stanie odpowiednio poprawić kodu mimo twoich wskazówek.
royas
Użytkownik
Użytkownik
Posty: 363
Rejestracja: 24 sie 2012, o 09:27
Płeć: Mężczyzna
Lokalizacja: Cieszyn
Pomógł: 80 razy

[C] Sito Erastotenesa przy użyciu listy

Post autor: royas »

Ale z czym masz problem?
Narysuj sobie fragment listy dwukierunkowej, przed i po usunięciu elementu. Ile wskazań należy poprawić?
ksisquare
Użytkownik
Użytkownik
Posty: 132
Rejestracja: 1 cze 2012, o 07:04
Płeć: Mężczyzna
Lokalizacja: Polska
Pomógł: 15 razy

[C] Sito Erastotenesa przy użyciu listy

Post autor: ksisquare »

Zdaje mnie mi się, że są dydaktycy z dużą klasą, którzy poświęcają pół życia (przy okazji) na tworzenie zadań.
I są partacze, ale cóż, musisz znieść swój krzyż.
royas
Użytkownik
Użytkownik
Posty: 363
Rejestracja: 24 sie 2012, o 09:27
Płeć: Mężczyzna
Lokalizacja: Cieszyn
Pomógł: 80 razy

[C] Sito Erastotenesa przy użyciu listy

Post autor: royas »

Czy to taka luźna obserwacja, czy sugestia, że coś tu spartaczyłem?
Hassgesang
Użytkownik
Użytkownik
Posty: 206
Rejestracja: 26 mar 2012, o 20:41
Płeć: Mężczyzna
Lokalizacja: Gdynia
Podziękował: 3 razy
Pomógł: 17 razy

[C] Sito Erastotenesa przy użyciu listy

Post autor: Hassgesang »

Nikt normalny nie będzie implementował sita listą, co najwyżej tablicą.
royas
Użytkownik
Użytkownik
Posty: 363
Rejestracja: 24 sie 2012, o 09:27
Płeć: Mężczyzna
Lokalizacja: Cieszyn
Pomógł: 80 razy

[C] Sito Erastotenesa przy użyciu listy

Post autor: royas »

Ale nie można tak poważnie traktować tych zadań z początkowego etapu nauki.
Idąc tym tropem nikt nie powinien pisać bublesorta czy quicksorta, a jednak większość pisze.

Tu po prostu są dwa punkty i nie wiem czy przypadkiem pierwszy nie jest bardziej istotny: zaimplementuj listę, użyj jej do sita.
Hassgesang
Użytkownik
Użytkownik
Posty: 206
Rejestracja: 26 mar 2012, o 20:41
Płeć: Mężczyzna
Lokalizacja: Gdynia
Podziękował: 3 razy
Pomógł: 17 razy

[C] Sito Erastotenesa przy użyciu listy

Post autor: Hassgesang »

Przy pomocy łyżki można opróżnić wannę z wodą, tylko co z tego, skoro łyżka się do tego kompletnie nie nadaje?

Ostatecznie spójrz na ten temat.
royas
Użytkownik
Użytkownik
Posty: 363
Rejestracja: 24 sie 2012, o 09:27
Płeć: Mężczyzna
Lokalizacja: Cieszyn
Pomógł: 80 razy

[C] Sito Erastotenesa przy użyciu listy

Post autor: royas »

Jeśli celem jest opróżnienie wanny to zgoda, ale tu raczej chodzi o zostanie kung-fu mistrzem łyżki.

Tu jesteśmy w stanie zrobić to lepiej niż z std::list, bo operujemy na węzłach tworzących listę. Jeśli mamy coś do usunięcia to mamy już węzeł, który usuwamy w \(\displaystyle{ O(1)}\), natomiast w rozwiązaniu gdzie podajemy klucz, który należy usunąć mamy \(\displaystyle{ O(n)}\). Kamil robi to w ten drugi sposób, choć ma możliwość zrobienia w pierwszy - na to zwracałem uwagę.
ODPOWIEDZ