/* This file implements a static open-address hashtable which uses double hashing. Copyright (C) 2004 The University of Texas at Austin This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. Email: usman@cs.njit.edu Mail: Usman Roshan, Department of Computer Sciences, NJIT-CCS, Computer Science Department, GITC 4400, University Heights, Newark, NJ 07102 */ /* Notes: when inserting key into table, must make sure that value is NULL. */ #include #include #include #include #include #include #include void list_hashtable2_stats(hashtable2 ht) { int i; assert(ht); for (i = 0; i < ht->size_; i++) { if (ht->table_[i]) { lookup_hashtable2(ht, ht->table_[i]->key); printf("Entry %d has problength=%d\n", i, probelength_hashtable2(ht)); } } } int probelength_hashtable2(hashtable2 ht) { return ht->probelength_; } void del_hashtable2(hashtable2 ht) { int i; assert(ht); for (i = 0; i < ht->size_; i++) if (ht->table_[i]) { /* * MUST free void* from main program by casting * appropriately */ assert(ht->table_[i]->value == NULL); free(ht->table_[i]); } free(ht->table_); free(ht); } /* * IMPORTANT: hashtable size MUST be of size of power of 2, otherwise all the * possible entries will not be considered */ hashtable2 new_hashtable2(long sz) { int i; double x; hashtable2 ht; ht = (hashtable2) malloc(sizeof(struct hashtable2_struct)); /* setting hashtable to be size of power of 2 */ /* this is required so that proper open addressing can occur, */ /* i.e. eventually every entry in the table is considered */ x = ceil(log(sz) / log(2)); sz = pow(2, x + 1); ht->size_ = sz; /* allocate memory for table */ ht->table_ = (hashtable2_node *) malloc(ht->size_ * sizeof(hashtable2_node)); /* initialize to NULLS */ for (i = 0; i < ht->size_; i++) ht->table_[i] = 0; ht->P_ = 2147483647; /* initialize P (large prime) */ ht->probelength_ = 0; /* initialize hash2_1 and hash2_2 variables */ srand(time(0)); ht->a1_ = rand() * (ht->P_ - 1) + 1; ht->a2_ = rand() * (ht->P_ - 1) + 1; ht->b1_ = rand() * ht->P_; ht->b2_ = rand() * ht->P_; return ht; } /* * This is called before hash2_1 and hash2_2. It sets the value of h_ to be * used by hash2_1 and hash2_2 and saves excessive calls to the hash * function. */ unsigned int hash_2(hashtable2 ht, PTR_TYPE key) { assert(ht); assert(key); key += (key << 12); key ^= (key >> 22); key += (key << 4); key ^= (key >> 9); key += (key << 10); key ^= (key >> 2); key += (key << 7); key ^= (key >> 12); ht->h_ = key; return key; } unsigned long hash2_1(hashtable2 ht) { assert(ht); return ((((ht->a1_ * ht->h_) + ht->b1_) % ht->P_) % ht->size_); } unsigned long hash2_2(hashtable2 ht) { assert(ht); return ((((ht->a2_ * ht->h_ + ht->b2_) % ht->P_) % (ht->size_ - 3)) | 1); } void insert_hashtable2(hashtable2 ht, PTR_TYPE key, void *value) { unsigned long i; int h1, h2; assert(ht); assert(key); hash_2(ht, key); /* hash_2(ht, key, ht->a1_, ht->a2_); */ h1 = hash2_1(ht); h2 = hash2_2(ht); ht->probelength_ = 0; for (i = h1; ht->table_[i]; i = (i + h2) % ht->size_) { ht->probelength_++; if (ht->table_[i]->key == key) { /* replace old entry */ assert(ht->table_[i]->value == NULL); ht->table_[i]->value = value; return; } } /* printf("insert: for key %d hash value is %i\n", key, i); */ ht->table_[i] = malloc(sizeof(struct hashtable2_node_struct)); ht->table_[i]->key = key; ht->table_[i]->value = value; return; } void set_value_null_hashtable2(hashtable2 ht, PTR_TYPE key) { unsigned long i; int h1, h2; assert(ht); assert(key); hash_2(ht, key); /* hash_2(ht, key, ht->a1_, ht->a2_); */ h1 = hash2_1(ht); h2 = hash2_2(ht); ht->probelength_ = 0; for (i = h1; ht->table_[i]; i = (i + h2) % ht->size_) { ht->probelength_++; if (ht->table_[i]->key == key) { /* delete entry */ ht->table_[i]->value = NULL; return; } } assert(0); return; } void * lookup_hashtable2(hashtable2 ht, PTR_TYPE key) { unsigned long i; int h1, h2; assert(ht); assert(key); hash_2(ht, key); /* hash_2(ht, key, ht->a1_, ht->a2_); */ h1 = hash2_1(ht); h2 = hash2_2(ht); ht->probelength_ = 0; for (i = h1; ht->table_[i]; i = (i + h2) % ht->size_) { ht->probelength_++; if (!(ht->table_[i])) return 0; else if (ht->table_[i] && ht->table_[i]->key == key) { return ht->table_[i]->value; } } return 0; } /* * unsigned int hash_2(hashtable2 ht, unsigned int key) { key *= 2654435761; * ht->h_ = key; return key; } */ /* * unsigned int hash_2(hashtable2 ht, unsigned int c, unsigned int a, * unsigned int b){ a=a-b; a=a-c; a=a^(c>>13); b=b-c; b=b-a; b=b^(a<<8); * c=c-a; c=c-b; c=c^(b>>13); a=a-b; a=a-c; a=a^(c>>12); b=b-c; b=b-a; * b=b^(a<<16); c=c-a; c=c-b; c=c^(b>>5); a=a-b; a=a-c; a=a^(c>>3); b=b-c; * b=b-a; b=b^(a<<10); c=c-a; c=c-b; c=c^(b>>15); ht->h_ = c; return c; } */