changeset 73:2667c3251a00

implement llrb deletion
author Shohei KOKUBO <e105744@ie.u-ryukyu.ac.jp>
date Tue, 10 Nov 2015 10:21:37 +0900
parents 5c4b9d116eda
children 724b65b1cfaf
files src/llrb/llrb.c src/llrb/llrbContext.c src/llrb/llrbContext.h src/llrb/main.c
diffstat 4 files changed, 306 insertions(+), 190 deletions(-) [+]
line wrap: on
line diff
--- a/src/llrb/llrb.c	Tue Nov 10 01:59:04 2015 +0900
+++ b/src/llrb/llrb.c	Tue Nov 10 10:21:37 2015 +0900
@@ -165,8 +165,12 @@
 
 __code colorFlip(struct Context* context, struct Node* node) {
     node->color ^= 1;
-    node->left->color ^= 1;
-    node->right->color ^= 1;
+
+    if (node->left != 0)
+        node->left->color ^= 1;
+
+    if (node->right != 0)
+        node->right->color ^= 1;
 
     stack_pop(context->code_stack, &context->next);
     goto meta(context, context->next);
@@ -244,227 +248,315 @@
 
     tree->current = tree->root;
     compare(context, tree, tree->current->key, context->data[Node]->node.key);
-    goto meta(context, Replace_d);
+    goto meta(context, Replace_d1);
 }
 
 __code delete_stub(struct Context* context) {
     goto delete(context, &context->data[Tree]->tree, &context->data[Allocate]->allocate);
 }
 
