mahlendur/_work/Data/Scripts/Content/LeGo/_Hashtable.d
Daniel Heße 96b7bfd52d Fixed some bugs, did some testing.
Everything should be working by now, up until final battle (still needs testing).

Updated LeGo to 2.8.0
2022-10-03 18:16:51 +02:00

177 lines
No EOL
4.5 KiB
D

// Eine Hashtable ist eigentlich bloß zCArray<zCArray<_HT_Obj>*>, also ein zweidimensionales Array.
class _HT_Obj {
var int key;
var int val;
};
const int HT_SIZE = 71; // Primzahl
func int _HT_CreatePtr(var int size) {
var int ptr; ptr = MEM_ArrayCreate();
var zCArray arr; arr = _^(ptr);
arr.array = MEM_Alloc(size*4);
arr.numAlloc = size*4;
arr.numInArray = 0;
return +ptr;
};
func int _HT_Create() {
return +_HT_CreatePtr(HT_SIZE);
};
func int hash(var int val) {
var int hash; hash = MEM_GetBufferCRC32(_@(val), 4);
return hash & 2147483647; // No negative values
};
func void _HT_Insert(var int ptr, var int val, var int key) {
var zCArray arr; arr = _^(ptr);
var int h; h = hash(key) % (arr.numAlloc/4);
var int bucket; bucket = MEM_ReadIntArray(arr.array, h);
if (!bucket) {
MEM_WriteIntArray(arr.array, h, MEM_ArrayCreate());
bucket = MEM_ReadIntArray(arr.array, h);
};
/* Check whether an entry with the same key already exists */
var zCArray buck; buck = _^(bucket);
var int i;
repeat(i, buck.numInArray/2);
if (MEM_ArrayRead(bucket, i*2) == key) {
MEM_Error("HT: A key has been assigned with two values!");
};
end;
MEM_ArrayInsert(bucket, key);
MEM_ArrayInsert(bucket, val);
arr.numInArray += 1;
/* resize if needed */
if (arr.numInArray == arr.numAlloc) {
var int am; am = arr.numInArray*2;
ptr;
am;
MEM_Call(_HT_Resize);
};
};
func void _HT_Resize(var int ptr, var int size) {
var zCArray arr; arr = _^(ptr); var zCArray buck;
var int htbl; htbl = _HT_CreatePtr(size); var zCArray hArr; hArr = _^(htbl);
var int i; var int j; var int bucket; i = 0; j = 0;
repeat(i, arr.numAlloc/4);
bucket = MEM_ReadIntArray(arr.array, i);
if (bucket) {
buck = _^(bucket);
repeat(j, buck.numInArray/2);
_HT_Insert(htbl, MEM_ReadIntArray(buck.array, 2*j+1), MEM_ReadIntArray(buck.array, 2*j));
end;
MEM_Free(bucket);
};
end;
MEM_Free(arr.array);
arr.array = hArr.array;
arr.numAlloc = size*4;
arr.numInArray = hArr.numInArray;
};
func int _HT_Get(var int ptr, var int key) {
var zCArray arr; arr = _^(ptr);
var int h; h = hash(key) % (arr.numAlloc/4);
var int bucket; bucket = MEM_ReadIntArray(arr.array, h);
if (!bucket) { return false; };
var zCArray buck; buck = _^(bucket);
var int i;
repeat(i, buck.numInArray/2);
if (MEM_ArrayRead(bucket, i*2) == key) {
return (MEM_ArrayRead(bucket, i*2+1));
};
end;
return false;
};
func int _HT_Has(var int ptr, var int key) {
var zCArray arr; arr = _^(ptr);
var int h; h = hash(key) % (arr.numAlloc/4);
var int bucket; bucket = MEM_ReadIntArray(arr.array, h);
if (!bucket) { return false; };
var zCArray buck; buck = _^(bucket);
var int i;
repeat(i, buck.numInArray/2);
if (MEM_ArrayRead(bucket, i*2) == key) {
return true;
};
end;
return false;
};
func void _HT_Remove(var int ptr, var int key) {
var zCArray arr; arr = _^(ptr);
var int h; h = hash(key) % (arr.numAlloc/4);
var int bucket; bucket = MEM_ReadIntArray(arr.array, h);
if (!bucket) { MEM_Error("HT: Key not found"); return; };
var zCArray buck; buck = _^(bucket);
var int i;
repeat(i, buck.numInArray/2);
if (MEM_ArrayRead(bucket, i*2) == key) {
MEM_ArrayRemoveIndex(bucket, i*2+1);
MEM_ArrayRemoveIndex(bucket, i*2);
arr.numInArray -= 1;
return;
};
end;
MEM_Error("HT: Key not found");
};
func void _HT_Change(var int ptr, var int val, var int key) {
/* A very lazy implementation but I doubt this will be used much */
_HT_Remove(ptr, key);
_HT_Insert(ptr, val, key);
};
func void _HT_InsertOrChange(var int ptr, var int val, var int key) {
if (_HT_Has(ptr, key)) {
_HT_Change(ptr, val, key);
} else {
_HT_Insert(ptr, val, key);
};
};
func int _HT_GetNumber(var int ptr) {
var zCArray arr; arr = _^(ptr);
return arr.numInArray;
};
func void _HT_ForEach(var int ptr, var func fnc) { // fnc(int key, int val)
var zCArray arr; arr = _^(ptr); var zCArray buck;
var int i; var int j; var int bucket; i = 0; j = 0;
repeat(i, arr.numAlloc/4);
bucket = MEM_ReadIntArray(arr.array, i);
if (bucket) {
buck = _^(bucket);
repeat(j, buck.numInArray/2);
MEM_ReadIntArray(buck.array, j*2 );
MEM_ReadIntArray(buck.array, j*2+1);
MEM_Call(fnc);
end;
};
end;
};
func void _HT_Destroy(var int ptr) {
var zCArray arr; arr = _^(ptr); var zCArray buck;
var int i; var int j; var int bucket; i = 0; j = 0;
repeat(i, arr.numAlloc/4);
bucket = MEM_ReadIntArray(arr.array, i);
if (bucket) {
MEM_ArrayFree(bucket);
};
end;
MEM_Free(arr.array);
MEM_Free(ptr);
};