Advertisement
runewalsh

Древесная Анархия [FPC]

Oct 11th, 2012
373
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Delphi 9.90 KB | None | 0 0
  1. type
  2.   _tRBTNodeColor = (RBT_Red, RBT_Black);
  3.  
  4.   // Associative array. Based on red-black tree.
  5.   generic gMap<_Key_, _Item_> = object(tRWObject)
  6.   type
  7.     tItemProc = procedure(var a: _Item_);
  8.   private
  9.   type
  10.     _pRBTNode = ^_tRBTNode;
  11.     _tRBTNode = record
  12.       left, right, parent: _pRBTNode;
  13.       color: _tRBTNodeColor;
  14.       key: _Key_;
  15.       data: _Item_;
  16.     end;
  17.   var
  18.     _root: _pRBTNode;
  19.     _count: sint;
  20.     function _FindNode(const key: _Key_): _pRBTNode;
  21.     procedure _RotateLeft(x: _pRBTNode);
  22.     procedure _RotateRight(x: _pRBTNode);
  23.     function _AddNode(const key: _Key_; const item: _Item_): _pRBTNode;
  24.     procedure _DeleteNode(z: _pRBTNode);
  25.     procedure _ForEach(x: _pRBTNode; proc: tItemProc);
  26.     procedure _Free(x: _pRBTNode);
  27.   protected
  28.     function _NullItem: _Item_; virtual; abstract;
  29.     procedure _Finalize(var key: _Key_; var item: _Item_); virtual;
  30.     function _Compare(const a, b: _Key_): tValueRelationship; virtual; abstract;
  31.   public
  32.     constructor Init;
  33.     destructor Done; virtual;
  34.     procedure Add(const key: _Key_; const item: _Item_);
  35.     function Find(const key: _Key_): _Item_;
  36.     procedure Remove(const key: _Key_);
  37.     procedure Clear;
  38.     procedure ForEach(proc: tItemProc);
  39.     property Count: sint read _count;
  40.   end;
  41.  
  42. ////////////////////////////////////////////////////////////////////
  43.  
  44.   function gMap._FindNode(const key: _Key_): _pRBTNode;
  45.   var
  46.     cn: _pRBTNode;
  47.   begin
  48.     cn := _root;
  49.     while Assigned(cn) do
  50.       case _Compare(key, cn^.key) of
  51.         value_Equals: break;
  52.         value_Greater: cn := cn^.right;
  53.         value_Less: cn := cn^.left;
  54.       end;
  55.     result := cn;
  56.   end;
  57.  
  58.   procedure gMap._RotateLeft(x: _pRBTNode);
  59.   var
  60.     y: _pRBTNode;
  61.   begin
  62.     y := x^.right;
  63.     x^.right := y^.left;
  64.     if Assigned(y^.left) then y^.left^.parent := x;
  65.     y^.parent := x^.parent;
  66.     if x = _root then _root := y else
  67.       if x = x^.parent^.left then
  68.         x^.parent^.left := y
  69.       else
  70.         x^.parent^.right := y;
  71.     y^.left := x;
  72.     x^.parent := y;
  73.   end;
  74.  
  75.   procedure gMap._RotateRight(x: _pRBTNode);
  76.   var
  77.     y: _pRBTNode;
  78.   begin
  79.     y := x^.left;
  80.     x^.left := y^.right;
  81.     if Assigned(y^.right) then y^.right^.parent := x;
  82.     y^.parent := x^.parent;
  83.     if x = _root then _root := y else
  84.       if x = x^.parent^.right then
  85.         x^.parent^.right := y
  86.       else
  87.         x^.parent^.left := y;
  88.     y^.right := x;
  89.     x^.parent := y;
  90.   end;
  91.  
  92.   function gMap._AddNode(const key: _Key_; const item: _Item_): _pRBTNode;
  93.   var
  94.     x, y, z, zpp: _pRBTNode;
  95.   begin
  96.     y := nil;
  97.     x := _root;
  98.     while Assigned(x) do
  99.     begin
  100.       y := x;
  101.       case _Compare(key, x^.key) of
  102.         value_Equals:
  103.           begin
  104.             _Finalize(x^.key, x^.data);
  105.             x^.key := key;
  106.             x^.data := item;
  107.             exit(x); // already exists
  108.           end;
  109.         value_Less: x := x^.left;
  110.         value_Greater: x := x^.right;
  111.       end;
  112.     end;
  113.  
  114.     inc(_count);
  115.     new(z);
  116.     z^.key := key;
  117.     z^.data := item;
  118.     z^.left := nil;
  119.     z^.right := nil;
  120.     z^.color := RBT_Red;
  121.     z^.parent := y;
  122.     result := z;
  123.  
  124.     if Assigned(y) then
  125.       case _Compare(key, y^.key) of
  126.         value_Less: y^.left := z;
  127.         else
  128.           y^.right := z;
  129.       end
  130.     else
  131.       _root := z;
  132.  
  133.     // rebalance
  134.     while (z <> _root) and (z^.parent^.color = RBT_Red) do
  135.     begin
  136.       zpp := z^.parent^.parent;
  137.       if z^.parent = zpp^.left then
  138.       begin
  139.         y := zpp^.right;
  140.         if Assigned(y) and (y^.color = RBT_Red) then
  141.         begin
  142.           z^.parent^.color := RBT_Black;
  143.           y^.color := RBT_Black;
  144.           zpp^.color := RBT_Red;
  145.           z := zpp;
  146.         end else
  147.         begin
  148.           if z = z^.parent^.right then
  149.           begin
  150.             z := z^.parent;
  151.             _RotateLeft(z);
  152.           end;
  153.           z^.parent^.color := RBT_Black;
  154.           zpp^.color := RBT_Red;
  155.           _RotateRight(zpp);
  156.         end;
  157.       end else
  158.       begin
  159.         y := zpp^.left;
  160.         if Assigned(y) and (y^.color = RBT_Red) then
  161.         begin
  162.           z^.parent^.color := RBT_Black;
  163.           y^.color := RBT_Black;
  164.           zpp^.color := RBT_Red;
  165.           z := zpp;
  166.         end else
  167.         begin
  168.           if z = z^.parent^.left then
  169.           begin
  170.             z := z^.parent;
  171.             _RotateRight(z);
  172.           end;
  173.           z^.parent^.color := RBT_Black;
  174.           zpp^.color := RBT_Red;
  175.           _RotateLeft(zpp);
  176.         end;
  177.       end;
  178.     end;
  179.     _root^.color := RBT_Black;
  180.   end;
  181.  
  182.   procedure gMap._DeleteNode(z: _pRBTNode);
  183.   var
  184.     w, x, y, x_parent: _pRBTNode;
  185.     tmpcol: _tRBTNodeColor;
  186.   begin
  187.     y := z;
  188.     x := nil;
  189.     x_parent := nil;
  190.  
  191.     if Assigned(y^.left) then
  192.     begin
  193.       if Assigned(y^.right) then
  194.       begin
  195.         y := y^.right;
  196.         while Assigned(y^.left) do y := y^.left;
  197.         x := y^.right;
  198.       end else
  199.         x := y^.left;
  200.     end else
  201.       x := y^.right;
  202.  
  203.     if y <> z then
  204.     begin
  205.       // relink y in place of z. y is z's successor
  206.       z^.left^.parent := y;
  207.       y^.left := z^.left;
  208.       if y <> z^.right then
  209.       begin
  210.         x_parent := y^.parent;
  211.         if Assigned(x) then x^.parent := y^.parent;
  212.         y^.parent^.left := x; // y must be a child of left
  213.         y^.right := z^.right;
  214.         z^.right^.parent := y;
  215.       end else
  216.         x_parent := y;
  217.       if _root = z then
  218.         _root := y
  219.       else
  220.         if z^.parent^.left = z then
  221.           z^.parent^.left := y
  222.         else
  223.           z^.parent^.right := y;
  224.       y^.parent := z^.parent;
  225.       tmpcol := y^.color;
  226.       y^.color := z^.color;
  227.       z^.color := tmpcol;
  228.       y := z;
  229.     end else
  230.     begin // y = z
  231.       x_parent := y^.parent;
  232.       if Assigned(x)  then
  233.         x^.parent := y^.parent;
  234.       if _root = z then
  235.         _root := x
  236.       else
  237.         if z^.parent^.left = z then
  238.           z^.parent^.left := x
  239.         else
  240.           z^.parent^.right := x;
  241.     end;
  242.  
  243.     // rebalance
  244.     if y^.color = RBT_Black then
  245.     begin
  246.       while (x <> _root) and ((not Assigned(x)) or (x^.color = RBT_Black)) do
  247.       begin
  248.         if x = x_parent^.left then
  249.         begin
  250.           w := x_parent^.right;
  251.           if w^.color = RBT_Red then
  252.           begin
  253.             w^.color := RBT_Black;
  254.             x_parent^.color := RBT_Red;
  255.             _RotateLeft(x_parent);
  256.             w := x_parent^.right;
  257.           end;
  258.           if ((not Assigned(w^.left)) or (w^.left^.color = RBT_Black)) and
  259.              ((not Assigned(w^.right)) or (w^.right^.color = RBT_Black)) then
  260.           begin
  261.             w^.color := RBT_Red;
  262.             x := x_parent;
  263.             x_parent := x_parent^.parent;
  264.           end else
  265.           begin
  266.             if (not Assigned(w^.right)) or (w^.right^.color = RBT_Black) then
  267.             begin
  268.               w^.left^.color := RBT_Black;
  269.               w^.color := RBT_Red;
  270.               _RotateRight(w);
  271.               w := x_parent^.right;
  272.             end;
  273.             w^.color := x_parent^.color;
  274.             x_parent^.color := RBT_Black;
  275.             if Assigned(w^.right)  then w^.right^.color := RBT_Black;
  276.             _RotateLeft(x_parent);
  277.             x := _root; // break;
  278.           end;
  279.         end else
  280.         begin
  281.           // mirror of above code
  282.           w := x_parent^.left;
  283.           if (w^.color = RBT_Red)  then
  284.           begin
  285.             w^.color := RBT_Black;
  286.             x_parent^.color := RBT_Red;
  287.             _RotateRight(x_parent);
  288.             w := x_parent^.left;
  289.           end;
  290.           if ((not Assigned(w^.right)) or (w^.right^.color = RBT_Black)) and
  291.              ((not Assigned(w^.left)) or (w^.left^.color = RBT_Black)) then
  292.           begin
  293.             w^.color := RBT_Red;
  294.             x := x_parent;
  295.             x_parent := x_parent^.parent;
  296.           end else
  297.           begin
  298.             if (not Assigned(w^.left)) or (w^.left^.color = RBT_Black) then
  299.             begin
  300.               w^.right^.color := RBT_Black;
  301.               w^.color := RBT_Red;
  302.               _RotateLeft(w);
  303.               w := x_parent^.left;
  304.             end;
  305.             w^.color := x_parent^.color;
  306.             x_parent^.color := RBT_Black;
  307.             if Assigned(w^.left) then w^.left^.color := RBT_Black;
  308.             _RotateRight(x_parent);
  309.             x := _root; // break;
  310.           end;
  311.         end;
  312.       end;
  313.       if Assigned(x) then x^.color := RBT_Black;
  314.     end;
  315.  
  316.     _Finalize(y^.key, y^.data);
  317.     dispose(y);
  318.     dec(_count);
  319.   end;
  320.  
  321.   procedure gMap._ForEach(x: _pRBTNode; proc: tItemProc);
  322.   begin
  323.     if Assigned(x) then
  324.     begin
  325.       _ForEach(x^.left, proc);
  326.       _ForEach(x^.right, proc);
  327.       proc(x^.data);
  328.     end;
  329.   end;
  330.  
  331.   procedure gMap._Free(x: _pRBTNode);
  332.   begin
  333.     if Assigned(x) then
  334.     begin
  335.       _Free(x^.left);
  336.       _Free(x^.right);
  337.       _Finalize(x^.key, x^.data);
  338.       dispose(x);
  339.     end;
  340.   end;
  341.  
  342.   procedure gMap._Finalize(var key: _Key_; var item: _Item_);
  343.   begin
  344.     Assert((@key = @key) and (@item = @item));
  345.   end;
  346.  
  347.   constructor gMap.Init;
  348.   begin
  349.     inherited Init;
  350.     _count := 0;
  351.   end;
  352.  
  353.   destructor gMap.Done;
  354.   begin
  355.     Clear;
  356.     inherited Done;
  357.   end;
  358.  
  359.   procedure gMap.Add(const key: _Key_; const item: _Item_);
  360.   begin
  361.     _AddNode(key, item);
  362.   end;
  363.  
  364.   procedure gMap.Remove(const key: _Key_);
  365.   var
  366.     n: _pRBTNode;
  367.   begin
  368.     n := _FindNode(key);
  369.     if Assigned(n) then _DeleteNode(n);
  370.   end;
  371.  
  372.   procedure gMap.Clear;
  373.   begin
  374.     _Free(_root);
  375.     _root := nil;
  376.   end;
  377.  
  378.   function gMap.Find(const key: _Key_): _Item_;
  379.   var
  380.     n: _pRBTNode;
  381.   begin
  382.     n := _FindNode(key);
  383.     if Assigned(n) then
  384.       result := n^.data
  385.     else
  386.       result := _nullItem;
  387.   end;
  388.  
  389.   procedure gMap.ForEach(proc: tItemProc);
  390.   begin
  391.     _ForEach(_root, proc);
  392.   end;
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement