rename dir
This commit is contained in:
@@ -0,0 +1,186 @@
|
||||
#include "stdio.h"
|
||||
#include "stdlib.h"
|
||||
#include "string.h"
|
||||
#include "time.h"
|
||||
|
||||
#define DEFAULT_MAP_SIZE 1<<5
|
||||
#define MAX_MAP_SIZE 1<<30
|
||||
#define CAPACITY_FACTOR 0.6f
|
||||
#define MAX_KEY_LENGTH 1<<3
|
||||
|
||||
typedef unsigned int Hash;
|
||||
typedef char* Key;
|
||||
typedef int Value;
|
||||
typedef struct Entry{
|
||||
struct Entry *next;
|
||||
Hash hash;
|
||||
Value value;
|
||||
Key key;
|
||||
}Entry;
|
||||
|
||||
typedef struct HashMap{
|
||||
Entry** heads;
|
||||
Value nul;
|
||||
unsigned int size;
|
||||
unsigned int usage;
|
||||
unsigned int realCapacity; //size * CAPACITY_FACTOR
|
||||
unsigned int sizeForIndex; //size - 1
|
||||
}HashMap;
|
||||
|
||||
HashMap* create(unsigned int);
|
||||
HashMap* transfer(HashMap*, HashMap*);
|
||||
Hash hash(char[]);
|
||||
HashMap* put(HashMap*, Key, Value);
|
||||
HashMap* putInHeads(HashMap*, int, Hash, Key, Value);
|
||||
HashMap* putInList(HashMap*, int, Hash, Key, Value);
|
||||
HashMap* resize(HashMap*);
|
||||
int find(char[]);
|
||||
void print(HashMap*);
|
||||
|
||||
HashMap* create(unsigned int size){
|
||||
HashMap* hashMap = malloc(sizeof(HashMap));
|
||||
int i;
|
||||
hashMap->size = size;
|
||||
hashMap->sizeForIndex = size - 1;
|
||||
hashMap->realCapacity = (unsigned int)(size * CAPACITY_FACTOR);
|
||||
hashMap->usage = 0;
|
||||
hashMap->heads = calloc(size, sizeof(Entry*));
|
||||
hashMap->nul = 0;
|
||||
return hashMap;
|
||||
}
|
||||
|
||||
HashMap* transfer(HashMap* newHashMap, HashMap* oldHashMap){
|
||||
unsigned int oldIndex, newIndex;
|
||||
Entry *oldEntry, *oldNextEntry;
|
||||
for (oldIndex = 0; oldIndex < oldHashMap->size; oldIndex++){
|
||||
if (oldHashMap->heads[oldIndex] != NULL){
|
||||
oldEntry = oldHashMap->heads[oldIndex];
|
||||
do{
|
||||
newIndex = (oldEntry->hash) & (newHashMap->sizeForIndex);
|
||||
oldNextEntry = oldEntry->next;
|
||||
oldEntry->next = newHashMap->heads[newIndex];
|
||||
newHashMap->heads[newIndex] = oldEntry;
|
||||
oldEntry = oldNextEntry;
|
||||
} while (oldEntry != NULL);
|
||||
}
|
||||
}
|
||||
newHashMap->usage = oldHashMap->usage;
|
||||
newHashMap->nul = oldHashMap->nul;
|
||||
free(oldHashMap->heads);
|
||||
oldHashMap->heads = NULL;
|
||||
free(oldHashMap);
|
||||
oldHashMap = NULL;
|
||||
return newHashMap;
|
||||
}
|
||||
|
||||
Hash hashCode(char* key){
|
||||
int offset = 5;
|
||||
Hash hashCode = 0;
|
||||
while (*key) hashCode = (hashCode << offset) + (*key++);
|
||||
return hashCode;
|
||||
}
|
||||
|
||||
HashMap* put(HashMap* hashMap, Key key, Value value){
|
||||
if (key == NULL){
|
||||
hashMap->nul = value;
|
||||
return hashMap;
|
||||
}
|
||||
Hash hash = hashCode(key);
|
||||
int index = hash & (hashMap->sizeForIndex);
|
||||
|
||||
if (hashMap->heads[index] == NULL){
|
||||
return putInHeads(hashMap, index, hash, key, value);
|
||||
} else {
|
||||
return putInList(hashMap, index, hash, key, value);
|
||||
}
|
||||
}
|
||||
|
||||
HashMap* putInHeads(HashMap* hashMap, int index, Hash hash, Key key, Value value){
|
||||
Entry* newHead = malloc(sizeof(Entry));
|
||||
newHead->hash = hash;
|
||||
newHead->key = _strdup(key);
|
||||
newHead->value = value;
|
||||
newHead->next = NULL;
|
||||
hashMap->heads[index] = newHead;
|
||||
(hashMap->usage)++;
|
||||
if (hashMap->usage > hashMap->realCapacity) return resize(hashMap);
|
||||
return hashMap;
|
||||
}
|
||||
HashMap* putInList(HashMap* hashMap, int index, Hash hash, Key key, Value value){
|
||||
Entry* lastEntry = hashMap->heads[index];
|
||||
while (lastEntry != NULL){
|
||||
if (lastEntry->hash == hash){
|
||||
lastEntry->value += value;
|
||||
return hashMap;
|
||||
}
|
||||
else lastEntry = lastEntry->next;
|
||||
}
|
||||
lastEntry = malloc(sizeof(Entry));
|
||||
lastEntry->hash = hash;
|
||||
lastEntry->key = _strdup(key);
|
||||
lastEntry->value = value;
|
||||
lastEntry->next = hashMap->heads[index];
|
||||
hashMap->heads[index] = lastEntry;
|
||||
(hashMap->usage)++;
|
||||
if (hashMap->usage > hashMap->realCapacity) return resize(hashMap);
|
||||
return hashMap;
|
||||
}
|
||||
|
||||
HashMap* resize(HashMap* hashMap){
|
||||
HashMap* newHashMap;
|
||||
if ((hashMap->size << 1) <= MAX_MAP_SIZE) {
|
||||
newHashMap = create((hashMap->size << 1));
|
||||
newHashMap = transfer(newHashMap, hashMap);
|
||||
return newHashMap;
|
||||
}
|
||||
return hashMap;
|
||||
}
|
||||
|
||||
Value get(HashMap* hashMap, Key key){
|
||||
Hash hash = hashCode(key);
|
||||
int index = hash & (hashMap->sizeForIndex);
|
||||
Entry* entry = hashMap->heads[index];
|
||||
while (entry != NULL){
|
||||
if (entry->hash == hash) return entry->value;
|
||||
entry = entry->next;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void print(HashMap* hashMap){
|
||||
unsigned int i;
|
||||
Entry* entry;
|
||||
for (i = 0; i < hashMap->size; i++){
|
||||
entry = hashMap->heads[i];
|
||||
while (entry != NULL){
|
||||
printf("%s: %d\n", entry->key, entry->value);
|
||||
entry = entry->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int main(){
|
||||
clock_t start, end;
|
||||
HashMap* hashMap = create(DEFAULT_MAP_SIZE);
|
||||
FILE* fp;
|
||||
char filePath[0xFF];
|
||||
char line[5];
|
||||
char key[MAX_KEY_LENGTH];
|
||||
|
||||
printf("input file path: ");
|
||||
scanf_s("%s", filePath, 0xFF);
|
||||
if (fopen_s(&fp, filePath, "r") == 0){
|
||||
start = clock();
|
||||
while (fgets(line, 5, fp) != NULL){
|
||||
line[3] = '\0';
|
||||
hashMap = put(hashMap, line, 1);
|
||||
}
|
||||
end = clock();
|
||||
printf("\n%fs", (float)(end - start)/1000);
|
||||
fclose(fp);
|
||||
print(hashMap);
|
||||
} else {
|
||||
printf("can't open file");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user