Advertisement
Guest User

Untitled

a guest
Mar 9th, 2015
245
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
D 3.89 KB | None | 0 0
  1. struct Link(N) {
  2. private:
  3.     N* child;
  4.  
  5. public:
  6.     this(N* n, Color c) {
  7.         child = cast(N*) ((cast(size_t) n) | c);
  8.     }
  9.    
  10.     auto getAs(Color c) {
  11.         return Link(node(), c);
  12.     }
  13.    
  14.     N* node() const {
  15.         return cast(N*) ((cast(size_t) child) & ~0x01);
  16.     }
  17.    
  18.     Color color() const {
  19.         return cast(Color) ((cast(size_t) child) & 0x01);
  20.     }
  21.    
  22.     bool isRed() const {
  23.         return color() == Color.Red;
  24.     }
  25.    
  26.     bool isBlack() const {
  27.         return color() == Color.Black;
  28.     }
  29.  
  30. private:
  31.     // Rotate the tree and return the new root.
  32.     auto rotateLeft() {
  33.         auto right = node().right;
  34.         node().right = right.node().left;
  35.         right.node().left = node();
  36.         return right;
  37.     }
  38.    
  39.     // Rotate the tree and return the new root.
  40.     auto rotateRight() {
  41.         auto left = node().left;
  42.         node().left = left.node().right;
  43.         left.node().right = node();
  44.         return left;
  45.     }
  46. }
  47.  
  48. enum Color {
  49.     Black = false,
  50.     Red = true,
  51. }
  52.  
  53. // Insert a new node in the tree.
  54. auto rb_insert(N)(N* root, N* n) {
  55.     // rbtree's depth is ln(n) which is at most 8 * size_t.sizeof.
  56.     // But a branch can be at most 2* longer than the shortest one.
  57.     Path!N[16 * size_t.sizeof] path; // TODO: make this void initialized.
  58.     auto stackp = &path[0]; // TODO: use .ptr when available.
  59.    
  60.     // Root is always black.
  61.     stackp.link = Link!N(root, Color.Black);
  62.    
  63.     while (stackp.node !is null) {
  64.         auto cmp = stackp.cmp = n.opCmp(stackp.node);
  65.         assert(cmp != 0);
  66.        
  67.         auto link = stackp.link;
  68.         stackp++;
  69.         stackp.link = (cmp < 0)
  70.             ? stackp.link.node().left
  71.             : stackp.link.node().right;
  72.     }
  73.    
  74.     // Inserted node is always red.
  75.     stackp.link = Link!N(n, Color.Red);
  76.    
  77.     // Now we found an insertion point, let's fix the tree.
  78.     for (stackp--; stackp !is &path[-1]; stackp--) {
  79.         auto link = stackp.link;
  80.         if (stackp.cmp < 0) {
  81.             auto left = link.node().left = stackp[1].link;
  82.             if (left.isBack()) {
  83.                 return;
  84.             }
  85.            
  86.             auto leftleft = left.node().left;
  87.             if (leftleft.isBlack()) {
  88.                 continue;
  89.             }
  90.            
  91.             /**
  92.              * l = left
  93.              * b = changed to black
  94.              *
  95.              * NB: Because of the handling of the right branch,
  96.              * it is impossible to have 2 red node on the right.
  97.              *
  98.              *      B
  99.              *     /         Rl
  100.              *    Rl   =>   / \
  101.              *   /         Rb  B
  102.              *  R
  103.              */
  104.             left.get().left = leftleft.getAs(Color.Black);
  105.             stackp.link = link.rotateRight();
  106.         } else {
  107.             auto right = link.node().right = stackp[1].link;
  108.             if (right.isBlack()) {
  109.                 return;
  110.             }
  111.            
  112.             auto left = link.node().left;
  113.             if (left.isRed()) {
  114.                 /**
  115.                  * r = right
  116.                  * b = changed to black
  117.                  * r = changed to red
  118.                  *
  119.                  * NB: Because left is red, we know link is black.
  120.                  * NB: We can't have 2 red nodes on the right.
  121.                  *
  122.                  *    B             Br
  123.                  *   / \           / \
  124.                  *  R   R    =>   Rb  Rb
  125.                  *     / \           / \
  126.                  *    R   B         R   B
  127.                  */
  128.                 link.node().left = left.getAs(Color.Back);
  129.                 link.node().right = right.getAs(Color.Back);
  130.                 stackp.link = link.getAs(Color.Red);
  131.                 continue;
  132.             }
  133.            
  134.             /**
  135.              *                  R
  136.              * This ensure that  \  is impossible.
  137.              *                    R
  138.              *
  139.              * l = left
  140.              * b = changed to black
  141.              * r = changed to red
  142.              *
  143.              * If we have 2 red node on the right at link level
  144.              * we rebalance to have them on the left and push
  145.              * the problem one level up.
  146.              *
  147.              *                R
  148.              *    R          /
  149.              *   / \   =>   R
  150.              *  B   R      /
  151.              *            B
  152.              *
  153.              * Or we have 2 red on the left, in which case
  154.              * the link must be black.
  155.              *
  156.              *    B             Rb
  157.              *   / \           / \
  158.              *  B   R    =>   Br  B
  159.              *     / \       / \
  160.              *    R   B     B   R
  161.              *
  162.              * And it is all screwed up :( What is wrong here ?
  163.              */
  164.             auto l = link.rotateLeft().getAs(link.color());
  165.             l.node().left = link.getAs(Color.Red);
  166.             stackp.link = l;
  167.         }
  168.     }
  169.    
  170.     return stackp.link.node();
  171. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement