Chapter #11 Examples in Oz
% Utility functions
proc {While Expr Stmt}
if {Expr} then {Stmt} {While Expr Stmt} end
end
proc {RepeatUntil Stmt Expr}
{Stmt}
if {Not {Expr}} then {RepeatUntil Stmt Expr} end
end
fun {MakeLinkedList}
linkedlist(head:{NewCell nil})
end
fun {MakeLinkedListNode K X}
linkedlistnode(key:K data:X next:{NewCell nil} prev:{NewCell nil})
end
fun {ListSearch L K}
X = {NewCell @(L.head)}
in
{While
fun {$} @X \= nil andthen @X.key \= K end
proc {$} X := @(@X.next) end}
@X
end
proc {ListInsert L X}
(X.next) := @(L.head)
if @(L.head) \= nil then
(@(L.head).prev) := X
end
(L.head) := X
(X.prev) := nil
end
proc {ListDelete L X}
if @(X.prev) \= nil then
(@(X.prev).next) := @(X.next)
else
(L.head) := @(X.next)
end
if @(X.next) \= nil then
(@(X.next).prev) := @(X.prev)
end
end
% 11.1 DirectAddress Table
fun {DirectAddressSearch T Key}
T.Key
end
proc {DirectAddressInsert T X=Value#Key}
T.Key := Value
end
proc {DirectAddressDelete T X=_#Key}
T.Key := nil
end
local
T = {Tuple.toArray nil#nil#nil#nil#nil}
in
{DirectAddressInsert T 10#1}
{DirectAddressInsert T 20#2}
{DirectAddressInsert T 30#3}
{DirectAddressInsert T 40#4}
{DirectAddressInsert T 50#5}
{Browse 'DirectAddressSearch'#{DirectAddressSearch T 1}}
{DirectAddressDelete T _#1}
{Browse 'DirectAddressSearch'#{DirectAddressSearch T 1}}
end
% 11.2 ChainedHashInsert
fun {SillyHash X}
case X
of a then 1
[] b then 1
[] c then 1
[] d then 2
[] e then 2
end
end
proc {ChainedHashInsert T X=Value#Key}
I = {SillyHash Key}
in
if T.I == nil then
T.I := {MakeLinkedList}
elseif {ListSearch T.I Key} \= nil then
{ChainedHashDelete T X}
end
{ListInsert T.I {MakeLinkedListNode Key Value}}
end
fun {ChainedHashSearch T Key}
I = {SillyHash Key}
in
if T.I == nil then
nil
else
case {ListSearch T.I Key}
of linkedlistnode(data:Value key:_ next:_ prev:_) then Value
else nil
end
end
end
proc {ChainedHashDelete T X=Value#Key}
I = {SillyHash Key}
in
{ListDelete T.I {ListSearch T.I Key}}
end
local
T = {Tuple.toArray nil#nil#nil#nil#nil}
in
{ChainedHashInsert T 10#a}
{ChainedHashInsert T 20#b}
{ChainedHashInsert T 30#c}
{ChainedHashInsert T 40#d}
{ChainedHashInsert T 50#e}
{Browse 'ChainedHashSearch'#{ChainedHashSearch T a}}
{ChainedHashDelete T _#a}
{ChainedHashDelete T _#b}
{ChainedHashInsert T 15#a}
{Browse 'ChainedHashSearch'#{ChainedHashSearch T a}}
{Browse 'ChainedHashSearch'#{ChainedHashSearch T b}}
{Browse 'ChainedHashSearch'#{ChainedHashSearch T c}}
end
% 11.3 Division Hash
fun {DivisionHash K M}
K mod M
end
% 11.3 Multiplication Hash
fun {IsPowerOf2 N}
{BitAnd N N-1} == 0
end
fun {BitAnd X Y}
case X#Y
of 0#_ then 0
[] _#0 then 0
else
2 * {BitAnd (X div 2) (Y div 2)} +
if X mod 2 == Y mod 2 then X mod 2 else 0 end
end
end
fun {ShiftRight X N}
X div {Pow 2 N}
end
fun {MultiplicationHash K Size}
if {IsPowerOf2 Size} then
local
R = 2654435769 * K
ShiftAmount
BitMask = Size - 1
in
{BitAnd {ShiftRight R ShiftAmount} BitMask}
end
else
local
Multiplier = 0.6180339887
X
%double x = o.hashCode() * MULTIPLIER;
in
%x -= Math.floor(x); // take the fractional part
%x *= tableSize; // multiply by the table size
{FloatToInt X}
end
end
end
% 11.4 Hash
M = 100
fun {Hash K I}
_
end
fun {HashInsert T K}
Return = {NewCell nil}
I = {NewCell 0}
in
{RepeatUntil
proc {$}
J = {Hash K I}
in
if T.J == nil then
T.J := K
Return := J
else
I := @I + 1
end
end
fun {$} @Return \= nil orelse @I == M end}
if @Return \= nil then
@Return
else
raise error('hash table overflow') end
end
end
fun {HashSearch T K}
Return = {NewCell nil}
I = {NewCell 0}
J = {NewCell _}
in
{RepeatUntil
proc {$}
J := {Hash K I}
if T.@J == K then
Return := J
else
I := @I + 1
end
end
fun {$} @Return \= nil orelse T.@J == nil orelse I == M end}
@Return
end
|