The changelog is something that will be formally defined during the process of preparing the release. At the moment, there has been a couple of minor fixes done in the dev trunk and-or the mozart-1-3-0-fixes brunch, some of them will have to merged. But, the main thing is that now the source compiles with gcc-4.0.

We are just starting with this work to gain the expertise of making releases, so we will go through the cvs to define the changelog. We will come up with a list soon.

Hi,

I have a wish for one of the future releases. I think that Mozart lacks some common data structures in the standard library. I think one of the most needed is a sorted associative container. Another such structure is a priority queue. I wonder why those did not make it into the Mozart's stdlib - I see it as a drawback for beginners who are used to C++'s or Java's stdlib.

To be constructive, I attach an implementation of sorted associative container that uses a red-black tree and a double-linked list (it is not as generic as could be, but could be enhanced easily).

Cheers,
Filip
local
   class RBTree
   feat
      new:% Creates a new red-black tree
      fun {$} {New RBTree Init} end

      isEmpty:% Checks whether the tree is empty
      fun {$ T}
         RootNode=T.ROOT
         NilNode=T.NIL
      in
         @(RootNode.left)==NilNode
      end

      put:% Add/set Value at Key
      proc {$ T Key Value}
         ({T Access(Key default:Value $)}.value):=Value
      end

      exchange:% Same as put, but retrieve the old value; throws if the key did 
not exist
      proc {$ T Key OldValue NewValue}
         {Exchange {T Access(Key can_throw:true $)}.value OldValue NewValue}
      end

      condExchange:% Same as put, but retrieve the old value; uses default 
value if the key did not exist
      proc {$ T Key Default OldValue NewValue}
         {Exchange {T Access(Key default:Default $)}.value OldValue NewValue}
      end

      get:% Retrieve value at key; throws if the key does not exist
      fun {$ T Key}
         @({T Access(Key can_throw:true $)}.value)
      end

      condGet:% Retrieve value at key; returns default if the key does not exist
      fun {$ T Key Default}
         try
            @({T Access(Key can_throw:true $)}.value)
         catch !NOT_FOUND_EXCEPTION then
            Default
         end
      end

      access:% Returns node the given key. If the key did not exist, creates a 
new node with value Default.
      %% The node has format node(key:Key value:ValueCell ...).
      fun {$ T Key Default}
         {RBTree.MakeExtNode {T Access(Key default:Default $)}}
      end

      condGetNode:%% Returns the node at the given key. Returns null if the key 
does not exist.
      %% The node has format node(key:Key value:ValueCell ...).
      fun {$ T Key}
         try
            {RBTree.MakeExtNode {T Access(Key can_throw:true $)}}
         catch !NOT_FOUND_EXCEPTION then
            null
         end
      end

      member:% Checks whether the key exists
      fun {$ T Key}
         try
            _={T Access(Key can_throw:true $)}
            true
         catch !NOT_FOUND_EXCEPTION then
            false
         end
      end

      removeAll:% Clears the tree
      proc {$ T}
         RootNode=T.ROOT
         NilNode=T.NIL
      in
         (RootNode.left):=NilNode
         (RootNode.right):=NilNode
         (RootNode.parent):=NilNode
      end

      remove:% Removes an entry
      proc {$ T Key}
         {T Delete({T Access(Key can_throw:true $)})}
      end

      silentRemove:% Removes an entry; does nothing when the key does not exist
      proc {$ T Key}
         try
            {T Delete({T Access(Key can_throw:true $)})}
         catch !NOT_FOUND_EXCEPTION then
            skip
         end
      end

      removeNode:% Removes the specified node.
      proc {$ T Node}
         {T Delete(Node.NODE)}
      end

      getNextNode:% Retrieves the next node (null if there is no next node).
      fun {$ Node}
         NextNode=@(Node.NODE.succ)
      in
         if NextNode==null then null else
            {RBTree.MakeExtNode NextNode}
         end
      end

      getPrevNode:% Retrieves the previous node (null if there is no previous 
node).
      fun {$ Node}
         PrevNode=@(Node.NODE.prec)
      in
         if PrevNode==null then null else
            {RBTree.MakeExtNode PrevNode}
         end
      end

      entries:% Retrieves the entries in the form Key#Value
      fun {$ T}
         {T CollectEntries($)}
      end

      keys:% Retrieves the keys
      fun {$ T}
         {T CollectKeys($)}
      end

      items:% Retrieves the values
      fun {$ T}
         {T CollectValues($)}
      end

      mentries:% Retrieves the entries in the form Key#<Value> (i.e. value as a 
