(phixonline)--> with javascript_semantics enum KEY = 0, LEFT, HEIGHT, -- (NB +/-1 gives LEFT or RIGHT) RIGHT sequence tree = {} integer freelist = 0 function newNode(object key) integer node if freelist=0 then node = length(tree)+1 tree &= {key,NULL,1,NULL} else node = freelist freelist = tree[freelist] tree[node+KEY..node+RIGHT] = {key,NULL,1,NULL} end if return node end function function height(integer node) return iff(node=NULL?0:tree[node+HEIGHT]) end function procedure setHeight(integer node) tree[node+HEIGHT] = max(height(tree[node+LEFT]), height(tree[node+RIGHT]))+1 end procedure function rotate(integer node, integer direction) integer idirection = LEFT+RIGHT-direction integer pivot = tree[node+idirection] {tree[pivot+direction],tree[node+idirection]} = {node,tree[pivot+direction]} setHeight(node) setHeight(pivot) return pivot end function function getBalance(integer N) return iff(N==NULL ? 0 : height(tree[N+LEFT])-height(tree[N+RIGHT])) end function function insertNode(integer node, object key) if node==NULL then return newNode(key) end if integer c = compare(key,tree[node+KEY]) if c!=0 then integer direction = HEIGHT+c -- LEFT or RIGHT -- note this crashes under p2js... (easy to fix, not so easy to find) -- tree[node+direction] = insertNode(tree[node+direction], key) atom tnd = insertNode(tree[node+direction], key) tree[node+direction] = tnd setHeight(node) integer balance = trunc(getBalance(node)/2) -- +/-1 (or 0) if balance then direction = HEIGHT-balance -- LEFT or RIGHT c = compare(key,tree[tree[node+direction]+KEY]) if c=balance then tree[node+direction] = rotate(tree[node+direction],direction) end if if c!=0 then node = rotate(node,LEFT+RIGHT-direction) end if end if end if return node end function function minValueNode(integer node) while 1 do integer next = tree[node+LEFT] if next=NULL then exit end if node = next end while return node end function function deleteNode(integer root, object key) integer c if root=NULL then return root end if c = compare(key,tree[root+KEY]) if c=-1 then tree[root+LEFT] = deleteNode(tree[root+LEFT], key) elsif c=+1 then tree[root+RIGHT] = deleteNode(tree[root+RIGHT], key) elsif tree[root+LEFT]==NULL or tree[root+RIGHT]==NULL then integer temp = iff(tree[root+LEFT] ? tree[root+LEFT] : tree[root+RIGHT]) if temp==NULL then -- No child case {temp,root} = {root,NULL} else -- One child case tree[root+KEY..root+RIGHT] = tree[temp+KEY..temp+RIGHT] end if tree[temp+KEY] = freelist freelist = temp else -- Two child case integer temp = minValueNode(tree[root+RIGHT]) tree[root+KEY] = tree[temp+KEY] tree[root+RIGHT] = deleteNode(tree[root+RIGHT], tree[temp+KEY]) end if if root=NULL then return root end if setHeight(root) integer balance = trunc(getBalance(root)/2) if balance then integer direction = HEIGHT-balance c = compare(getBalance(tree[root+direction]),0) if c=-balance then tree[root+direction] = rotate(tree[root+direction],direction) end if root = rotate(root,LEFT+RIGHT-direction) end if return root end function procedure inOrder(integer node) if node!=NULL then inOrder(tree[node+LEFT]) printf(1, "%d ", tree[node+KEY]) inOrder(tree[node+RIGHT]) end if end procedure integer root = NULL sequence test = shuffle(tagset(50003)) for i=1 to length(test) do root = insertNode(root,test[i]) end for test = shuffle(tagset(50000)) for i=1 to length(test) do root = deleteNode(root,test[i]) end for inOrder(root)