散列

Erlang提供了一个可从任意项式产生一个整数散列值的BIF:

hash(Term,MaxInt)
返回一个在1..MaxInt范围内的整数。

借助hash BIF我们可以编写一个高效的字典查询程序。该程序的接口与第??节的二叉树实现的字典几乎完全一样。

程序9.4

  1. -module(tupleStore).
  2. -export([new/0,new/1,lookup/2,add/3,delete/2]).
  3.  
  4. new() ->
  5. new(256).
  6.  
  7. new(NoOfBuckets) ->
  8. make_tuple(NoOfBuckets, []).
  9.  
  10. lookup(Key, Tuple) ->
  11. lookup_in_list(Key, element(hash(Key, size(Tuple)), Tuple)).
  12.  
  13. add(Key, Value, Tuple) ->
  14. Index = hash(Key, size(Tuple)),
  15. Old = element(Index, Tuple),
  16. New = replace(Key, Value, Old, []),
  17. setelement(Index, Tuple, New).
  18.  
  19. delete(Key, Tuple) ->
  20. Index = hash(Key, size(Tuple)),
  21. Old = element(Index, Tuple),
  22. New = delete(Key, Old, []),
  23. setelement(Index, Tuple, New).
  24.  
  25. make_tuple(Length, Default) ->
  26. make_tuple(Length, Default, []).
  27.  
  28. make_tuple(0, _, Acc) ->
  29. list_to_tuple(Acc);
  30. make_tuple(N, Default, Acc) ->
  31. make_tuple(N-1, Default, [Default|Acc]).
  32.  
  33. delete(Key, [{Key,_}|T], Acc) ->
  34. lists:append(T, Acc);
  35. delete(Key, [H|T], Acc) ->
  36. delete(Key, T, [H|Acc]);
  37. delete(Key, [], Acc) ->
  38. Acc.
  39.  
  40. replace(Key, Value, [], Acc) ->
  41. [{Key,Value}|Acc];
  42. replace(Key, Value, [{Key,_}|T], Acc) ->
  43. [{Key,Value}|lists:append(T, Acc)];
  44. replace(Key, Value, [H|T], Acc) ->
  45. replace(Key, Value, T, [H|Acc]).
  46.  
  47. lookup_in_list(Key, []) ->
  48. undefined;
  49. lookup_in_list(Key, [{Key, Value}|_]) ->
  50. {value, Value};
  51. lookup_in_list(Key, [_|T]) ->
  52. lookup_in_list(Key, T).

该程序与程序??.4的唯一区别就在于函数new/1,我们需要向该函数传入散列表的大小。

程序??.4是传统散列查找程序的一个简单实现。散列表T由一个定长元组表示。为了查找项式Key对应的值,需要计算出一个介于1..size(T)之间的散列索引Ielement(I,T)返回一个列表,包含散列索引相同的所有{Key,Value}键值对。在该列表中可以搜索到所需的{Key,Value}对。

向散列表中插入数据时,首先计算出Key的散列索引整数I,再向element(I,T)返回的列表中插入新的{Key,Value}对。原先与Key关联的值将被丢弃。

tupleStore模块提供了高效的字典。为了提高访问效率散列表的大小必须大于表中所插入的元素的数目。从这种结构中进行查询非常高效,但插入就逊色些。这是因为大部分Erlang视线中BIF setelement(Index,Val,T)每次都会创建一个新的元组T