-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathHashMap.js
More file actions
146 lines (127 loc) · 4.17 KB
/
Copy pathHashMap.js
File metadata and controls
146 lines (127 loc) · 4.17 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
// HashMap.js
export default class HashMap {
constructor(initialCapacity = 16, loadFactor = 0.75) {
this.capacity = initialCapacity;
this.loadFactor = loadFactor;
// Creamos un arreglo con la capacidad inicial, donde cada espacio es un arreglo vacío (para manejar colisiones)
this.buckets = new Array(this.capacity).fill(null).map(() => []);
this.size = 0; // Para rastrear el número de claves almacenadas (length)
}
// Función Hash mejorada con el módulo dentro del bucle
hash(key) {
let hashCode = 0;
const primeNumber = 31;
for (let i = 0; i < key.length; i++) {
hashCode = (primeNumber * hashCode + key.charCodeAt(i)) % this.capacity;
}
return hashCode;
}
// Método auxiliar para evitar acceso fuera de los límites de la memoria
checkIndex(index) {
if (index < 0 || index >= this.buckets.length) {
throw new Error("Trying to access index out of bound");
}
}
// Guardar o actualizar un par clave-valor
set(key, value) {
const index = this.hash(key);
this.checkIndex(index);
const bucket = this.buckets[index];
// 1. Revisar si la clave ya existe para sobreescribir el valor
for (let i = 0; i < bucket.length; i++) {
if (bucket[i][0] === key) {
bucket[i][1] = value;
return; // Actualizado, no aumenta el tamaño
}
}
// 2. Si no existe, agregar al bucket (Manejo de colisión simple)
bucket.push([key, value]);
this.size++;
// 3. Verificar si superamos el Load Factor para redimensionar (Grow)
if (this.size > this.capacity * this.loadFactor) {
this.resize();
}
}
// Duplicar la capacidad y reubicar todos los elementos
resize() {
const oldBuckets = this.buckets;
this.capacity *= 2; // Duplicamos capacidad
this.buckets = new Array(this.capacity).fill(null).map(() => []);
this.size = 0;
// Recalcular los hashes para reasignar a los nuevos buckets
for (const bucket of oldBuckets) {
for (const [key, value] of bucket) {
this.set(key, value);
}
}
}
// Obtener el valor asociado a una clave
get(key) {
const index = this.hash(key);
this.checkIndex(index);
const bucket = this.buckets[index];
for (let i = 0; i < bucket.length; i++) {
if (bucket[i][0] === key) {
return bucket[i][1];
}
}
return null; // Si no lo encuentra
}
// Verificar si la clave existe
has(key) {
return this.get(key) !== null;
}
// Eliminar una clave
remove(key) {
const index = this.hash(key);
this.checkIndex(index);
const bucket = this.buckets[index];
for (let i = 0; i < bucket.length; i++) {
if (bucket[i][0] === key) {
bucket.splice(i, 1); // Remover del array
this.size--;
return true;
}
}
return false;
}
// Retornar número de claves almacenadas
length() {
return this.size;
}
// Vaciar completamente el HashMap
clear() {
this.buckets = new Array(this.capacity).fill(null).map(() => []);
this.size = 0;
}
// Retornar arreglo con todas las claves
keys() {
const allKeys = [];
for (const bucket of this.buckets) {
for (const [key] of bucket) {
allKeys.push(key);
}
}
return allKeys;
}
// Retornar arreglo con todos los valores
values() {
const allValues = [];
for (const bucket of this.buckets) {
for (const [, value] of bucket) {
allValues.push(value);
}
}
return allValues;
}
// Retornar arreglo con todos los pares clave-valor
entries() {
const allEntries = [];
for (const bucket of this.buckets) {
for (const entry of bucket) {
allEntries.push(entry);
}
}
return allEntries;
}
}