Sito Eratostenesa - Lista dwukierunkowa

0

Witam !

Mam mały problem z algorytmem sito w liście ...
Otóż kompiluje się dobrze , nie wyskakuję błąd jedynie gdy wchodzi w funkcję odpowiadającą za ten algorytm po prostu zwiesza się.
Możliwe że jest tu jakiś drobny błąd , ale przeglądałem ten kod ze 4 razy i jakoś mi się go nie udało wychwycić . Może ktoś ma jakiś pomysł czemu to cudo nie działa ? Poniżej wklejam cały kod , a funkcja która sprawia problemy jest na końcu:

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

struct prim
{
	int x;
	struct prim *next;
	struct prim *prev;
};
typedef struct prim prim;
prim *head = NULL, *tail = NULL;                //wskaźnik na glowe i ogon listy

//FUNCTIONS
//-------------------------------------------------------------------------
void add(int x);				//dodaje liczbe do listy
void print(void);
void del(prim *trash);			//przyjmuje wskaźnik do usunięci
void sito(int n);				// przyjmuje zakres podany przez uzytkownika
//-------------------------------------------------------------------------
	
int main(int argc, char *argv[]) 
{
	int i;
	int n;
	
	
	print();
	printf("\n\nPodaj Liczbe : ");
	scanf("%d",&n);
	
	for(i=2; i<n; i++)
		add(i);
	print();
	sito(n);
	printf("\n------------------------------------\n");
	fflush(stdin);
	print();
		
	
	return 0;
}

void add(int x)
{
	prim *nowy = NULL;
	
	if(head == NULL)
	{
		head = tail = malloc(sizeof(prim));
		head->x = x;
		head->next = NULL;
		head->prev = NULL;
		return;
	}
	
	nowy = malloc(sizeof(prim));
	nowy->x = x;
	nowy->next = NULL;
	nowy->prev = tail;
	tail->next = nowy;
	tail = nowy;
}

void print(void)
{
	prim *tmp = head;
	if(head == NULL)
	{
		printf("Lista jest pusta");
		return;
	}
	
	while(tmp != NULL)
	{
		printf("%d\n",tmp->x);
		tmp = tmp->next;
	}
	
}

void del(prim *trash)
{
	prim *tmp;
	if(head == NULL)
	{
		printf("Lista jest pusta");
		return;
	}
	else if(trash == head)
	{
		head->next->prev = NULL;
		head = head->next;
		free(trash);
		return;
	}
	else if(trash == tail)
	{
		tail->prev->next = NULL;
		tail = tail->prev;
		free(trash);
		return;		
	}
	
	trash->prev->next = trash->next;
	trash->next->prev = trash->prev;
	free(trash);
}

void sito(int n)
{
	prim *tmp = head, *tmp2 = head;
	
	n = sqrt(n);									
	while(tmp->x < n);							//Wykonuj dopóki Liczba będzie mniejsza od pierwiastka zakresu 
	{
		tmp2 = head;
		while(tmp2 != NULL)						//Wykonuj dopóki wskaźnik tymczasowy tmp2 będzię różny od NULL , aby przejechać całą listę ;
		{
			if((tmp2->x % tmp->x) == 0)			//Jeżeli liczba z listy jest podzielna przez któąś poprzednią
				del(tmp2);						//Wywal
			tmp2 = tmp2->next;					
		}
		tmp = tmp->next;
	}
}











 
0

Przy tej funkcji wchodzi w nią i program niby działa pracuje , ale nic się nie dzieje

void sito(int n)
{
	prim *tmp = head, *tmp2 = head;
	
	n = sqrt(n);									
	while(tmp->x < n);							//Wykonuj dopóki Liczba będzie mniejsza od pierwiastka zakresu 
	{
		tmp2 = head;
		while(tmp2 != NULL)						//Wykonuj dopóki wskaźnik tymczasowy tmp2 będzię różny od NULL , aby przejechać całą listę ;
		{
			if((tmp2->x % tmp->x) == 0)			//Jeżeli liczba z listy jest podzielna przez któąś poprzednią
				del(tmp2);						//Wywal
			tmp2 = tmp2->next;					
		}
		tmp = tmp->next;
	}
} 
0

A wiesz na czym polega sito? bo to nie jest właściwie napisane...
Program się gubi, bo

  1. źle zaimplementowałeś algorytm
if((tmp2->x % tmp->x) == 0)            //Jeżeli liczba z listy jest podzielna przez któąś poprzednią
                del(tmp2);                        //Wywal
            tmp2 = tmp2->next;  

jeśli warunek zostanie spełniony to tmp2 jest źle ustawione, dodatkowo - tak wywalisz wszystkie liczby.

0

Zauważyłem jeden błąd , lecz poprawienie go nic nie zmieniło . Wskaźnik tmp2 będzie ustawiony na właściwym elemencie, jeżeli modulo będzie z 2 liczb zero to znaczy że będzie podzielne i wywalam , jeżeli nie przechodzę po prostu na kolejny element . Problem polegał na tym że odwoływałem się do już nie istniejącego wskaźnika tmp2->next który już był usunięty . Lecz poprawienie tego nic nie zmieniło ...

 void sito(int n)
{
	prim *tmp = head, *tmp2 = head, *trash = NULL;
	
	n = sqrt(n);									
	while(tmp->x < n);						
	{
		tmp2 = head;
		while(tmp2->next != NULL)				
		{
			if((tmp2->x % tmp->x) == 0)	
			{
				trash = tmp2;
				tmp2 = tmp2->next;
				del(trash);
                                continue;
			}
			tmp2 = tmp2->next;
		}
		tmp = tmp->next;
	}
}
0

Dalej pozostaje ten sam problem - nie jest to algorytm sita
dodatkowo każdy element zostanie wg Twojego algorytmu usunięty! I to tak, że tmp zniknie, więc wywali sie na tmp = tmp->next;

0

To niby jaki jest Algorytm sito . Wykreśla wszystkie wielokrotności liczb do pierwiastka zakresu . Czemu niby wszystkie wywali ?

0
kaczus napisał(a):

Dalej pozostaje ten sam problem - nie jest to algorytm sita
dodatkowo każdy element zostanie wg Twojego algorytmu usunięty! I to tak, że tmp zniknie, więc wywali sie na tmp = tmp->next;

Kaczus , nie wprowadzaj w błąd dopóki sam nie wiesz czym jest algorytm sita i jak się go wykonuje . Po zmodyfikowaniu , oczywiście moich kilku głupich błędów kod działa i wypluwa same liczby pierwsze .

Zanim coś napiszesz przeanalizuj kod który ktoś wkleja a dopiero później odpowiadaj .

Pozdrawiam.

Działający kod :

void sito(int n)
{
	prim *tmp = head, *tmp2 = head, *trash = NULL;
	
	while(tmp->x < sqrt(n))
	{
		tmp2 = tmp->next;
		while(tmp2 != NULL)
		{
			if((tmp2->x % tmp->x) == 0)
			{
				trash = tmp2;
				tmp2 = tmp2->next;
				del(trash);
				continue;
			}
			tmp2 = tmp2->next;
		}
		tmp = tmp->next;
	}
} 
0

Złożoność obliczeniowa oczywiście mniejsza będzie przy Tablicy z tym się w 100 % zgadzam . Lecz będzie ona jedynie statyczna a nie dynamiczna, na tym polegają listy i takie miałem zadanie . Poza tym dzisiaj moc obliczeniowa spokojnie pozwala nam na takie zabawy , chyba że piszesz program na jakiś mikroprocesor i musisz oszczędzać to się zgadzam .

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