-__code replaceNode_d(struct Context* context, struct Tree* tree, struct Node* oldNode, struct Node* newNode, struct Node* node) {
+__code replaceNode_d1(struct Context* context, struct Tree* tree, struct Node* oldNode, struct Node* newNode, struct Node* node) {
     *newNode = *oldNode;
     tree->current = newNode;
     
     if (tree->result == -1) {
-        
-        if (tree->current->left != 0)
-            if (tree->current->left->left != 0)
-                if (tree->current->left->color != Red && tree->current->left->left->color != Red)
-                    goto meta(context, MoveRedL);
-        
-        stack_push(node_stack, &tree->current);
+        if (tree->current->left != 0) {
 
-        tree->current->left = context->heap;
-        tree->current = oldNode->left;
+            if (tree->current->left->left != 0)
+                if (tree->current->left->color != Red && tree->current->left->left->color != Red) {
+                    context->next = MoveRedL1;
+                    
+                    stack_push(context->code_stack, &context->next);
+                    goto meta(context, ColorFlip);
+                }
+            
+            stack_push(context->node_stack, &tree->current);
 
-        allocator(context);
-        compare(context, tree, tree->current->key, context->data[Node]->node.key);
-        
-        goto meta(context, Replace_d);
+            tree->current->left = context->heap;
+            tree->current = oldNode->left;
+
+            allocator(context);
+            compare(context, tree, tree->current->key, context->data[Node]->node.key);
+
+            goto meta(context, Replace_d1);
+        }
     } else {
         if (tree->current->left != 0)
-            if (tree->current->left->color = Red) {
+            if (tree->current->left->color == Red) {
                 allocator(context);
-                *context->data[context->dataNum]->node = *tree->current->left;
-                tree->current->left = context->data[context->dataNum]->node;
-                
-                // roatate right
-                struct Node* tmp = tree->current->left;
-                tree->current->left = tmp->right;
-                tmp->right = tree->current;
-                tmp->color = tree->current->color;
-                tree->current->color = Red;
-                tree->current = tmp;
-            }
+                context->data[context->dataNum]->node = *tree->current->left;
+                tree->current->left = &context->data[context->dataNum]->node;
 
-        if (tree->result == 0 && tree->current->right == 0) {
-            stack_pop(node_stack, &tree->current);
-
-            compare(context, tree, tree->current->key, context->data[Node]->node.key);
+                context->next = Replace_d2;
+                stack_push(context->code_stack, &context->next);
 
-            if (tree->result == 1) {
-                tree->current->right = 0;
-            } else {
-                tree->current->left = 0;
+                goto meta(context, RotateR);
             }
 
-            if (tree->current->right != 0)
-                if (tree->current->right->color == Red)
-                    goto meta(context, RotateL);
-            
-            if (tree->current->left != 0)
-                if (tree->current->left->left != 0)
-                    if (tree->current->left->color == Red && tree->current->left->left->color == Red)
-                        goto meta(context, RotateR);
-            
-            goto meta(context, FixUp);
+        goto meta(context, Replace_d2);
+    }
+}
+
+__code replaceNode_d1_stub(struct Context* context) {
+    goto replaceNode_d1(context, &context->data[Tree]->tree, context->data[Tree]->tree.current, &context->data[context->dataNum]->node, &context->data[Node]->node);
+}
+
+__code replaceNode_d2(struct Context* context, struct Tree* tree) {
+    if (tree->result == 0 && tree->current->right == 0) {
+        stack_pop(context->node_stack, &tree->current);
+
+        compare(context, tree, tree->current->key, context->data[Node]->node.key);
+        
+        if (tree->result == 1) {
+            tree->current->right = 0;
+        } else {
+            tree->current->left = 0;
         }
-            
+
+        goto meta(context, Balance1);
+    }
+
+    goto meta(context, Replace_d3);
+}
 
-        if (tree->current->right != 0) {
-            if (tree->right->left != 0) {
-                if (tree->current->right->color != Red && tree->current->right->left->color != Red) {
-                    goto meta(context, MoveRedR);
-                }
+__code replaceNode_d2_stub(struct Context* context) {
+    goto replaceNode_d2(context, &context->data[Tree]->tree);
+}
+
+__code replaceNode_d3(struct Context* context, struct Tree* tree) {
+    if (tree->current->right != 0) {
+        if (tree->current->right->left != 0)
+            if (tree->current->right->color != Red && tree->current->right->left->color != Red) {
+                context->next = MoveRedR1;
+                stack_push(context->code_stack, &context->next);
+
+                goto meta(context, ColorFlip);
             }
 
-            stack_push(node_stack, &tree->current);
-        
-            tree->current->right = context->heap;
-            tree->current = oldNode->right;
-            
-            allocator(context);
+        goto meta(context, Replace_d4);
+    }
+}
 
-            goto(context, Replace_d);
-
-        }
-        
-    allocator(context);
-    compare(context, tree, tree->current->key, context->data[Node]->node.key);
-    goto meta(context, Replace_d);
+__code replaceNode_d3_stub(struct Context* context) {
+    goto replaceNode_d3(context, &context->data[Tree]->tree);
 }
 
-__code replaceNode_d_stub(struct Context* context) {
-    goto replaceNode_d(context, &context->data[Tree]->tree, context->data[Tree]->tree.current, &context->data[context->dataNum]->node, &context->data[Node]->node);
+__code replaceNode_d4(struct Context* context, struct Tree* tree, struct Node* node) {
+    stack_push(context->node_stack, &tree->current);
+
+    if (tree->result == 0) {
+        tree->current = node->right;
+        goto meta(context, FindMin);
+    } else {
+        struct Node* next = node->right;
+        tree->current->right = context->heap;
+        tree->current = next;
+        
+        allocator(context);
+
+        compare(context, tree, tree->current->key, context->data[Node]->node.key);
+
+        goto meta(context, Replace_d1);
+    }
 }
 
-__code moveRedLeft(struct Context* context, struct Node* node) {
-    // color flip
-    node->color ^= 1;
-    node->left->color ^= 1;
-    node->right->color ^= 1;
+__code replaceNode_d4_stub(struct Context* context) {
+    goto replaceNode_d4(context, &context->data[Tree]->tree, context->data[Tree]->tree.current);
+}
 
+__code moveRedLeft1(struct Context* context, struct Tree* tree, struct Node* node) {
     if (tree->current->right != 0)
         if (tree->current->right->left != 0)
             if (tree->current->right->left == Red) {
                 allocator(context);
-                *context->data[context->dataNum]->node = *node->right;
-                node->right = context->data[context->dataNum]->node;
+                context->data[context->dataNum]->node = *node->right;
+                node->right = &context->data[context->dataNum]->node;
                 
                 allocator(context);
-                *context->data[context->dataNum]->node = *node->right->left;
-                node->right->left = context->data[context->dataNum]->node;
-
-                // rotate right
-                struct Node* tmp = node->right->left;
-                node->right->left = tmp->right;
-                tmp->right = node->right;
-                tmp->color = node->right->color;
-                node->right->color = Red;
-                node->right = tmp;
-
-                // rotate left
-                tmp = node->right;
-                node->right = tmp->left;
-                tmp->left = node;
-                tmp->color = node->color;
-                node->color = Red;
-
-                // color flip
-                node->color ^= 1;
-                node->left->color ^= 1;
-                node->right->color ^= 1;
-
-                tree->current = tmp;
+                context->data[context->dataNum]->node = *node->right->left;
+                node->right->left = &context->data[context->dataNum]->node;
+                
+                stack_push(context->node_stack, &tree->current);
+                tree->current = node->right;
+                
+                context->next = MoveRedL2;
+                stack_push(context->code_stack, &context->next);
+                
+                goto meta(context, RotateR);
             }
 
-    stack_push(node_stack, &tree->current);
+    stack_pop(context->code_stack, &context->next);
+    if (context->next == DeleteMin2)
+        goto meta(context, context->next);
 
+    stack_push(context->code_stack, &context->next);
+    stack_push(context->node_stack, &tree->current);
+    
+    struct Node* next = node->left;
     tree->current->left = context->heap;
-    tree->current = oldNode->left;
-
+    tree->current = next;
+    
     allocator(context);
     compare(context, tree, tree->current->key, context->data[Node]->node.key);
     
-    goto meta(context, Replace_d);
+    goto meta(context, Replace_d1);
+}
+
+__code moveRedLeft1_stub(struct Context* context) {
+    goto moveRedLeft1(context, &context->data[Tree]->tree, context->data[Tree]->tree.current);
+}
+ 
+__code moveRedLeft2(struct Context* context, struct Tree* tree) {
+    stack_pop(context->node_stack, &tree->current);
+
+    context->next = MoveRedL3;
+    stack_push(context->code_stack, &context->next);
+
+    context->next = ColorFlip;
+    stack_push(context->code_stack, &context->next);
+
+    goto meta(context, RotateL);
 }
 
-__code moveRedRight(struct Context* context, struct Node* node) {
-    // color flip
-    node->color ^= 1;
-    node->left->color ^= 1;
-    node->right->color ^= 1;
+__code moveRedLeft2_stub(struct Context* context) {
+    goto moveRedLeft2(context, &context->data[Tree]->tree);
+}
+
+__code moveRedLeft3(struct Context* context, struct Tree* tree) {
+    stack_pop(context->code_stack, &context->next);
+    if (context->next == DeleteMin2)
+        goto meta(context, context->next);
+
+    stack_push(context->code_stack, &context->next);
+    stack_push(context->node_stack, &tree->current);
 
+    tree->current = tree->current->left;
+    
+    compare(context, tree, tree->current->key, context->data[Node]->node.key);
+    
+    goto meta(context, Replace_d1);
+}
+
+__code moveRedLeft3_stub(struct Context* context) {
+    goto moveRedLeft3(context, &context->data[Tree]->tree);
+}
+
+__code moveRedRight1(struct Context* context, struct Tree* tree, struct Node* node) {
     if (tree->current->left != 0)
         if (tree->current->left->left != 0)
             if (tree->current->left->left == Red) {
                 allocator(context);
-                *context->data[context->dataNum]->node = *node->left;
-                node->left = context->data[context->dataNum]->node;
+                context->data[context->dataNum]->node = *node->left;
+                node->left = &context->data[context->dataNum]->node;
                 
-                // rotate right
-                struct Node* tmp = node->left;
-                node->left = tmp->right;
-                tmp->right = node;
-                tmp->color = node->color;
-                node->color = Red;
+                context->next = MoveRedR2;
+                stack_push(context->code_stack, &context->next);
+
+                context->next = ColorFlip;
+                stack_push(context->code_stack, &context->next);
+
+                goto meta(context, RotateR);
+            }
+
+    goto meta(context, Replace_d4);
+}
 
-                // color flip
-                node->color ^= 1;
-                node->left->color ^= 1;
-                node->right->color ^= 1;
+__code moveRedRight1_stub(struct Context* context) {
+    goto moveRedRight1(context, &context->data[Tree]->tree, context->data[Tree]->tree.current);
+}
+
+__code moveRedRight2(struct Context* context, struct Tree* tree) {
+    stack_push(context->node_stack, &tree->current);
+    tree->current = tree->current->right;
+    
+    compare(context, tree, tree->current->key, context->data[Node]->node.key);
+    
+    goto meta(context, Replace_d1);
+}
 
-                tree->current = tmp;
-            }
-    
-    stack_push(node_stack, &tree->current);
-    
-    tree->current->right = context->heap;
-    tree->prev = tree->current;
-    tree->current = oldNode->right;
-    
-    allocator(context);
-    if (tree->result = 0) {
-        goto meta(context, DeleteMin);
+__code moveRedRight2_stub(struct Context* context) {
+    goto moveRedRight2(context, &context->data[Tree]->tree);
+}
+
+__code findMin(struct Context* context, struct Tree* tree, struct Node* tmp) {
+    if (tree->current->left == 0) {
+        tmp->key = tree->current->key;
+        tmp->value = tree->current->value;
+            
+        stack_pop(context->node_stack, &tree->current);
+
+        tree->current->key = tmp->key;
+        tree->current->value = tmp->value;
+
+        stack_push(context->node_stack, &tree->current);
+
+        struct Node* next = tree->current->right;
+
+        tree->current->right = context->heap;
+        tree->current = next;
+
+        allocator(context);
+
+        goto meta(context, DeleteMin1);
     } else {
-        compare(context, tree, tree->current->key, context->data[Node]->node.key);
-        
-        goto meta(context, Replace_d);
+        tree->current = tree->current->left;
+
+        goto meta(context, FindMin);
     }
 }
 
-__code colorFlip_stub(struct Context* context) {
-    goto colorFlip(context, context->data[Tree]->tree.current);
+__code findMin_stub(struct Context* context) {
+    goto findMin(context, &context->data[Tree]->tree, &context->data[Node]->node);
 }
 
-__code deleteMin(struct Context* context, struct Tree* tree, struct Node* oldNode, struct Node* newNode) {
-    stack_push(node_stack, &newNode);
-    
+__code deleteMin1(struct Context* context, struct Tree* tree, struct Node* oldNode, struct Node* newNode) {
     *newNode = *oldNode;
     tree->current = newNode;
 
     if (tree->current->left == 0) {
-        newNode->left = 0;
+        struct Node* node = tree->current;
+
+        stack_pop(context->node_stack, &tree->current);
+        
+        compare(context, tree, tree->current->key, node->key);
 
-        if (tree->current->right != 0)
-            if (tree->current->right->color == Red)
-                goto meta(context, RotateL);
+        if (tree->result == -1) {
+            tree->current->left = 0;
+        } else {
+            tree->current->right = 0;
+        }
         
-        goto meta(context, FixUp);
+        goto meta(context, Balance1);
     }
 
     if (tree->current->left != 0)
         if (tree->current->left->left != 0)
-            if (tree->current->left->color != Red && tree->current->left->left->color != Red)
-                goto meta(context, MoveRedL);
+            if (tree->current->left->color != Red && tree->current->left->left->color != Red) {
+                context->next = DeleteMin2;
+                stack_push(context->code_stack, &context->next);
+
+                context->next = MoveRedL1;
+                stack_push(context->code_stack, &context->next);
+                
+                goto meta(context, ColorFlip);
+            }
 
-    tree->current = oldNode->left;
-    newNode->left = context->heap;
+    goto meta(context, DeleteMin2);
+}
+
+__code deleteMin1_stub(struct Context* context) {
+    goto deleteMin1(context, &context->data[Tree]->tree, context->data[Tree]->tree.current, &context->data[context->dataNum]->node);
+}
+
+__code deleteMin2(struct Context* context, struct Tree* tree, struct Node* node) {
+    stack_push(context->node_stack, &tree->current);
+    tree->current->left = context->heap;
+    tree->current = node->left;
 
     allocator(context);
-    goto meta(context, DeleteMin);
+    goto meta(context, DeleteMin1);
 }
 
-__code max_stub(struct Context* context) {
-    goto max(context, &context->data[Tree]->tree, context->data[Tree]->tree.current, &context->data[context->dataNum]->node);
+__code deleteMin2_stub(struct Context* context) {
+    goto deleteMin2(context, &context->data[Tree]->tree, context->data[Tree]->tree.current);
 }
--- a/src/llrb/llrbContext.c	Tue Nov 10 01:59:04 2015 +0900
+++ b/src/llrb/llrbContext.c	Tue Nov 10 10:21:37 2015 +0900
@@ -23,11 +23,19 @@
 extern __code balance2_stub(struct Context*);
 extern __code balance3_stub(struct Context*);
 extern __code get_stub(struct Context*);
+extern __code findMin_stub(struct Context*);
 extern __code delete_stub(struct Context*);
-extern __code deleteMax_stub(struct Context*);
-extern __code deleteMin_stub(struct Context*);
-extern __code replaceNode_d_stub(struct Context*);
-extern __code max_stub(struct Context*);
+extern __code replaceNode_d1_stub(struct Context*);
+extern __code replaceNode_d2_stub(struct Context*);
+extern __code replaceNode_d3_stub(struct Context*);
+extern __code replaceNode_d4_stub(struct Context*);
+extern __code moveRedLeft1_stub(struct Context*);
+extern __code moveRedLeft2_stub(struct Context*);
+extern __code moveRedLeft3_stub(struct Context*);
+extern __code moveRedRight1_stub(struct Context*);
+extern __code moveRedRight2_stub(struct Context*);
+extern __code deleteMin1_stub(struct Context*);
+extern __code deleteMin2_stub(struct Context*);
 extern __code exit_code(struct Context*);
 
 __code initLLRBContext(struct Context* context, int num) {
@@ -37,32 +45,41 @@
     context->heapStart = malloc(context->heapLimit);
 
     context->codeNum = Exit;
-    context->code[Code1]     = code1_stub;
-    context->code[Code2]     = code2_stub;
-    context->code[Code3]     = code3_stub;
-    context->code[Code4]     = code4;
-    context->code[Code5]     = code5;
-    context->code[Find]      = find;
-    context->code[Not_find]  = not_find;
-    context->code[Code6]     = code6;
-    context->code[Put]       = put_stub;
-    context->code[Replace]   = replaceNode_stub;
-    context->code[Insert]    = insertNode_stub;
-    context->code[RotateL]   = rotateLeft_stub;
-    context->code[RotateR]   = rotateRight_stub;
-    context->code[ColorFlip] = colorFlip_stub;
-    context->code[FixUp]     = fixUp_stub;
-    context->code[ChangeRef] = changeReference_stub;
-    context->code[Balance1]  = balance1_stub;
-    context->code[Balance2]  = balance2_stub;
-    context->code[Balance3]  = balance3_stub;
-    context->code[Get]       = get_stub;
-    /* context->code[Delete]    = delete_stub; */
-    /* context->code[DeleteMax] = deleteMax_stub; */
-    /* //    context->code[DeleteMin] = deleteMin_stub; */
-    /* context->code[Replace_d] = replaceNode_d_stub; */
-    /* context->code[Max]       = max_stub; */
-    context->code[Exit]      = exit_code;
+
+    context->code[Code1]      = code1_stub;
+    context->code[Code2]      = code2_stub;
+    context->code[Code3]      = code3_stub;
+    context->code[Code4]      = code4;
+    context->code[Code5]      = code5;
+    context->code[Find]       = find;
+    context->code[Not_find]   = not_find;
+    context->code[Code6]      = code6;
+    context->code[Put]        = put_stub;
+    context->code[Replace]    = replaceNode_stub;
+    context->code[Insert]     = insertNode_stub;
+    context->code[RotateL]    = rotateLeft_stub;
+    context->code[RotateR]    = rotateRight_stub;
+    context->code[ColorFlip]  = colorFlip_stub;
+    context->code[FixUp]      = fixUp_stub;
+    context->code[ChangeRef]  = changeReference_stub;
+    context->code[Balance1]   = balance1_stub;
+    context->code[Balance2]   = balance2_stub;
+    context->code[Balance3]   = balance3_stub;
+    context->code[Get]        = get_stub;
+    context->code[Delete]     = delete_stub;
+    context->code[FindMin]    = findMin_stub;
+    context->code[Replace_d1] = replaceNode_d1_stub;
+    context->code[Replace_d2] = replaceNode_d2_stub;
+    context->code[Replace_d3] = replaceNode_d3_stub;
+    context->code[Replace_d4] = replaceNode_d4_stub;
+    context->code[MoveRedL1]  = moveRedLeft1_stub;
+    context->code[MoveRedL2]  = moveRedLeft2_stub;
+    context->code[MoveRedL3]  = moveRedLeft3_stub;
+    context->code[MoveRedR1]  = moveRedRight1_stub;
+    context->code[MoveRedR2]  = moveRedRight2_stub;
+    context->code[DeleteMin1] = deleteMin1_stub;
+    context->code[DeleteMin2] = deleteMin2_stub;
+    context->code[Exit]       = exit_code;
     
     context->heap = context->heapStart;
 
--- a/src/llrb/llrbContext.h	Tue Nov 10 01:59:04 2015 +0900
+++ b/src/llrb/llrbContext.h	Tue Nov 10 10:21:37 2015 +0900
@@ -27,11 +27,19 @@
     Balance2,
     Balance3,
     Get,
+    FindMin,
     Delete,
-    DeleteMax,
-    DeleteMin,
-    Replace_d,
-    Max,
+    Replace_d1,
+    Replace_d2,
+    Replace_d3,
+    Replace_d4,
+    MoveRedL1,
+    MoveRedL2,
+    MoveRedL3,
+    MoveRedR1,
+    MoveRedR2,
+    DeleteMin1,
+    DeleteMin2,
     Exit,
 };
 
--- a/src/llrb/main.c	Tue Nov 10 01:59:04 2015 +0900
+++ b/src/llrb/main.c	Tue Nov 10 10:21:37 2015 +0900
@@ -25,7 +25,7 @@
         print_tree(node->left, n+1);
         for (int i=0;i<n;i++)
             printf("  ");
-        printf(/*"key=%d value=%d depth=%d */"color=%s\t%p\n", /*node->key, node->value, n, */node->color==0? "R":"B", node);
+        printf("key=%d value=%d color=%s\t%p\n", node->key, node->value,/* n, */node->color==0? "R":"B", node);
         print_tree(node->right, n+1);
     }
 }
@@ -88,12 +88,11 @@
     print_tree(context->data[Tree]->tree.root, 0);
     
     struct Node* node = &context->data[Node]->node;
-    node->key = 0;
-    node->value = 0;
+    node->key = 5;
     
     context->next = Code5;
 
-    goto meta(context, DeleteMax);
+    goto meta(context, Delete);
 }
 
 __code code5(struct Context* context) {