Strona 1 z 1

[C++] Tablice Mieszające

: 11 lis 2013, o 21:36
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.

[C++] Tablice Mieszające

: 11 lis 2013, o 21:44
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.

[C++] Tablice Mieszające

: 11 lis 2013, o 22:06
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\}}\)

[C++] Tablice Mieszające

: 11 lis 2013, o 22:11
autor: Afish
Zachęcam zatem do pokazania poprawionego kodu.

[C++] Tablice Mieszające

: 11 lis 2013, o 22:16
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;
}


[C++] Tablice Mieszające

: 11 lis 2013, o 22:30
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.

[C++] Tablice Mieszające

: 11 lis 2013, o 22:47
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

[C++] Tablice Mieszające

: 11 lis 2013, o 23:00
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.

[C++] Tablice Mieszające

: 11 lis 2013, o 23:11
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

[C++] Tablice Mieszające

: 11 lis 2013, o 23:17
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.

[C++] Tablice Mieszające

: 11 lis 2013, o 23:48
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

[C++] Tablice Mieszające

: 15 lis 2013, o 00:17
autor: qba92
Myślę, że dr K to przyjmie z godnością a już rysuje Ci ładnie w gnuplocie?