[C++] Tablice Mieszające

Awatar użytkownika
piti-n
Użytkownik
Użytkownik
Posty: 534
Rejestracja: 24 gru 2010, o 22:42
Płeć: Mężczyzna
Lokalizacja: Wroclaw
Podziękował: 41 razy
Pomógł: 45 razy

[C++] Tablice Mieszające

Post autor: piti-n »

Przeprowadzić eksperymenty dotyczące wstawiania do tablicy haszowanej rozmiaru m metodą
adresowania otwartego przy wykorzystaniu:
• adresowania linowego z funkcją \(\displaystyle{ h \left( k, i \right) = \left( h ' \left( k \right) + i \right) \mod m}\),
• adresowania kwadratowego z funkcją \(\displaystyle{ h \left( k, i \right) = \left( h ' \left( k \right) + c_1 \cdot i + c_2 \cdot i ^{2} \right) \mod m}\)
• adresowania dwukrotnego z funkcją \(\displaystyle{ h \left( k, i \right) = \left( h ' \left( k \right) + i \cdot h '' \left( k \right) \right) \mod m}\)
gdzie: \(\displaystyle{ k}\) – liczba całkowita nieujemna – jest wstawianym kluczem, \(\displaystyle{ h \left( k, i \right)}\) – miejsce wstawiania \(\displaystyle{ k}\)
w \(\displaystyle{ i}\)-tej próbie, oraz \(\displaystyle{ h ′ \left( k \right) = k \mod m}\), a \(\displaystyle{ h '' \left( k \right) = 1 + k \mod \left( m - 1 \right)}\)

A wiec napisałem taki kod:

Kod: Zaznacz cały

#include <math.h>
#include <cstdlib>
#include <ctime>
#include <stdio.h>
#include <iostream>

void RandomNumber(int A[],int n)
{
	int i=0;
	while(i<n)						//przechodzimy po każdym elemencie tablicy i przypisujemy mu jakąś losową wartość
	{
		A[i]=(rand()) % (n)+1 ;  		//(rand()) % (n*n-1) losuje liczbę i (%) przeprowadza operację modulo z (n*n-1) czyli zwraca resztę z dzielenia wylosowanej liczby przez (n*n-1)
	//	std::cout<<A[i]<<" ";			// po odkomentowaniu drukuje nieposortowaną tablice
		i++;
	}
				//std::cout<<"
";	

}
void dwukrotne(int A[], int m,int c){
	int i=0;
	 int proba=1;
	int * tmp=new int[m];
	while(i<m)	{
		tmp[i]=0;	
		i++;
	}
	i=0;
	while(i<m){
		while(true){
			if(tmp[((A[i]%m) + proba * ((1+A[i])%(m-1))) % m]==0){
				tmp[((A[i]%m) + proba * ((1+A[i])%(m-1))) % m]=A[i];
				break;

			}
			//if(i%(long int)(m/50)==0){

		//std::cout<<i+1<<" "<<proba<<" "<<"
";
		//std::cout<<proba<<" "<<"
";
		//}		
					std::cout<<proba<<", "<<"
";

			proba++;
		}

		//std::cout<<proba<<" ";	
		proba=1;
		i++;
	}
	i=0;
			std::cout<<"
";	

//	while(i<m)	{
	//std::cout<<tmp[i]<<" ";	
	//	i++;
	//}
}
void kwadratowe(int A[], int m,int c){
	int i=0,proba=1;
int * tmp=new int[m];
	while(i<m)	{
		tmp[i]=0;	
		i++;
	}
	i=0;
	while(i<m){
		while(true){
			if(tmp[(( int)((A[i]%m)+proba+c*pow(proba,2)) ) % m]==0){
				tmp[((int)((A[i]%m)+proba+c*pow(proba,2)) ) % m]=A[i];
				break;
			}
			proba++;
		}
		//if(i%(long int)(m/50)==0){
			std::cout<<m<<", "<<"
";

		//std::cout<<i+1<<" "<<proba<<" "<<"
";
		//std::cout<<proba<<" "<<"
";
		//}	
		proba=1;
		i++;
	}
	i=0;
			std::cout<<"
";	

	//while(i<m)	{
	//std::cout<<tmp[i]<<" ";	
	//	i++;
	//}
}


void liniowe(int  A[], int m){
	int i=1,proba=1,e=0;
	int tmp[m];
	while(i<m)	{
		tmp[i]=0;	
		i++;
	}
	i=0;
	while(i<m){
		while(true){
			if(tmp[(A[i]+proba)%m]==0){
				tmp[(A[i]+proba)%m]=A[i];
				break;
			}
			proba++;
		}
		if(i%(int)floor(m/50)==0){
				//	std::cout<<m<<", "<<"
";

		//std::cout<<i+1<<" "<<proba<<" "<<"
";
		//std::cout<<proba<<" "<<"
";
		e++;}	
		proba=1;
		i++;
	}
	i=0;
			

	//while(i<m)	{
	//std::cout<<tmp[i]<<" ";	
	//	i++;
	//}
}

int main(int argc, char **argv)
{
	int length = 25;
	
	srand( time( NULL ) );	
	while(length<=1000){
	int* A= new int[length];
	RandomNumber(A,4*length);	
	//liniowe(A,length);
	kwadratowe(A,4*length,2*length);
		//dwukrotne(A,length,length);

	length+=25;
}
	

	//kwadratowe(A,length,2*length);
	//dwukrotne(A,length,2*length);
	return 0;
}

Dla liniowego ładnie działa wszystko. Dla kwadratowego przy m=2200 wysypuje Naruszenie ochrony pamięci, A przy podwójnym niestety już przy m = 25 ma problem z obliczeniem tego i dochodzi do próby kilkuset tysiecznej i nie może wstawić. proba=i, length=m. Jakby był ktoś w stanie sprawdzić czemu tak sie dzieje, to byłbym bardzo wdzieczny.
Ostatnio zmieniony 11 lis 2013, o 21:47 przez Afish, łącznie zmieniany 1 raz.
Powód: Stosuj tagi, dbaj o formatowanie. Nieczytelny zapis to brak szacunku dla innych użytkowników forum.
Afish
Moderator
Moderator
Posty: 2828
Rejestracja: 15 cze 2008, o 15:45
Płeć: Mężczyzna
Lokalizacja: Seattle, WA
Podziękował: 3 razy
Pomógł: 356 razy

[C++] Tablice Mieszające

Post autor: Afish »

Dlaczego losujesz liczby do 4*length, podczas gdy tablica ma rozmiar length? W kwadratowym robisz podobne zabiegi.

Poza tym formatuj porządnie kod i pisz czytelniej.
Awatar użytkownika
piti-n
Użytkownik
Użytkownik
Posty: 534
Rejestracja: 24 gru 2010, o 22:42
Płeć: Mężczyzna
Lokalizacja: Wroclaw
Podziękował: 41 razy
Pomógł: 45 razy

[C++] Tablice Mieszające

Post autor: piti-n »

dziękuję, za dużo godzin programowania i przeoczyłem to. Niemniej to nie rozwiazuje problemu. tam jest \(\displaystyle{ 4 \cdot length}\) ze wzgledu że dla kw. w treści zadań ma być \(\displaystyle{ 4 \cdot length}\) gdzie, \(\displaystyle{ length \in \left\{ 25,50,...,2500\right\}}\)
Ostatnio zmieniony 11 lis 2013, o 22:11 przez Afish, łącznie zmieniany 1 raz.
Powód: Poprawa wiadomości.
Afish
Moderator
Moderator
Posty: 2828
Rejestracja: 15 cze 2008, o 15:45
Płeć: Mężczyzna
Lokalizacja: Seattle, WA
Podziękował: 3 razy
Pomógł: 356 razy

[C++] Tablice Mieszające

Post autor: Afish »

Zachęcam zatem do pokazania poprawionego kodu.
Awatar użytkownika
piti-n
Użytkownik
Użytkownik
Posty: 534
Rejestracja: 24 gru 2010, o 22:42
Płeć: Mężczyzna
Lokalizacja: Wroclaw
Podziękował: 41 razy
Pomógł: 45 razy

[C++] Tablice Mieszające

Post autor: piti-n »

Kod: Zaznacz cały

#include <math.h>
#include <cstdlib>
#include <ctime>
#include <stdio.h>
#include <iostream>

void RandomNumber(int A[],int n)
{
	int i=0;
	while(i<n)						
	{
		A[i]=(rand()) % (n)+1 ;  		
		i++;
	}
			

}
void dwukrotne(int A[], int m,int c){
	int i=0;
	int proba=1;
	int * tmp=new int[m];
	while(i<m)	{
		tmp[i]=0;	
		i++;
	}
	i=0;
	while(i<m){
		while(true){
			if(tmp[((A[i]%m) + proba * ((1+A[i])%(m-1))) % m]==0){
				tmp[((A[i]%m) + proba * ((1+A[i])%(m-1))) % m]=A[i];
				break;
			}
			proba++;
		}
		proba=1;
		i++;
	}
	i=0;
	std::cout<<"
";	
//	while(i<m)	{
	//std::cout<<tmp[i]<<" ";	
	//	i++;
	//}
}
void kwadratowe(int A[], int m,int c){
	int i=0,proba=1;
	int * tmp=new int[m];
	while(i<m)	{
		tmp[i]=0;	
		i++;
	}
	i=0;
	while(i<m){
		while(true){
			if(tmp[(( int)((A[i]%m)+proba+c*pow(proba,2)) ) % m]==0){
				tmp[((int)((A[i]%m)+proba+c*pow(proba,2)) ) % m]=A[i];
				break;
			}
			proba++;
		}
		proba=1;
		i++;
	}
	i=0;
	std::cout<<"
";	
	//while(i<m)	{
	//std::cout<<tmp[i]<<" ";	
	//	i++;
	//}
}


void liniowe(int  A[], int m){
	int i=1,proba=1,e=0;
	int tmp[m];
	while(i<m)	{
		tmp[i]=0;	
		i++;
	}
	i=0;
	while(i<m){
		while(true){
			if(tmp[(A[i]+proba)%m]==0){
				tmp[(A[i]+proba)%m]=A[i];
				break;
			}
			proba++;
		}
		//if(i%(int)floor(m/50)==0){
			//	std::cout<<m<<", "<<"
";
			//std::cout<<i+1<<" "<<proba<<" "<<"
";
			//std::cout<<proba<<" "<<"
";
		//}	
		proba=1;
		i++;
	}
	i=0;
	//while(i<m)	{
	//std::cout<<tmp[i]<<" ";	
	//	i++;
	//}
}

int main(int argc, char **argv)
{
	int length = 25;
	srand( time( NULL ) );	
	while(length<=1000){
		int* A= new int[4*length];
		RandomNumber(A,4*length);	
		//liniowe(A,4*length);
		//kwadratowe(A,4*length,2*length);
		dwukrotne(A,length,length);
		length+=25;
	}
	return 0;
}

Afish
Moderator
Moderator
Posty: 2828
Rejestracja: 15 cze 2008, o 15:45
Płeć: Mężczyzna
Lokalizacja: Seattle, WA
Podziękował: 3 razy
Pomógł: 356 razy

[C++] Tablice Mieszające

Post autor: Afish »

W funkcji liniowe linijka int tmp[m]; jest niezgodna ze standardem.

Kod: Zaznacz cały

if(tmp[(( int)((A[i]%m)+proba+c*pow(proba,2)) ) % m]==0){
            tmp[((int)((A[i]%m)+proba+c*pow(proba,2)) ) % m]=A[i];
            break;
         }
Na moje oko wyskakujesz tutaj poza zakres integera. Ponadto zauważ, że wyrażenie będące indeksem tablicy można łatwo wydzielić do zmiennej i nie pisać go dwukrotnie.
Awatar użytkownika
piti-n
Użytkownik
Użytkownik
Posty: 534
Rejestracja: 24 gru 2010, o 22:42
Płeć: Mężczyzna
Lokalizacja: Wroclaw
Podziękował: 41 razy
Pomógł: 45 razy

[C++] Tablice Mieszające

Post autor: piti-n »

faktycznie masz racje. Zmieniłem na long inta i działa. Nadal jednak nie działa dwukrotne. Z tego co sobie wypisywałem w tym miejscu

Kod: Zaznacz cały

while(i<m){
      while(true){
         if(tmp[((A[i]%m) + proba * ((1+A[i])%(m-1))) % m]==0){
            tmp[((A[i]%m) + proba * ((1+A[i])%(m-1))) % m]=A[i];
            break;
         }
         proba++;
         std::cout<<proba<<"
";
      }
      proba=1;
      i++;
   }

to poprostu algorytm próbował wstawić jednakże nie mógł i próba wędrowała do olbrzymich liczb
Afish
Moderator
Moderator
Posty: 2828
Rejestracja: 15 cze 2008, o 15:45
Płeć: Mężczyzna
Lokalizacja: Seattle, WA
Podziękował: 3 razy
Pomógł: 356 razy

[C++] Tablice Mieszające

Post autor: Afish »

Na moje oko jest okej. Program nie wstawia elementów, bo warunek nigdy nie jest spełniony, czyli funkcja mieszająca zwraca cyklicznie indeksy, pod którymi są już wpisane inne elementy, co może się zdarzyć.
Przykład:
\(\displaystyle{ h '' \left( k \right) = 1 + k \mod \left( m - 1 \right)}\)
Jeżeli \(\displaystyle{ k = m-2}\), to wynikiem tego będzie \(\displaystyle{ 0}\). Wtedy niezależnie od numeru próby, funkcja mieszająca zwróci ten sam wynik.

Swoją drogą, nigdzie nie zwalniasz tablic tymczasowych tmp.
Awatar użytkownika
piti-n
Użytkownik
Użytkownik
Posty: 534
Rejestracja: 24 gru 2010, o 22:42
Płeć: Mężczyzna
Lokalizacja: Wroclaw
Podziękował: 41 razy
Pomógł: 45 razy

[C++] Tablice Mieszające

Post autor: piti-n »

No wiem, że sie może tak zdarzyć jednakże to sie zdarza z prawdopodobieństwem 0.99 co jest raczej dziwne szczególnie że mam zrobić po 50 eksperymentów
Afish
Moderator
Moderator
Posty: 2828
Rejestracja: 15 cze 2008, o 15:45
Płeć: Mężczyzna
Lokalizacja: Seattle, WA
Podziękował: 3 razy
Pomógł: 356 razy

[C++] Tablice Mieszające

Post autor: Afish »

To zapewne przez prawo wielkich liczb ;) Możesz debugować i szukać, czy nie ma tam błędu, aczkolwiek osobiście poprzestałbym na uzasadnieniu, że owa funkcja mieszająca jest do niczego.
Awatar użytkownika
piti-n
Użytkownik
Użytkownik
Posty: 534
Rejestracja: 24 gru 2010, o 22:42
Płeć: Mężczyzna
Lokalizacja: Wroclaw
Podziękował: 41 razy
Pomógł: 45 razy

[C++] Tablice Mieszające

Post autor: piti-n »

Troche głupio powiedziec wykładowcy że funkcja którą sobie tam wymyślił jest do niczego ale ok
Dzięki wielkie za pomoc
qba92
Użytkownik
Użytkownik
Posty: 3
Rejestracja: 18 gru 2011, o 19:38
Płeć: Mężczyzna
Lokalizacja: Wrocław

[C++] Tablice Mieszające

Post autor: qba92 »

Myślę, że dr K to przyjmie z godnością a już rysuje Ci ładnie w gnuplocie?
ODPOWIEDZ