Hajautustaulukon ideana on, että sinulla on "avainarvo", jonka perusteella voit kaivaa hajautustaulukosta toisen avainarvoon liitetyn arvon. Hajautustaulukko ei ole lineaarinen tietosäiliö, kuten CB Kokoelmat. Hajautustaulukko näin nopea: sinun ei koskaan tarvitse käydä kaikkia 10000 enityäsi läpi, jotta saisit tavaran "miekka" ominaisuudet. (esim. power, defence, tyypi jne.) Yksi kutsu cbHashTbl_Access() funktioon riittää. Sen aika vaativuus on pyöreästi vakio. Hajautustaulukolla on yksi rajoite: taulukon koko pitäisi tuntea etukäteen ja sen uudelleen venyttäminen on erittäin raskasta. Tarkempi selostus löytyy wikipediasta.
Kirjastosta puuttuu oikeastaan enää yksi kriittinen ominaisuus ja se on hajautustaulukon uudelleen venyttäminen - mutta koska se on mahdollista tehdä jo kirjaston nykyisillä funktioilla, jukaisen kirjaston jo nyt. Selvittäkää bugeja, mahdollisia koodausvirheitä, parannuksia ja - kommentoikaa.
Ominaisuuksia:
-Kirjasto käyttää pelkästään muistipaloja, jonka ansiosta voit luoda hajautustaulukkoja loputtomasti ja tunkea sellaisen vaikka typeen tai välittää funktiolle.
-cbHashTbl omistaa sisältämänsä datan, joten sinun ei tarvitse pitää käyttämiäsi muistipaloja tallessa.
-cbHashTbl tukee vakio mittaisia merkkijonoavaimia ja dataa.
-Hautustaulukon sisältö voidaan läpikäydä tarvittaessa avain ja elementti kerrallaan.
-Hajautustaulukko sallii useat identtiset avaimet, mikäli g_MultiElementMode on asetettu todeksi.
Tässä Include "cbHashTable.cb" :
Code: Select all
// cbHashTable - nopea hajautustaulukko CoolBasic:lle. (C) JATothrim 2010.
SCREEN 800,600
Dim cbHashTbl_PrimeTbl(28) // prime table For hash Function(s)
cbHashTbl_PrimeTbl(0) = 5
cbHashTbl_PrimeTbl(1) = 13
cbHashTbl_PrimeTbl(2) = 23
cbHashTbl_PrimeTbl(3) = 47
cbHashTbl_PrimeTbl(4) = 97
cbHashTbl_PrimeTbl(5) = 193
cbHashTbl_PrimeTbl(6) = 389
cbHashTbl_PrimeTbl(7) = 769
cbHashTbl_PrimeTbl(8) = 1543
cbHashTbl_PrimeTbl(9) = 3079
cbHashTbl_PrimeTbl(10) = 6151
cbHashTbl_PrimeTbl(11) = 12289
cbHashTbl_PrimeTbl(12) = 24593
cbHashTbl_PrimeTbl(13) = 49157
cbHashTbl_PrimeTbl(14) = 98317
cbHashTbl_PrimeTbl(15) = 196613
cbHashTbl_PrimeTbl(16) = 393241
cbHashTbl_PrimeTbl(17) = 786433
cbHashTbl_PrimeTbl(18) = 1572869
cbHashTbl_PrimeTbl(19) = 3145739
cbHashTbl_PrimeTbl(20) = 6291469
cbHashTbl_PrimeTbl(21) = 12582917
cbHashTbl_PrimeTbl(22) = 25165843
cbHashTbl_PrimeTbl(23) = 50331653
cbHashTbl_PrimeTbl(24) = 100663319
cbHashTbl_PrimeTbl(25) = 201326611
cbHashTbl_PrimeTbl(26) = 402653189
cbHashTbl_PrimeTbl(27) = 805306457
cbHashTbl_PrimeTbl(28) = 1610612741
Global g_HashTblMem As integer //Memblock
Global g_MultiElementMode As Byte //True/False
Global g_HashTblBucketExists As Byte//Flag. If false after cbHashTbl_Insert(), new bucket were created.
g_HashTblMem = 0
g_MultiElementMode = False //use cbHashTbl As HashSet(unique keys) Or HashMultiSet(non-unique keys)
// Public utility functions
// Modified CRC32 hash.
Function DoCRC32_Hash(memblock, prime)
Dim a
a = Crc32(memblock)
If a < 0 Then a = a - (1 Shl 31)
Return a Mod prime
EndFunction
Function FindNearestPrime(size As integer)
Dim i
For i = 0 To 28
If cbHashTbl_PrimeTbl(i) > size Then Return cbHashTbl_PrimeTbl(i)
Next i
EndFunction
// Creates new "key" memblock for hashtable with text.
Function NewStringKey(hstbl, txt$, empty$ = " ")
Dim keymem, i, sz
sz = PeekInt(hstbl, SCTbl_KeySize)
keymem = MakeMEMBlock(sz)
StringValue(keymem, txt, empty)
Return keymem
EndFunction
// Creates new "element" memblock for hashtable with text.
Function NewStringElement(hstbl, txt$, empty$ = " ")
Dim elementmem, i, sz
sz = PeekInt(hstbl, SCTbl_ElementSize)
elementmem = MakeMEMBlock(sz)
StringValue(elementmem, txt, empty)
Return elementmem
EndFunction
// Writes string to memblock
Function StringValue(keymem, txt$, empty$ = " ")
Dim i, sz
sz = MEMBlockSize(keymem)
For i = 0 To sz-1
If i < Len(txt)
PokeByte keymem, i, Asc(Mid(txt, i+1, 1))
Else
PokeByte keymem, i, Asc(empty)
EndIf
Next i
Return keymem
EndFunction
// Reads string from memblock
Function GetStringValue(memblock)
Dim i, sz, txt As String
sz = MEMBlockSize(memblock)
For i = 0 To sz-1
txt = txt + Chr(PeekByte(memblock, i))
Next i
Return txt
EndFunction
// Read string-element from offset. Use only if g_HashTblMem is non-zero.
Function GetStringElement$(hstbl, offset)
Dim i, sz
Dim txt As String
sz = PeekInt(hstbl, SCTbl_ElementSize)
For i = 0 To sz-1
txt = txt + Chr(PeekByte(g_HashTblMem, offset + i))
Next i
Return txt
EndFunction
// Read string-key from offset. Use only if g_HashTblMem is non-zero.
Function GetStringKey$(hstbl, offset)
Dim i, sz
Dim txt As String
sz = PeekInt(hstbl, SCTbl_KeySize)
For i = 0 To sz-1
txt = txt + Chr(PeekByte(g_HashTblMem, offset + i))
Next i
Return txt
EndFunction
// SeekConst(s) for
Const SCTbl_Elements = 0 'Elements in hashtable
Const SCTbl_TableSize = 4 'Allocated table size
Const SCTbl_KeySize = 8 'size of key
Const SCTbl_ElementSize = 12 'size of Element
Const SCTbl_UsedBuckets = 16 'Amount of buckets in use
Const SCTbl_BucketAlloc = 20 'count of slots in bucket, when allocated Or resized.
Const SCTbl_FirstBucket = 24
// Create new hash table.
// Param: [buckets_init] - max buckets in hashtable
// Param: [key_size] - size of the key, in bytes.
// Param: [element_size] - size of invidual element to store, in bytes.
// Param: [initial_bucketsz] - see [SCTbl_BucketAlloc] const.
// Returns: New initialized memblock for cbHashTable.
Function CreateHashTable(buckets_init, key_size, element_size, initial_bucketsz = 5)
Dim hstbl
buckets_init = FindNearestPrime(buckets_init)
hstbl = MakeMEMBlock(SCTbl_FirstBucket + buckets_init*4)
PokeInt hstbl, SCTbl_TableSize, buckets_init
PokeInt hstbl, SCTbl_ElementSize, element_size
PokeInt hstbl, SCTbl_KeySize, key_size
PokeInt hstbl, SCTbl_BucketAlloc, initial_bucketsz
Return hstbl
EndFunction
// Checks if bucket allredy contains the key.
// [For library internal use]
Function cbHashTbl_CheckDuplicate(bucket, keymem, keysz, elementsz, sz = -1, startindex = 0)
Dim i, check, checkmem
If sz = -1 Then sz = PeekInt(bucket, 0)
check = Crc32(keymem)
checkmem = MakeMEMBlock(keysz)
For i = startindex To sz-1
MemCopy bucket, i*(keysz+elementsz) + 4, checkmem, 0, keysz
If Crc32(checkmem) = check
If cbHashTbl_KeyCMP(bucket, keymem, i, keysz, elementsz)
DeleteMEMBlock checkmem
Return i
EndIf
EndIf
Next i
DeleteMEMBlock checkmem
Return -1
EndFunction
//Byte-to-byte key compare.
// [For library internal use]
Function cbHashTbl_KeyCMP(bucket, keymem, index, keysz, elementsz)
Dim i
For i = 0 To keysz-1
If PeekByte(keymem, i) <> PeekByte(bucket, 4 + index * (keysz+elementsz) + i) Then Return False
Next i
Return True
EndFunction
//Insert element to hashtable.
// Gets: [g_MultiElementMode] - allow collisions?
// Param: [hstbl] - hashtable
// Param: [keymem] - memblock to key value (data is copied into hashtable.)
// Param: [elementmem] - memblock to element (data is copied into hashtable.)
// Sets: [g_HashTblBucketExists] - true if inserting to old bucket.
// Returns: True on success.
Function cbHashTbl_Insert(hstbl, keymem, elementmem)
Dim index, bucket, sz, elementsz, keysz, i, check, checkmem
index = DoCRC32_Hash(keymem, PeekInt(hstbl, SCTbl_TableSize)) * 4 + SCTbl_FirstBucket
bucket = PeekInt(hstbl, index)
elementsz = PeekInt(hstbl, SCTbl_ElementSize)
keysz = PeekInt(hstbl, SCTbl_KeySize)
If bucket <> 0
g_HashTblBucketExists = True
sz = PeekInt(bucket, 0)
If g_MultiElementMode = False And sz > 0
If cbHashTbl_CheckDuplicate(bucket, keymem, keysz, elementsz, sz) > -1 Then Return False
EndIf
If (keysz+elementsz) * (sz+1) + 4 > MEMBlockSize(bucket)
ResizeMEMBlock bucket, (sz + PeekInt(hstbl, SCTbl_BucketAlloc)) * (keysz + elementsz) + 4
EndIf
Else
g_HashTblBucketExists = False
bucket = MakeMEMBlock(4+(elementsz+keysz) * PeekInt(hstbl, SCTbl_BucketAlloc))
PokeInt hstbl, SCTbl_UsedBuckets, PeekInt(hstbl, SCTbl_UsedBuckets) + 1
PokeInt hstbl, index, bucket
EndIf
MemCopy keymem, 0, bucket, 4 + sz * (keysz + elementsz), keysz
MemCopy elementmem, 0, bucket, 4 + sz * (keysz + elementsz) + keysz, elementsz
PokeInt bucket, SCTbl_Elements, sz + 1
Return True
EndFunction
//Read single element from hashtable.
// Param: [hstbl] - hashtable
// Param: [keymem] - memblock to key value
// Sets: [g_HashTblMem] - Memblock to where element is currently stored.
// If hashtable can't find the element mapped to [keymem], g_HashTblMem is set to zero.
// Returns: Offset to first element in g_HashTblMem. If [g_MultiElementMode] mode is enabled
// returned value is 0 eg. DOES NOT point to any element: Use
// cbHashTbl_NextBckElement() To get the elements. Return value is undefined
// if Sets:[g_HashTblMem] does not contain memblock.
Function cbHashTbl_Access(hstbl, keymem)
Dim vbucket, sz, keysz, elementsz, index
vbucket = DoCRC32_Hash(keymem, PeekInt(hstbl, SCTbl_TableSize)) * 4 + SCTbl_FirstBucket
g_HashTblMem = PeekInt(hstbl, vbucket)
If g_HashTblMem <> 0
sz = PeekInt(g_HashTblMem, 0)
If sz > 0
keysz = PeekInt(hstbl, SCTbl_KeySize)
elementsz = PeekInt(hstbl, SCTbl_ElementSize)
index = cbHashTbl_CheckDuplicate(g_HashTblMem, keymem, keysz, elementsz, sz)
If index <> -1
If g_MultiElementMode = True Then Return 0
Return index * (keysz+elementsz) + keysz + 4
Else
g_HashTblMem = 0
EndIf
Else
g_HashTblMem = 0
EndIf
EndIf
If g_MultiElementMode = True Then Return 0
EndFunction
// Iterate throught single bucket of elements, [g_MultiElementMode] only operation.
// Param: [hstbl] - hashtable.
// Param: [offset] - Zero: get first element. Variable: get next element.
// Returns: Offset for [g_HashTblMem] or Zero if there is no more elements mapped to key.
Function cbHashTbl_NextBck(hstbl, keymem, offset)
Dim keysz, elementsz
keysz = PeekInt(hstbl, SCTbl_KeySize)
elementsz = PeekInt(hstbl, SCTbl_ElementSize)
If offset = 0
offset = cbHashTbl_CheckDuplicate(g_HashTblMem, keymem, keysz, elementsz, -1, 0)
If offset = -1 Then Return 0 Else Return offset * (keysz + elementsz) + keysz + 4
Else
offset = (offset-4) / (keysz + elementsz)
offset = cbHashTbl_CheckDuplicate(g_HashTblMem, keymem, keysz, elementsz, -1, offset+1)
If offset = -1 Then Return 0
Return offset * (keysz + elementsz) + keysz + 4
EndIf
EndFunction
// Start to iterate thought the Hashtable. Iterated keys are read only, so if you overwrite
// a key throught the iterator the cbHashTbl may break completly.
// Param: [hstbl] - hashtable.
// Param: [itermem] - (optional) old iterator memblock to initate.
// Param: [mode] - (optional) iterate keys:0 or elements:1?
// Returns: iterator memblock or zero if hashtable is empty.
Function cbHashTbl_IterateBegin(hstbl, itermem = 0, mode = 1)
Dim i, keysz
If itermem = 0 Then itermem = MakeMEMBlock(16)
keysz = PeekInt(hstbl, SCTbl_KeySize)
PokeInt itermem, 0, hstbl
PokeInt itermem, 4, -1
PokeInt itermem, 8, 0
PokeInt itermem, 12, keysz*(mode = 1)
Return itermem
EndFunction
// Get next element/key in the Hashtable. Note: to read both key and mapped element iterate first
// to key and then to element.
// Param: [itermem] - iterator memblock.
// Param: [mode] - (default is elements) iterate keys:0 or elements:1
// Returns: true if got valid element and false if all elements have been
// iterated.
Function cbHashTbl_Next(itermem, mode = 1)
Dim i, hstbl, bucket, readpos, sz, keysz, index, bckind, tblsz
hstbl = PeekInt(itermem, 0) //get iterated hashtbl
bckind = PeekInt(itermem, 4)
index = PeekInt(itermem, 8) //get current element
readpos = PeekInt(itermem, 12) //get offset setting (was Last Read element Or key?)
If bckind > -1
bucket = PeekInt(hstbl, SCTbl_FirstBucket + bckind * 4) //get current bucket
sz = PeekInt(bucket, 0) //get bucket size
EndIf
keysz = PeekInt(hstbl, SCTbl_KeySize)
If readpos = 0 And mode = 1 And bckind <> -1
PokeInt itermem, 12, keysz
ElseIf sz <= index+1 Or bckind = -1
// move To Next bucket.
tblsz = PeekInt(hstbl, SCTbl_TableSize)
For i = bckind+1 To tblsz
bucket = PeekInt(hstbl, SCTbl_FirstBucket + i * 4)
If bucket <> 0
If PeekInt(bucket, 0) > 0
PokeInt itermem, 4, i
PokeInt itermem, 8, 0
PokeInt itermem, 12, keysz*(mode = 1)
Return True
EndIf
EndIf
Next i
Return False
Else
PokeInt itermem, 8, index + 1
PokeInt itermem, 12, keysz*(mode = 1)
Return True
EndIf
EndFunction
// Get Memblock of the Iterator
// Param: [itermem] - iterator memblock.
// Returns: Memblock.
Function cbHashTbl_IterMem(itermem)
Dim hstbl
hstbl = PeekInt(itermem, 0)
Return PeekInt(hstbl, SCTbl_FirstBucket + PeekInt(itermem, 4) * 4)
EndFunction
// Get offset in current iterator memblock for eg. PeekInt.
// Param: [itermem] - iterator memblock.
// Param: [userpadd] - add userpadd to base offset.
// Returns: calculated offset for cbHashTbl_IterMem() returned memblock.
Function cbHashTbl_Offset(itermem, userpadd = 0)
Dim hstbl, keysz, elementsz, index, padd
hstbl = PeekInt(itermem, 0)
keysz = PeekInt(hstbl, SCTbl_KeySize)
elementsz = PeekInt(hstbl, SCTbl_ElementSize)
index = PeekInt(itermem, 8)
padd = PeekInt(itermem, 12) + userpadd
Return 4 + padd + (keysz+elementsz)*index
EndFunction
// Read data at iterator location.
// Param: [itermem] - iterator memblock.
// Param: [usermem] - memblock to where write data. If zero, data
// is read as one int:0, float:1, short:2 or byte:4.
// Memblock must be big enough to store pointed key nor element.
// Param: [valuetype] - type of data to read, ignored if usermem is non-zero.
Function cbHashTbl_Read(itermem, usermem, valuetype = -1)
EndFunction
//Delete element from hashtable. Note: this function may free the bucket memblock
// if bucket elements are reduced to zero.
// Param: [hstbl] - hashtable
// Param: [keymem] - memblock to key value
// Param: [delmode] - (0): remove first matching element.
// - (1): remove all elements mapped to key.
// - (2): delete the [bucket] where the keymem maps
// Returns: number of element deleted.
Function cbHashTbl_Delete(hstbl, keymem, delmode = 0)
Dim index, bucket, sz, elementsz, keysz, i, pos, removed
index = DoCRC32_Hash(keymem, PeekInt(hstbl, SCTbl_TableSize)) * 4 + SCTbl_FirstBucket
bucket = PeekInt(hstbl, index)
If bucket <> 0
sz = PeekInt(bucket, 0)
elementsz = PeekInt(hstbl, SCTbl_ElementSize)
keysz = PeekInt(hstbl, SCTbl_KeySize)
If delmode = 2 Or sz = 1
DeleteMEMBlock bucket
PokeInt hstbl, index, 0
PokeInt hstbl, SCTbl_UsedBuckets, PeekInt(hstbl, SCTbl_UsedBuckets)-1
removed = sz
ElseIf delmode = 0
i = cbHashTbl_CheckDuplicate(bucket, keymem, keysz, elementsz, sz)
If i <> -1
// perform Delete
If i < sz-1 And sz > 0
pos = i*(elementsz+keysz) + 4
MemCopy bucket, pos + (elementsz+keysz), bucket, pos, (sz-i) * (elementsz+keysz)
EndIf
PokeInt bucket, 0, sz-1
removed = 1
EndIf
ElseIf delmode = 1
Repeat
i = cbHashTbl_CheckDuplicate(bucket, keymem, keysz, elementsz, sz)
If i <> -1
g_HashTblMem = bucket
// perform Delete
If i < sz-1 And sz > 0
pos = i*(elementsz+keysz) + 4
MemCopy bucket, pos + (elementsz+keysz), bucket, pos, (sz-i) * (elementsz+keysz)
EndIf
sz = sz - 1
removed = removed + 1
Else
Exit
EndIf
Forever
PokeInt bucket, 0, sz
EndIf
EndIf
PokeInt hstbl, SCTbl_Elements, PeekInt(hstbl, SCTbl_Elements)-removed
Return removed
EndFunction
// Resizes hashtable.
// Param: [hstbl] - hashtable
// Param: [newsize] - new size of the hashtable
// Returns: Resized hashtable, old is destroyed.
Function cbHashTbl_Resize(hstbl, newsize)
EndFunction
// Copies hashtable A contents into HashTable B.
// Param: [hstblA] - source hashtable
// Param: [hstblB] - destination hashtable
// Param: [keymem] - (optional) if provided, moves only one element.
// Param: [rpl] - replace hstblB contents if key is not unique in hstblB.
Function cbHashTbl_Copy(hstblA, hstblB, keymem = 0, rpl = 1)
EndFunction
// Removes all hashtable elements
// Param: [hstbl] - hashtable
// Param: [freebuckets] - if true, free allocated memory, don't recycle.
Function cbHashTbl_Flush(hstbl, freebuckets = 1)
EndFunction
Code: Select all
//(C) JATothrim 2010.
Const keylen = 10
Dim hstbl, key, element, i, j, z, x, y, fbck, ticks, vkey
Dim msgresult(1) As String
msgresult(1) = "Ok."
msgresult(0) = "Fail."
hstbl = CreateHashTable(50, keylen, 20)
key = NewStringKey(hstbl, "xyzq")
element = NewStringElement(hstbl, "test_element","-")
'g_MultiElementMode = True
//###########################################################
//# cbHashTbl_Insert() testing. #
//###########################################################
For i = 0 To 100
StringValue(key, Str(vkey),"_")
StringValue(element, "test_element "+Str(vkey),"-")
vkey = vkey + Rand(4) '1/4 of insertions will fail.
z = cbHashTbl_Insert(hstbl, key, element)
Print "Insert: "+msgresult(z)
Next i
WaitKey:Cls:Locate 0,0
StringValue(key, "xyz1")
StringValue(element, "one")
Print "Insert "+Chr(34)+"xyz1"+Chr(34)+" "+msgresult(cbHashTbl_Insert(hstbl, key, element))
StringValue(key, "xyz2")
StringValue(element, "two two")
Print "Insert "+Chr(34)+"xyz2"+Chr(34)+" "+msgresult(cbHashTbl_Insert(hstbl, key, element))
StringValue(key, "xyz3")
StringValue(element, "three three three")
Print "Insert "+Chr(34)+"xyz3"+Chr(34)+" "+msgresult(cbHashTbl_Insert(hstbl, key, element))
// "a1sellers" and "advertees" have same crc32 hash. (so later will pass 2/3 of the unique insertion checks)
StringValue(key, "a1sellers")
StringValue(element, "this ok")
z = cbHashTbl_Insert(hstbl, key, element)
Print "Insert "+Chr(34)+"a1sellers"+Chr(34)+" "+msgresult(z)
StringValue(key, "advertees")
StringValue(element, "this not so ok")
z = cbHashTbl_Insert(hstbl, key, element)
Print "Insert "+Chr(34)+"advertees"+Chr(34)+" "+msgresult(z)
//###########################################################
//# cbHashTbl_Access() testing. #
//###########################################################
Dim offset
If g_MultiElementMode
// Insert multiple elements To cbHashtbl And iterate them all. (but Not the Crc32 collied ones!)
StringValue(key, "advertees")
StringValue(element, "jeba!")
cbHashTbl_Insert(hstbl, key, element):Print " "
StringValue(element, "moar!")
cbHashTbl_Insert(hstbl, key, element):Print " "
StringValue(element, "partyy!")
cbHashTbl_Insert(hstbl, key, element):Print " "
Write "[g_MultiElementMode] Access: "
cbHashTbl_Access(hstbl, key) //Select bucket.
If g_HashTblMem
offset = cbHashTbl_NextBck(hstbl, key, 0) //Get start offset.
While offset
Print GetStringElement(hstbl, offset)
offset = cbHashTbl_NextBck(hstbl, key, offset) // Iterate all elements mapped To [key]
Wend
EndIf
Else
Write "Access: "
offset = cbHashTbl_Access(hstbl, StringValue(key, "xyz2"))
If g_HashTblMem
Print "Element mapped to "+Chr(34)+"xyz2"+Chr(34)+" found:"+Chr(34)+GetStringElement(hstbl, offset)+Chr(34)
EndIf
Write "Access: "
offset = cbHashTbl_Access(hstbl, StringValue(key, "advertees"))
If g_HashTblMem
Print "Element mapped to "+Chr(34)+"advertees"+Chr(34)+" found:"+Chr(34)+GetStringElement(hstbl, offset)+Chr(34)
EndIf
EndIf
WaitKey:Cls:Locate 0,0
//###########################################################
//# cbHashTbl_Next() testing. #
//###########################################################
Dim itr
itr = cbHashTbl_IterateBegin(hstbl, itr)
While cbHashTbl_Next(itr, 0)
g_HashTblMem = cbHashTbl_IterMem(itr)
offset = cbHashTbl_Offset(itr)
Write GetStringKey(hstbl, offset)+" --> "
cbHashTbl_Next(itr, 1)
g_HashTblMem = cbHashTbl_IterMem(itr)
offset = cbHashTbl_Offset(itr)
Print GetStringElement(hstbl, offset)
Wend
DeleteMEMBlock itr
WaitKey:Cls:Locate 0,0
//###########################################################
//# cbHashTbl_Delete() testing. #
//###########################################################
Write "deleting key xyz1.. "
z = cbHashTbl_Delete(hstbl, StringValue(key, "xyz1"))
offset = cbHashTbl_Access(hstbl, key)
If g_HashTblMem = 0 Then Print "Ok. ("+z+" deleted)" Else Print "Failed."
Print "deleting key advertees.. "
z = cbHashTbl_Delete(hstbl, StringValue(key, "advertees"), 1)
cbHashTbl_Access(hstbl, key)
If g_HashTblMem
Print "Failed To delete elements:"
offset = cbHashTbl_NextBck(hstbl, key, 0) //Get start offset.
While offset
Print GetStringElement(hstbl, offset)
offset = cbHashTbl_NextBck(hstbl, key, offset) // Iterate all elements mapped To [key]
Wend
Else
Print "Ok. ("+z+" deleted)"
EndIf
Write "deleting bucket xyz2.. "
z = cbHashTbl_Delete(hstbl, StringValue(key, "xyz2"),2)
offset = cbHashTbl_Access(hstbl, key)
If g_HashTblMem = 0 Then Print "Ok. ("+z+" deleted)" Else Print "Failed."
WaitKey