modifiable cell)
      fun {$ T}
         {T CollectMEntries($)}
      end

      entryRange:% Retrieves all entries with LBKey =< Key =< UBKey
      fun {$ T LBKey UBKey}
         {T CollectEntriesRange(LBKey UBKey $)}
      end

      keyRange:% Retrieves all keys such that LBKey =< Key =< UBKey
      fun {$ T LBKey UBKey}
         {T CollectKeysRange(LBKey UBKey $)}
      end

      itemsRange:% Retrieves all items with LBKey =< Key =< UBKey
      fun {$ T LBKey UBKey}
         {T CollectValuesRange(LBKey UBKey $)}
      end

      mentryRange:% Retrieves all modifiable entries with LBKey =< Key =< UBKey
      fun {$ T LBKey UBKey}
         {T CollectMEntriesRange(LBKey UBKey $)}
      end

      getKeyLB:% Retrieves the key that is greater or equal to the specified 
lower bound; Default if there is no such key
      fun {$ T LBKey Default}
         Node={T FindLB(LBKey $)}
      in
         if Node==T.NIL then
            Default
         else
            @(Node.key)
         end
      end

      getKeyUB:% Retrieves the key that is smaller or equal to the specified 
upper bound; Default if there is no such key
      fun {$ T UBKey Default}
         Node={T FindUB(UBKey $)}
      in
         if Node==T.NIL then
            Default
         else
            @(Node.key)
         end
      end

      firstKey:% Returns the first key; Default if the tree is empty
      fun {$ T Default}
         FirstNode=@(T.NIL.succ)
      in
         if FirstNode==T.NIL then
            Default
         else
            @(FirstNode.key)
         end
      end

      lastKey:% Returns the last key; Default if the tree is empty
      fun {$ T Default}
         LastNode=@(T.NIL.prec)
      in
         if LastNode==T.NIL then
            Default
         else
            @(LastNode.key)
         end
      end

      listAdd:% Adds an entry to the list stored under Key.
      proc {$ T Key Value}
         Node={T Access(Key default:nil $)}
      in
         (Node.value):=Value|@(Node.value)
      end

      listRemove:% Removes an entry from the list stored under Key; if the list 
becomes empty, removes the Key.
      proc {$ T Key Value}
         try
            Node={T Access(Key can_throw:true $)}
            L
         in
            L={Filter @(Node.value) fun {$ V2} V2\=Value end}
            if L\=nil then
               (Node.value):=L
            else
               {T Delete(Node)}
            end
         catch !NOT_FOUND_EXCEPTION then
            skip %% The key did not exist
         end
      end

      %%=============================================================
      %% Implementation
      %%=============================================================

      %% The root and nil nodes
      NOT_FOUND_EXCEPTION:unit
      NODE:unit
      ROOT
      NIL

      MakeExtNode:%
      fun {$ Node}
         node(NODE:Node key:@(Node.key) value:Node.value)
      end
         
      NewNode:% Creates a new node
      fun {$ Key Value Color PLR}
         node(parent:{NewCell PLR}
              left:{NewCell PLR}
              right:{NewCell PLR}
              color:{NewCell Color} 
              key:{NewCell Key}
              value:{NewCell Value}
              prec:{NewCell PLR}
              succ:{NewCell PLR}
             )
      end

      meth Init
         NilNode
      in
         NilNode={RBTree.NewNode null null black NilNode}
         self.ROOT={RBTree.NewNode null null black NilNode}
         self.NIL=NilNode
      end

      meth RotateLeft(Node)
         Right=@(Node.right)
         RightLeft=@(Right.left)
         NodeParent=@(Node.parent)
      in
         (Node.right):=RightLeft
         if RightLeft\=self.NIL then (RightLeft.parent):=Node end

         (Right.parent):=NodeParent
         if Node==@(NodeParent.left) then
            (NodeParent.left):=Right
         else
            (NodeParent.right):=Right
         end
         (Right.left):=Node
         (Node.parent):=Right
      end

      meth RotateRight(Node)
         Left=@(Node.left)
         LeftRight=@(Left.right)
         NodeParent=@(Node.parent)
      in
         (Node.left):=LeftRight
         if LeftRight\=self.NIL then (LeftRight.parent):=Node end

         (Left.parent):=NodeParent
         if Node==@(NodeParent.left) then
            (NodeParent.left):=Left
         else
            (NodeParent.right):=Left
         end
         (Left.right):=Node
         (Node.parent):=Left
      end

      meth FindLB(Key $)
         X={NewCell null}
         Y={NewCell null}
      in
         Y:=self.ROOT
         X:=@(self.ROOT.left)
         case 
            for while:@X\=self.NIL return:R default:false do
               [EMAIL PROTECTED]
            in
               if @(XNode.key) == Key then
                  {R true}
               elseif @(XNode.key) > Key then
                  X:=@(XNode.left)
               else
                  X:=@(XNode.right)
               end
               Y:=XNode
            end
         of true then
            @X
         else
            if @Y==self.ROOT then
               self.NIL
            else
               YKey=@(@Y.key)
            in
               if Key<YKey then
                  @Y
               else
                  @(@Y.succ)
               end
            end
         end
      end

      meth FindUB(Key $)
         X={NewCell null}
         Y={NewCell null}
      in
         Y:=self.ROOT
         X:=@(self.ROOT.left)
         case 
            for while:@X\=self.NIL return:R default:false do
               [EMAIL PROTECTED]
            in
               if @(XNode.key) == Key then
                  {R true}
               elseif @(XNode.key) > Key then
                  X:=@(XNode.left)
               else
                  X:=@(XNode.right)
               end
               Y:=XNode
            end
         of true then
            @X
         else
            if @Y==self.ROOT then
               self.NIL
            else
               YKey=@(@Y.key)
            in
               if Key>YKey then
                  @Y
               else
                  @(@Y.prec)
               end
            end
         end
      end

      %% Returns Node at Key; uses Default as the initial value.
      %% When CanThrow==true, it throws NOT_FOUND_EXCEPTION rather than 
