第八章 Caché 算法与数据结构 散列表

文章目录

  • 第八章 Caché 算法与数据结构 散列表
  • 散列表
  • 完整示例
    • 链表节点类
    • 哈希表类
    • 调用

第八章 Caché 算法与数据结构 散列表

散列表

散列表也叫做哈希表,这种数据结构提供了键(key)值(value)的映射关系,只要给出一个key就可以高效查找它所匹配的value,时间复杂度接近于O(1)。

key value
key1 vaule1
key2 vaule2
key3 vaule3
key4 vaule4

完整示例

在直接寻址的情况下,具有关键字k的元素被存储在槽k中。比方说关键字域有3,5,9,11四个数,那么它只能被存储在3,5,9,11四个位置,其他的位置全部都被浪费掉了,这时候就可以通过散列函数h,将关键字域中的元素映射到散列表[0,m-1]的位置上。

这时候内存的花销就大大的减少了。

散列函数定义为:

index=key%16;

通过链接法来解决碰撞问题:

链表节点类

Class PHA.YX.Arithmetic.HashMap.HashEntry Extends %RegisteredObject
{

Property key As %Integer;

Property value [ InitialExpression = 0 ];

Property next As HashEntry;

Property pre As HashEntry;

}

哈希表类

Class PHA.YX.Arithmetic.HashMap Extends %RegisteredObject
{

Property size As %Integer [ InitialExpression = 16 ];

Property arrayList As array Of PHA.YX.Arithmetic.HashMap.HashEntry;

Method %OnNew() As %Status [ Private, ServerOnly = 1 ]
{
	f i = 0 : 1 : ..size - 1 d
	.d ..arrayList.SetAt("", i)
	Quit $$$OK
}

Method getContainer() As %ListOfObjects
{
	q ..arrayList
}

Method getIndex(key As %Integer)
{
	q key#16
}

Method insert(key As %Integer, value As %Integer) As %Boolean
{
	q:..get(key)'="" $$$NO
	s index = ..getIndex(key)
	q:index>16 $$$NO
	s ret = $$$NO
	if (..arrayList.GetAt(index) = "") {
		s mEntry = ##class(PHA.YX.Arithmetic.HashMap.HashEntry).%New()
		s mEntry.key = key
		s mEntry.value = value
		d ..arrayList.RemoveAt(index)
		d ..arrayList.SetAt(mEntry,key)
		s ret = $$$YES
	}
	else {
		s mEntry = ..arrayList.GetAt(index)
		s preEntry = mEntry
		while (mEntry '="") {
			s preEntry = mEntry
			s mEntry = mEntry.next 
		}
		s newEntry = ##class(PHA.YX.Arithmetic.HashMap.HashEntry).%New()
		s newEntry.pre = mEntry
		s newEntry.key = key
		s newEntry.value = value
		s preEntry.next = newEntry
		s ret = $$$YES
	}  
	q ret
}

Method get(key As %Integer) As PHA.YX.Arithmetic.HashMap.HashEntry
{
	s index = ..getIndex(key)
	q:..arrayList.GetAt(index)="" ""
	
	s ret = ""
	#dim mEntry as PHA.YX.Arithmetic.HashMap.HashEntry = ..arrayList.GetAt(index)
	while ((mEntry '= "")&&(ret = ""))
	{
		i mEntry.key = key d
		.s ret = mEntry
		e  d
		.s mEntry = mEntry.next
	}
	q ret
}

Method remove(key As %Integer) As %Boolean
{
	s index = ..getIndex(key)
	q:..arrayList.GetAt(index)="" $$$NO
	
	#dim mEntry as PHA.YX.Arithmetic.HashMap.HashEntry = ..arrayList.GetAt(index)
	while (mEntry '= ""){
		if (mEntry.key = key){
			if (mEntry.pre = ""){
				s mEntry.value = ""
				return $$$YES
			}else{
				s mEntry.pre = mEntry.next
				return $$$YES
			}
		}else{
			s mEntry = mEntry.next
		}
	}
	return $$$NO
}

Method edit(key As %Integer, value As %Integer) As %Boolean
{
	#dim mEntry as PHA.YX.Arithmetic.HashMap.HashEntry = ..get(key)
	q:mEntry="" $$$NO
	s mEntry.value = value
	q $$$YES
}

}

调用

/// w ##class(PHA.YX.Arithmetic).HashMap()
ClassMethod HashMap()
{
	s $zt = "ErrHashMap"

	#dim mHashMap as PHA.YX.Arithmetic.HashMap = ##class(PHA.YX.Arithmetic.HashMap).%New()
	d mHashMap.insert(1,2)
	d mHashMap.insert(17,3)
	w mHashMap.get(1),!
	w mHashMap.get(17),!
	w mHashMap.get(1).value,!
	w mHashMap.get(17).value,!
	d mHashMap.edit(1,4)
	w mHashMap.get(1).value,!
	w mHashMap.get(17).value,!
	d mHashMap.remove(1)
	w mHashMap.get(1).value,!
	w mHashMap.get(17).value,!
	q ""
ErrHashMap
	q $ze
}

做了一个简单的碰撞测试,最后是输出结果,显然这两个地址是不一样的

DHC-APP>w ##class(PHA.YX.Arithmetic).HashMap()
[email protected]
[email protected]
2
3
4
3
 
3
 

你可能感兴趣的:(Caché,算法与数据结构,Caché,算法,数据结构,散列,键值对)