395 lines
11 KiB
C++
395 lines
11 KiB
C++
#include <iostream>
|
||
#include <algorithm>
|
||
#include <chrono>
|
||
#include <random>
|
||
#include <iomanip>
|
||
|
||
//#include <limits>
|
||
//#include <algorithm>
|
||
//#include <string>
|
||
//#include <iomanip>
|
||
//#include <fstream>
|
||
//#include <clocale>
|
||
|
||
#define EMPTY -1 // puste miejsce w tablicy mieszajacej
|
||
#define REMOVED -2 // puste miejsce tablicy mieszajacej z ktorego usuniety zostal jakis element
|
||
|
||
long long int g_counter {0};
|
||
//Zad. 1 Wstawianie do tablicy mieszajacej (adresowanie liniowe)
|
||
|
||
/** Funkcja mieszająca wykorzystująca adresowanie liniowe
|
||
@param x element dla którego obliczamy wartość funkcji mieszającej
|
||
@param m rozmiar tablicy do której wstawiamy (parametr funki mieszajacej)
|
||
@param i która to próba wstawienia/które obliczenie funkcji mieszającej (parametr funki mieszajacej)
|
||
@return wartość f. mieszającej, pod ten indeks próbujemy wstawić potem x
|
||
*/
|
||
int h(int x, int m, int i){
|
||
g_counter++;
|
||
if (i==0) {
|
||
return x % m;
|
||
} else {
|
||
return (x % m + i) % m;
|
||
}
|
||
};
|
||
|
||
int h_kw(int x, int m, int i){
|
||
g_counter++;
|
||
int formula = ((x % m) + (2 * i * i) - (5*i)) % m;
|
||
return (formula<0) ? (m+formula)%m : formula;
|
||
};
|
||
|
||
int h_d(int x, int m, int i){
|
||
g_counter++;
|
||
int formula = ((x % m) + i*((((x/m)%(m/2))*2) + 1))%m;
|
||
return formula;
|
||
};
|
||
/*
|
||
*h(x, i, m) = (h1(x, m) + i*(h2(x, m)) mod m dla: i = 0, 1, 2, . . . , m − 1,
|
||
h1(x, m) = x mod m,
|
||
h2(x, m) = (((x/m) mod (m/2)) * 2) + 1.
|
||
*
|
||
** Funkcja wstawiajaca jeden element x do tablicy mieszajacej tab o rozmiarze m
|
||
@param A tablica mieszajaca
|
||
@param m rozmiar tablicy mieszajacej
|
||
@param x element wstawiany do tablicy
|
||
@return true, jesli element zostal wstawiony; false, jesli nie udalo sie wstawic elementu (brak miejsca w tablicy)
|
||
*/
|
||
bool hash_al_wstaw(int * A, int m, int x)
|
||
{
|
||
// Zaimplementuj
|
||
//...
|
||
for (int i = 0; i < m-1; i++) {
|
||
int k = h(x, m, i);
|
||
if (A[k] == EMPTY || A[k] == REMOVED){
|
||
A[k]=x;
|
||
return true;
|
||
}
|
||
}
|
||
return false;
|
||
}
|
||
|
||
bool hash_al_szukaj(int * A, int m, int x){
|
||
for (int i = 0; i < m; i++) {
|
||
int k = h(x, m, i);
|
||
if (A[k] == x){ return true;}
|
||
if (A[k] == EMPTY){ return false;}
|
||
}
|
||
return false;
|
||
}
|
||
|
||
|
||
bool hash_al_wstaw_kw(int * A, int m, int x)
|
||
{
|
||
// Zaimplementuj
|
||
//...
|
||
for (int i = 0; i < m-1; i++) {
|
||
int k = h_kw(x, m, i);
|
||
if (A[k] == EMPTY || A[k] == REMOVED){
|
||
A[k]=x;
|
||
return true;
|
||
}
|
||
}
|
||
return false;
|
||
}
|
||
|
||
bool hash_al_szukaj_kw(int * A, int m, int x){
|
||
for (int i = 0; i < m; i++) {
|
||
int k = h_kw(x, m, i);
|
||
if (A[k] == x){ return true;}
|
||
if (A[k] == EMPTY){ return false;}
|
||
}
|
||
return false;
|
||
}
|
||
|
||
bool hash_al_wstaw_d(int * A, int m, int x)
|
||
{
|
||
// Zaimplementuj
|
||
//...
|
||
for (int i = 0; i < m-1; i++) {
|
||
int k = h_d(x, m, i);
|
||
if (A[k] == EMPTY || A[k] == REMOVED){
|
||
A[k]=x;
|
||
return true;
|
||
}
|
||
}
|
||
return false;
|
||
}
|
||
|
||
bool hash_al_szukaj_d(int * A, int m, int x){
|
||
for (int i = 0; i < m; i++) {
|
||
int k = h_d(x, m, i);
|
||
if (A[k] == x){ return true;}
|
||
if (A[k] == EMPTY){ return false;}
|
||
}
|
||
return false;
|
||
}
|
||
|
||
int main()
|
||
{
|
||
std::cout << "Zadanie 1 i 2:\n";
|
||
// Zad. 2 (rozgrzewka + test)
|
||
const int m1 = 8; //rozmiar tablicy mieszajacej
|
||
int t[m1]; //tablica mieszajaca
|
||
// Wyczyszczenie tablicy mieszajacej t (Wypelnienie pustymi miejscami)
|
||
for (int i = 0; i < m1; i++)
|
||
{
|
||
t[i] = EMPTY;
|
||
}
|
||
|
||
// Wstawianie elementów do tablicy mieszajacej t (uzyć funkcji hash_al_wstaw)
|
||
for(int x : {8,6,18,11,3,32,19,27})
|
||
{
|
||
hash_al_wstaw(t, m1, x);
|
||
}
|
||
// ...
|
||
|
||
|
||
// Wyswietlenie tablicy mieszajacej t o rozmiarze m1
|
||
std::cout << std::setw(7) << "indeks:";
|
||
for (int i = 0; i < m1; i++)
|
||
{
|
||
std::cout << std::setw(11) << i;
|
||
}
|
||
std::cout << std::endl;
|
||
std::cout << std::setw(8) << "|";
|
||
for (int i = 0; i < m1; i++)
|
||
{
|
||
std::cout << std::setw(10) << t[i] << "|" ;
|
||
}
|
||
std::cout << std::endl;
|
||
|
||
|
||
// Zad. 3 Pomiary
|
||
|
||
std::cout << "\nZadanie 3:\n";
|
||
// a) Tablica z danymi
|
||
// Tworzenie tablicy dane z danymi do wstawinia do tablicy mieszajacej
|
||
int rozm_dane = 20000000; //liczba elementow w tablicy dane
|
||
int* dane = new int[rozm_dane];
|
||
//wypelnienie tablicy dane kolejnymi liczbami od 0 do rozm_dane-1
|
||
for (int i = 0;i < rozm_dane;i++)
|
||
{
|
||
dane[i] = i;
|
||
}
|
||
std::random_device rd;
|
||
std::mt19937 g(rd());
|
||
std::shuffle(dane, dane + rozm_dane, g); //losowa permutacja elementow w tablicy dane (wymieszanie tablicy)
|
||
|
||
|
||
// b) Tablica mieszajaca
|
||
// Utworz pusta tablice mieszajaca tab o rozmiarze m = 2097152 (2 do potegi 21)
|
||
const int m = 2097152;
|
||
int * tab = new int[m];
|
||
for (int i = 0; i < m ; i++)
|
||
{
|
||
tab[i] = EMPTY;
|
||
}
|
||
|
||
// ...
|
||
|
||
// c) Wstaw 10000 elemetow z tablicy dane do pustej tablicy mieszajacej tab (zapelnienie 0%). Na tej podstawie zmierz sredni czas wstawiania elementu oraz srednią liczbe wywolan funkcji mieszajacej przy wstawianiu elementu do pustej tablicy.
|
||
|
||
std::cout << "Pomiary:\n";
|
||
g_counter = 0;
|
||
// Mierzenie czasu, przyklad:
|
||
auto start = std::chrono::high_resolution_clock::now();
|
||
for (int i = 0; i < 10000; i++) {
|
||
hash_al_wstaw(tab, m, dane[i]);
|
||
}
|
||
|
||
//tutaj mierzona operacja
|
||
auto stop = std::chrono::high_resolution_clock::now();
|
||
std::chrono::duration<double, std::micro> czas = stop - start;
|
||
std::cerr << "Uplynelo: " << czas.count() << " us\n";
|
||
std::cerr << "Ilość wywołań funkcji wstawiającej: " << g_counter << "\n";
|
||
// d) Zmierz sredni czas wstawiania elementu oraz srednią liczbe wywolan funkcji mieszajacej przy wstawianiu elementu do tablicy wypelnionej w 10%, 20%, 30%, 40%, 50%, 60%, 70%, 80%, 90% (dla próbki: 10000 elementów).
|
||
//UWAGA! Do tablicy mieszajacej nie wstawiac elementow, ktore juz w niej sa.
|
||
for(double range : {0.0,0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9}){
|
||
for (int i = 0; i < m ; i++)
|
||
{
|
||
tab[i] = EMPTY;
|
||
}
|
||
|
||
g_counter = 0;
|
||
for (int i = 0; i < range*m; i++) {
|
||
hash_al_wstaw(tab, m, dane[i]);
|
||
}
|
||
|
||
|
||
g_counter = 0;
|
||
// Mierzenie czasu, przyklad:
|
||
std::cerr << "Pomiar dla " << range*100 << "%\n";
|
||
auto start = std::chrono::high_resolution_clock::now();
|
||
for (int i = range*m; i < (range*m)+10000; i++) {
|
||
hash_al_wstaw(tab, m, dane[i]);
|
||
}
|
||
auto stop = std::chrono::high_resolution_clock::now();
|
||
std::chrono::duration<double, std::micro> czas = stop - start;
|
||
std::cerr << "Uplynelo: " << czas.count() << " us\n";
|
||
std::cerr << "Ilość wywołań funkcji wstawiającej: " << g_counter << "\n";
|
||
|
||
|
||
|
||
}
|
||
|
||
std::cerr << std::endl;
|
||
for(double range : {0.0,0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9}){
|
||
for (int i = 0; i < m ; i++)
|
||
{
|
||
tab[i] = EMPTY;
|
||
}
|
||
|
||
g_counter = 0;
|
||
for (int i = 0; i < range*m; i++) {
|
||
hash_al_wstaw(tab, m, dane[i]);
|
||
}
|
||
|
||
|
||
g_counter = 0;
|
||
// Mierzenie czasu, przyklad:
|
||
std::cerr << "Pomiar wyszukiwania dla " << range*100 << "%\n";
|
||
int idx=0;
|
||
int krok = (range*m)/10000;
|
||
auto start = std::chrono::high_resolution_clock::now();
|
||
for (int i = 0; i < 10000; i++) {
|
||
hash_al_szukaj(tab, m, dane[idx]);
|
||
idx = idx+krok;
|
||
|
||
}
|
||
auto stop = std::chrono::high_resolution_clock::now();
|
||
std::chrono::duration<double, std::micro> czas = stop - start;
|
||
std::cerr << "Uplynelo: " << czas.count() << " us\n";
|
||
std::cerr << "Ilość wywołań funkcji szukającej: " << g_counter << "\n";
|
||
|
||
|
||
|
||
}
|
||
//...
|
||
std::cerr<<std::endl;
|
||
std::cerr<<std::endl;
|
||
std::cerr<<std::endl;
|
||
for(double range : {0.0,0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9}){
|
||
for (int i = 0; i < m ; i++)
|
||
{
|
||
tab[i] = EMPTY;
|
||
}
|
||
|
||
g_counter = 0;
|
||
for (int i = 0; i < range*m; i++) {
|
||
hash_al_wstaw_kw(tab, m, dane[i]);
|
||
}
|
||
|
||
|
||
g_counter = 0;
|
||
// Mierzenie czasu, przyklad:
|
||
std::cerr << "Pomiar wstawiania kwadratowego dla " << range*100 << "%\n";
|
||
auto start = std::chrono::high_resolution_clock::now();
|
||
for (int i = range*m; i < (range*m)+10000; i++) {
|
||
hash_al_wstaw_kw(tab, m, dane[i]);
|
||
}
|
||
auto stop = std::chrono::high_resolution_clock::now();
|
||
std::chrono::duration<double, std::micro> czas = stop - start;
|
||
std::cerr << "Uplynelo: " << czas.count() << " us\n";
|
||
std::cerr << "Ilość wywołań funkcji wstawiającej: " << g_counter << "\n";
|
||
|
||
|
||
|
||
}
|
||
|
||
std::cerr << std::endl;
|
||
for(double range : {0.0,0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9}){
|
||
for (int i = 0; i < m ; i++)
|
||
{
|
||
tab[i] = EMPTY;
|
||
}
|
||
|
||
g_counter = 0;
|
||
for (int i = 0; i < range*m; i++) {
|
||
hash_al_wstaw_kw(tab, m, dane[i]);
|
||
}
|
||
|
||
|
||
g_counter = 0;
|
||
// Mierzenie czasu, przyklad:
|
||
std::cerr << "Pomiar wyszukiwania kwadratowego dla " << range*100 << "%\n";
|
||
int idx=0;
|
||
int krok = (range*m)/10000;
|
||
auto start = std::chrono::high_resolution_clock::now();
|
||
for (int i = 0; i < 10000; i++) {
|
||
hash_al_szukaj_kw(tab, m, dane[idx]);
|
||
idx = idx+krok;
|
||
|
||
}
|
||
auto stop = std::chrono::high_resolution_clock::now();
|
||
std::chrono::duration<double, std::micro> czas = stop - start;
|
||
std::cerr << "Uplynelo: " << czas.count() << " us\n";
|
||
std::cerr << "Ilość wywołań funkcji szukającej: " << g_counter << "\n";
|
||
|
||
|
||
|
||
}
|
||
|
||
std::cerr<<std::endl;
|
||
std::cerr<<std::endl;
|
||
std::cerr<<std::endl;
|
||
for(double range : {0.0,0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9}){
|
||
for (int i = 0; i < m ; i++)
|
||
{
|
||
tab[i] = EMPTY;
|
||
}
|
||
|
||
g_counter = 0;
|
||
for (int i = 0; i < range*m; i++) {
|
||
hash_al_wstaw_d(tab, m, dane[i]);
|
||
}
|
||
|
||
|
||
g_counter = 0;
|
||
// Mierzenie czasu, przyklad:
|
||
std::cerr << "Pomiar wstawiania podwójnego dla " << range*100 << "%\n";
|
||
auto start = std::chrono::high_resolution_clock::now();
|
||
for (int i = range*m; i < (range*m)+10000; i++) {
|
||
hash_al_wstaw_d(tab, m, dane[i]);
|
||
}
|
||
auto stop = std::chrono::high_resolution_clock::now();
|
||
std::chrono::duration<double, std::micro> czas = stop - start;
|
||
std::cerr << "Uplynelo: " << czas.count() << " us\n";
|
||
std::cerr << "Ilość wywołań funkcji wstawiającej: " << g_counter << "\n";
|
||
|
||
|
||
|
||
}
|
||
|
||
std::cerr << std::endl;
|
||
for(double range : {0.0,0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9}){
|
||
for (int i = 0; i < m ; i++)
|
||
{
|
||
tab[i] = EMPTY;
|
||
}
|
||
|
||
g_counter = 0;
|
||
for (int i = 0; i < range*m; i++) {
|
||
hash_al_wstaw_d(tab, m, dane[i]);
|
||
}
|
||
|
||
|
||
g_counter = 0;
|
||
// Mierzenie czasu, przyklad:
|
||
std::cerr << "Pomiar wyszukiwania podwójnego dla " << range*100 << "%\n";
|
||
int idx=0;
|
||
int krok = (range*m)/10000;
|
||
auto start = std::chrono::high_resolution_clock::now();
|
||
for (int i = 0; i < 10000; i++) {
|
||
hash_al_szukaj_d(tab, m, dane[idx]);
|
||
idx = idx+krok;
|
||
|
||
}
|
||
auto stop = std::chrono::high_resolution_clock::now();
|
||
std::chrono::duration<double, std::micro> czas = stop - start;
|
||
std::cerr << "Uplynelo: " << czas.count() << " us\n";
|
||
std::cerr << "Ilość wywołań funkcji szukającej: " << g_counter << "\n";
|
||
|
||
}
|
||
return 0;
|
||
}
|