creating a new node.
      meth Access(Key can_throw:CanThrow<=false default:Default<=_ $)
         X={NewCell null}
         Y={NewCell null}
      in
         Y:=self.ROOT
         X:=@(self.ROOT.left)
         case 
            for while:@X\=self.NIL return:R default:false#_ do
               [EMAIL PROTECTED]
            in
               Y:=XNode
               if @(XNode.key) == Key then
                  {R true#XNode}
               elseif @(XNode.key) > Key then
                  X:=@(XNode.left)
               else
                  X:=@(XNode.right)
               end
            end
         of true#FoundNode then
            FoundNode
         else
            if CanThrow then
               raise NOT_FOUND_EXCEPTION end
            end
            local
               [EMAIL PROTECTED]
               Node={RBTree.NewNode Key Default red self.NIL}
               X={NewCell Node}
            in
               (Node.parent):=YNode
               if YNode==self.ROOT then
                  (YNode.left):=Node
                  (self.NIL.succ):=Node
                  (self.NIL.prec):=Node
               else
                  if @(YNode.key)>Key then
                     YNodePrec=@(YNode.prec)
                  in
                     (YNode.prec):=Node
                     (YNodePrec.succ):=Node
                     (Node.prec):=YNodePrec
                     (Node.succ):=YNode
                     
                     (YNode.left):=Node
                  else
                     YNodeSucc=@(YNode.succ)
                  in
                     (YNode.succ):=Node
                     (YNodeSucc.prec):=Node
                     (Node.succ):=YNodeSucc
                     (Node.prec):=YNode

                     (YNode.right):=Node
                  end
               end
               %% Do the rotations...
               for while:@(@(@X.parent).color)==red do
                  [EMAIL PROTECTED]
                  Parent=@(Node.parent)
                  Grandparent=@(Parent.parent)
               in
                  if Parent==@(Grandparent.left) then
                     Uncle=@(Grandparent.right)
                  in
                     if @(Uncle.color)==red then
                        (Parent.color):=black
                        (Uncle.color):=black
                        (Grandparent.color):=red
                        X:=Grandparent
                     else
                        if Node==@(Parent.right) then
                           X:=Parent
                           RBTree, RotateLeft(Parent)
                        end
                        local
                           [EMAIL PROTECTED]
                           Parent=@(Node.parent)
                           Grandparent=@(Parent.parent)
                        in
                           (Parent.color):=black
                           (Grandparent.color):=red
                           RBTree, RotateRight(Grandparent)
                        end
                     end
                  else
                     Uncle=@(Grandparent.left)
                  in
                     if @(Uncle.color)==red then
                        (Parent.color):=black
                        (Uncle.color):=black
                        (Grandparent.color):=red
                        X:=Grandparent
                     else
                        if Node==@(Parent.left) then
                           X:=Parent
                           RBTree, RotateRight(Parent)
                        end
                        local
                           [EMAIL PROTECTED]
                           Parent=@(Node.parent)
                           Grandparent=@(Parent.parent)
                        in
                           (Parent.color):=black
                           (Grandparent.color):=red
                           RBTree, RotateLeft(Grandparent)
                        end
                     end
                  end
               end
               (@(self.ROOT.left).color):=black
               %% Return the new node
               Node
            end
         end
      end

      meth Successor(Node $)
         Right=@(Node.right)
         Y={NewCell Right}
      in
         if Right\=self.NIL then
            for while:@(@Y.left)\=self.NIL do
               Y:=@(@Y.left)
            end
            @Y
         else
            X={NewCell Node}
         in
            Y:=@(Node.parent)
            for while:@X==@(@Y.right) do
               X:[EMAIL PROTECTED]
               Y:=@(@Y.parent)
            end
            if @Y==self.ROOT then
               self.NIL
            else
               @Y
            end
         end
      end

      meth Predecessor(Node $)
         Left=@(Node.left)
         Y={NewCell Left}
      in
         if Left\=self.NIL then
            for while:@(@Y.right)\=self.NIL do
               Y:=@(@Y.right)
            end
            @Y
         else
            X={NewCell Node}
         in
            Y:=@(Node.parent)
            for return:R do
               [EMAIL PROTECTED]
               [EMAIL PROTECTED]
            in
               if XNode\=@(YNode.left) then
                  {R YNode}
               elseif YNode==self.ROOT then
                  {R self.NIL}
               end
               X:=YNode
               Y:=@(YNode.parent)
            end
         end
      end

      meth DeleteFixUp(Node)
         RootLeftNode=@(self.ROOT.left)
         X={NewCell Node}
      in
         for
            while:(@X.color)==black andthen @X\=RootLeftNode
            break:B
         do
            [EMAIL PROTECTED]
            Parent=@(Node.parent)
         in
            if Node==@(Parent.left) then
               W={NewCell @(Parent.right)}
               WColorC=(@W.color)
            in
               if @WColorC==red then
                  WColorC:=black
                  (Parent.color):=red
                  RBTree, RotateLeft(Parent)
                  W:=@(@(@X.parent).right)
               end
               local
                  Parent=@(@X.parent)
                  [EMAIL PROTECTED]
                  WNodeRightColorC=@(WNode.right).color
                  WNodeLeftColorC=@(WNode.left).color
               in
                  if @WNodeRightColorC==black andthen @WNodeLeftColorC==black 
then
                     (WNode.color):=red
                     X:=Parent
                  else
                     if @WNodeRightColorC==black then
                        WNodeLeftColorC:=black
                        (WNode.color):=red
                        RBTree, RotateRight(WNode)
                        W:=@(Parent.right)
                     end
                     local
                        [EMAIL PROTECTED]
                     in
                        (WNode.color):=@(Parent.color)
                        (Parent.color):=black
                        (@(WNode.right).color):=black
                        RBTree, RotateLeft(Parent)
                        {B}
                     end
                  end
               end
            else
               W={NewCell @(Parent.left)}
               WColorC=(@W.color)
            in
               if @WColorC==red then
                  WColorC:=black
                  (Parent.color):=red
                  RBTree, RotateRight(Parent)
                  W:=@(@(@X.parent).left)
               end
               local
                  Parent=@(@X.parent)
                  [EMAIL PROTECTED]
                  WNodeRightColorC=@(WNode.right).color
                  WNodeLeftColorC=@(WNode.left).color
               in
                  if @WNodeRightColorC==black andthen @WNodeLeftColorC==black 
then
                     (WNode.color):=red
                     X:=Parent
                  else
                     if @WNodeLeftColorC==black then
                        WNodeRightColorC:=black
                        (WNode.color):=red
                        RBTree, RotateLeft(WNode)
                        W:=@(Parent.left)
                     end
                     local
                        [EMAIL PROTECTED]
                     in
                        (WNode.color):=@(Parent.color)
                        (Parent.color):=black
                        (@(WNode.left).color):=black
                        RBTree, RotateRight(Parent)
                        {B}
                     end
                  end
               end
            end
         end
         (@X.color):=black
      end

      meth Delete(Node)
         YNode=if @(Node.left)==self.NIL orelse @(Node.right)==self.NIL then
                  Node
               else
                  RBTree, Successor(Node $)
               end
         XNode=if @(YNode.left)==self.NIL then @(YNode.right) else 
@(YNode.left) end

         Prec=@(Node.prec)
         Succ=@(Node.succ)
      in
         (Prec.succ):=Succ
         (Succ.prec):=Prec

         (XNode.parent):=@(YNode.parent)
         if self.ROOT==@(YNode.parent) then
            (self.ROOT.left):=XNode
         else
            YParentNode=@(YNode.parent)
         in
            if YNode==@(YParentNode.left) then
               (YParentNode.left):=XNode
            else
               (YParentNode.right):=XNode
            end
         end
         if YNode\=Node then
            Parent=@(Node.parent)
            Left=@(Node.left)
            Right=@(Node.right)
         in
            (YNode.left):=Left
            (YNode.right):=Right
            (YNode.parent):=Parent
            (Left.parent):=YNode
            (Right.parent):=YNode
            if Node==@(Parent.left) then
               (Parent.left):=YNode
            else
               (Parent.right):=YNode
            end
            if @(YNode.color)==black then
               (YNode.color):=red
               RBTree, DeleteFixUp(XNode)
            else
               (YNode.color):=@(Node.color)
            end
         else
            if @(YNode.color)==black then
               RBTree, DeleteFixUp(XNode)
            end
         end
      end

      meth CollectEntries($)
         fun {CollectEntry Node}
            if Node==self.NIL then
               nil
            else
               @(Node.key)#@(Node.value) | {CollectEntry @(Node.succ)}
            end
         end
      in
         {CollectEntry @(self.NIL.succ)}
      end

      meth CollectKeys($)
         fun {CollectKey Node}
            if Node==self.NIL then
               nil
            else
               @(Node.key) | {CollectKey @(Node.succ)}
            end
         end
      in
         {CollectKey @(self.NIL.succ)}
      end

      meth CollectValues($)
         fun {CollectValue Node}
            if Node==self.NIL then
               nil
            else
               @(Node.value) | {CollectValue @(Node.succ)}
            end
         end
      in         
         {CollectValue @(self.NIL.succ)}
      end

      meth CollectMEntries($)
         fun {CollectMEntry Node}
            if Node==self.NIL then
               nil
            else
               @(Node.key)#(Node.value) | {CollectMEntry @(Node.succ)}
            end
         end
      in
         {CollectMEntry @(self.NIL.succ)}
      end

      meth CollectEntriesRange(LB UB $)
         fun {CollectEntryUB Node}
            if Node==self.NIL orelse @(Node.key)>UB then
               nil
            else
               @(Node.key)#@(Node.value) | {CollectEntryUB @(Node.succ)}
            end
         end
      in
         {CollectEntryUB RBTree, FindLB(LB $)}
      end

      meth CollectKeysRange(LB UB $)
         fun {CollectKeyUB Node}
            if Node==self.NIL orelse @(Node.key)>UB then
               nil
            else
               @(Node.key) | {CollectKeyUB @(Node.succ)}
            end
         end
      in
         {CollectKeyUB RBTree, FindLB(LB $)}
      end

      meth CollectValuesRange(LB UB $)
         fun {CollectValueUB Node}
            if Node==self.NIL orelse @(Node.key)>UB then
               nil
            else
               @(Node.value) | {CollectValueUB @(Node.succ)}
            end
         end
      in
         {CollectValueUB RBTree, FindLB(LB $)}
      end

      meth CollectMEntriesRange(LB UB $)
         fun {CollectMEntryUB Node}
            if Node==self.NIL orelse @(Node.key)>UB then
               nil
            else
               @(Node.key)#(Node.value) | {CollectMEntryUB @(Node.succ)}
            end
         end
      in
         {CollectMEntryUB RBTree, FindLB(LB $)}
      end
end
in
   {Browse {RBTree.new}}
end
_________________________________________________________________________________
mozart-users mailing list                               
[email protected]
http://www.mozart-oz.org/mailman/listinfo/mozart-users

Reply via email to