Last active
July 8, 2025 02:06
-
-
Save mistymntncop/3fd09e83d6df306c6a2a2bead05ab2cd to your computer and use it in GitHub Desktop.
Revisions
-
mistymntncop revised this gist
Jul 8, 2025 . 1 changed file with 2 additions and 19 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -26,10 +26,7 @@ enum Color { typedef struct Node Node; struct Node { uint64_t key; uint64_t value; Color color; uint32_t ref_count; Node *children[NODE_CHILD_COUNT]; @@ -52,7 +49,6 @@ struct ZipperNode { bool dirty; bool dont_release; ZipperNode *prev; }; @@ -82,7 +78,7 @@ static void node_release(Node *node) { for(uint32_t i = 0; i < NODE_CHILD_COUNT; i++) { node_release(node->children[i]); } free(node); } } @@ -236,18 +232,6 @@ static void flip_color(Zipper *zipper) { update_color(zipper, !zipper->focus->color); } static bool insert(Zipper *zipper, uint64_t key, uint64_t value) { bool insert_node = true; while(zipper->focus != 0) { @@ -314,7 +298,6 @@ static void print_rb_tree_recurse(Node *node) { print_rb_tree_recurse(child); } } } static void print_rb_tree(Node *node) { -
mistymntncop revised this gist
Jul 7, 2025 . 1 changed file with 3 additions and 4 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -262,7 +262,7 @@ static bool insert(Zipper *zipper, uint64_t key, uint64_t value) { } else if(key > node->key) { go_down(zipper, RIGHT); } else { update(zipper, value); insert_node = false; break; } @@ -292,9 +292,8 @@ static bool insert(Zipper *zipper, uint64_t key, uint64_t value) { node = zipper->focus; } } update_color(zipper, BLACK); return insert_node; } -
mistymntncop revised this gist
Jul 7, 2025 . 1 changed file with 19 additions and 19 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -248,7 +248,8 @@ static void move_red_left(Zipper *zipper) { } } static bool insert(Zipper *zipper, uint64_t key, uint64_t value) { bool insert_node = true; while(zipper->focus != 0) { Node *node = zipper->focus; @@ -261,19 +262,21 @@ static void insert(Zipper *zipper, uint64_t key, uint64_t value) { } else if(key > node->key) { go_down(zipper, RIGHT); } else { node->value = value; insert_node = false; break; } } if(insert_node) { Node *new_node = calloc(1, sizeof(Node)); new_node->key = key; new_node->value = value; new_node->color = RED; new_node->ref_count = 1; zipper->focus = new_node; zipper->dirty = true; } while(zipper->path != 0) { go_up(zipper); Node *node = zipper->focus; @@ -289,20 +292,17 @@ static void insert(Zipper *zipper, uint64_t key, uint64_t value) { node = zipper->focus; } } if(insert_node) { update_color(zipper, BLACK); } return insert_node; } static Zipper init_zipper(Node *root) { Zipper zipper = { .focus = root }; return zipper; } static void print_rb_tree_recurse(Node *node) { printf("\tn_%lld_%p [label=\"%lld\\nrc: %d\"];\n", node->key, node, node->key, node->ref_count); for(uint32_t i = 0; i < NODE_CHILD_COUNT; i++) { -
mistymntncop revised this gist
Jul 7, 2025 . 1 changed file with 5 additions and 3 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -304,12 +304,14 @@ static void rb_insert(Tree *tree, uint64_t key, uint64_t value) { } static void print_rb_tree_recurse(Node *node) { printf("\tn_%lld_%p [label=\"%lld\\nrc: %d\"];\n", node->key, node, node->key, node->ref_count); for(uint32_t i = 0; i < NODE_CHILD_COUNT; i++) { Node *child = node->children[i]; if(child) { char *color = child->color == RED ? "red" : "black"; uint32_t penwidth = child->color == RED ? 5 : 1; printf("\t" "n_%lld_%p -> n_%lld_%p [color=\"%s\", penwidth=%d, dir=none];\n", node->key, node, child->key, child, color, penwidth ); print_rb_tree_recurse(child); } } -
mistymntncop revised this gist
Jul 7, 2025 . 1 changed file with 2 additions and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -308,7 +308,8 @@ static void print_rb_tree_recurse(Node *node) { for(uint32_t i = 0; i < NODE_CHILD_COUNT; i++) { Node *child = node->children[i]; if(child) { printf("\t" "n%p -> n%p [color=\"%s\"];\n", node, child, child->color == RED ? "red" : "blue"); print_rb_tree_recurse(child); } } -
mistymntncop revised this gist
Jul 7, 2025 . 1 changed file with 31 additions and 65 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -150,7 +150,6 @@ static void go_up(Zipper *zipper) { dirty = true; } new_focus->children[child_index] = current; if(!zipper->dont_release) { node_release(original_child); } @@ -186,7 +185,6 @@ static void update_child(Zipper *zipper, uint32_t child_index, Node *child, bool Node *node = mutable_focus(zipper); Node *original_child = node->children[child_index]; node->children[child_index] = child; if(!dont_release) { node_release(original_child); } @@ -305,77 +303,45 @@ static void rb_insert(Tree *tree, uint64_t key, uint64_t value) { } static void print_rb_tree_recurse(Node *node) { printf("\tn%p [label=\"%lld\\nrc: %d\"];\n", node, node->key, node->ref_count); for(uint32_t i = 0; i < NODE_CHILD_COUNT; i++) { Node *child = node->children[i]; if(child) { printf("\t" "n%p -> n%p;\n", node, child); print_rb_tree_recurse(child); } } } static void print_rb_tree(Node *node) { printf("strict digraph BST {\n"); print_rb_tree_recurse(node); printf("}\n"); } int main() { Zipper zipper = init_zipper(0); for(uint32_t i = 0; i < 10; i++) { insert(&zipper, i, i); } Node *root = commit(&zipper); zipper = init_zipper(root); for(uint32_t i = 10; i < 20; i++) { insert(&zipper, i, i); } Node *root2 = commit(&zipper); printf("strict digraph BST {\n"); print_rb_tree_recurse(root); print_rb_tree_recurse(root2); printf("}\n"); return 0; } -
mistymntncop revised this gist
Jul 7, 2025 . 1 changed file with 30 additions and 19 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -5,6 +5,10 @@ #include <malloc.h> #include <assert.h> //Partially Persistent Left-Leaning Red-Black Tree //Implemented using Zippers //https://sedgewick.io/wp-content/themes/sedgewick/papers/2008LLRB.pdf //Just pedagogical. No proper memory managagement here, would use Arenas in practice // cl -Zi -Od /INCREMENTAL:NO zipper.c enum { @@ -72,7 +76,7 @@ static Node *node_acquire(Node *node) { static void node_release(Node *node) { if(node == 0) return; assert(node->ref_count != 0); if(--node->ref_count == 0) { for(uint32_t i = 0; i < NODE_CHILD_COUNT; i++) { @@ -168,13 +172,18 @@ static Node *commit(Zipper *zipper) { return root; } static Node *mutable_focus(Zipper *zipper) { Node *node = zipper->focus; if(!zipper->dirty) { node = node_clone(node); zipper->focus = node; zipper->dirty = true; } return node; } static void update_child(Zipper *zipper, uint32_t child_index, Node *child, bool dont_release) { Node *node = mutable_focus(zipper); Node *original_child = node->children[child_index]; node->children[child_index] = child; //node_acquire(child); @@ -184,27 +193,17 @@ static void update_child(Zipper *zipper, uint32_t child_index, Node *child, bool } static void update_color(Zipper *zipper, Color color) { Node *node = mutable_focus(zipper); node->color = color; } static void update(Zipper *zipper, uint64_t value) { Node *node = mutable_focus(zipper); node->value = value; } static void rotate_left(Zipper *zipper) { Node *h = mutable_focus(zipper); Color color = h->color; Node *x = h->children[RIGHT]; update_child(zipper, RIGHT, x->children[LEFT], true); @@ -217,7 +216,7 @@ static void rotate_left(Zipper *zipper) { } static void rotate_right(Zipper *zipper) { Node *h = mutable_focus(zipper); Color color = h->color; Node *x = h->children[LEFT]; update_child(zipper, LEFT, x->children[RIGHT], true); @@ -239,6 +238,18 @@ static void flip_color(Zipper *zipper) { update_color(zipper, !zipper->focus->color); } static void move_red_left(Zipper *zipper) { Node *node = zipper->focus; flip_color(zipper); if(node->children[RIGHT] && is_red(node->children[RIGHT]->children[LEFT])) { go_down(zipper, RIGHT); rotate_right(zipper); go_up(zipper); rotate_left(zipper); flip_color(zipper); } } static void insert(Zipper *zipper, uint64_t key, uint64_t value) { while(zipper->focus != 0) { Node *node = zipper->focus; @@ -253,7 +264,7 @@ static void insert(Zipper *zipper, uint64_t key, uint64_t value) { go_down(zipper, RIGHT); } else { assert(!"moo"); return; //TODO: better story } } Node *new_node = calloc(1, sizeof(Node)); @@ -320,14 +331,14 @@ int main() { #endif root = commit(&zipper); //A Node *root2 = 0; { Zipper zipper = init_zipper(root); for(uint32_t i = 10; i < 20; i++) { insert(&zipper, i, i); } root2 = commit(&zipper); int lol = 3; } -
mistymntncop revised this gist
Jul 7, 2025 . 1 changed file with 8 additions and 6 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -168,7 +168,7 @@ static Node *commit(Zipper *zipper) { return root; } static void update_child(Zipper *zipper, uint32_t child_index, Node *child, bool dont_release) { Node *node = zipper->focus; if(!zipper->dirty) { node = node_clone(node); @@ -178,7 +178,9 @@ static void update_child(Zipper *zipper, uint32_t child_index, Node *child) { Node *original_child = node->children[child_index]; node->children[child_index] = child; //node_acquire(child); if(!dont_release) { node_release(original_child); } } static void update_color(Zipper *zipper, Color color) { @@ -205,25 +207,25 @@ static void rotate_left(Zipper *zipper) { Node *h = zipper->focus; Color color = h->color; Node *x = h->children[RIGHT]; update_child(zipper, RIGHT, x->children[LEFT], true); update_color(zipper, RED); zipper->focus = x; zipper->dirty = x->ref_count == 1; zipper->dont_release = true; update_child(zipper, LEFT, h, true); update_color(zipper, color); } static void rotate_right(Zipper *zipper) { Node *h = zipper->focus; Color color = h->color; Node *x = h->children[LEFT]; update_child(zipper, LEFT, x->children[RIGHT], true); update_color(zipper, RED); zipper->focus = x; zipper->dirty = x->ref_count == 1; zipper->dont_release = true; update_child(zipper, RIGHT, h, true); update_color(zipper, color); } -
mistymntncop revised this gist
Jul 6, 2025 . 1 changed file with 216 additions and 93 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -6,37 +6,56 @@ #include <assert.h> //Just pedagogical. No proper memory managagement here, would use Arenas in practice // cl -Zi -Od /INCREMENTAL:NO zipper.c enum { LEFT = 0, RIGHT = 1, NODE_CHILD_COUNT = 2, }; typedef enum Color Color; enum Color { RED = 1, BLACK = 0, }; typedef struct Node Node; struct Node { uint64_t key; union { //char value_u8; uint64_t value; }; Color color; uint32_t ref_count; Node *children[NODE_CHILD_COUNT]; }; typedef struct Tree Tree; struct Tree { Node **roots; uint32_t roots_count; //Arena *roots_arena; //Arena *nodes_arena; //Node **free_list; }; typedef struct ZipperNode ZipperNode; struct ZipperNode { Node *parent; uint32_t child_index; bool dirty; bool dont_release; ZipperNode *prev; }; typedef struct Zipper Zipper; struct Zipper { bool dirty; bool dont_release; //context Node *focus; @@ -45,86 +64,66 @@ struct Zipper { uint32_t path_count; }; static Node *node_acquire(Node *node) { if(node == 0) return 0; node->ref_count++; return node; } static void node_release(Node *node) { if(node == 0) return; //assert(node->ref_count != 0); if(--node->ref_count == 0) { for(uint32_t i = 0; i < NODE_CHILD_COUNT; i++) { node_release(node->children[i]); } //free(node); } } static Node *node_clone(Node *src) { Node *node = calloc(1, sizeof(Node)); node->key = src->key; node->value = src->value; node->color = src->color; node->ref_count = 1; for(uint32_t i = 0; i < NODE_CHILD_COUNT; i++) { node->children[i] = node_acquire(src->children[i]); } return node; } static bool is_red(Node *node) { bool result = node && node->color == RED; return result; } static void go_down(Zipper *zipper, uint32_t child_index) { Node *current = zipper->focus; bool dirty = false; assert(child_index < NODE_CHILD_COUNT); Node *child = current ? current->children[child_index] : 0; if(zipper->dirty && child && child->ref_count == 1) { dirty = true; } ZipperNode *path_node = calloc(1, sizeof(ZipperNode)); path_node->parent = current; path_node->child_index = child_index; path_node->dirty = zipper->dirty; path_node->dont_release = zipper->dont_release; path_node->prev = zipper->path; zipper->path = path_node; zipper->path_count++; zipper->focus = child; zipper->dirty = dirty; zipper->dont_release = false; } static void go_up(Zipper *zipper) { @@ -137,25 +136,31 @@ static void go_up(Zipper *zipper) { Node *parent = path_node->parent; Node *new_focus = parent; uint32_t child_index = path_node->child_index; bool dirty = path_node->dirty; Node *original_child = parent ? parent->children[child_index] : 0; if(original_child != current) { if(zipper->dirty && !dirty) { Node *new_parent = node_clone(parent); new_focus = new_parent; dirty = true; } new_focus->children[child_index] = current; //node_acquire(current); if(!zipper->dont_release) { node_release(original_child); } } zipper->focus = new_focus; zipper->dirty = dirty; zipper->dont_release = path_node->dont_release; free(path_node); } } static Node *commit(Zipper *zipper) { while(zipper->path != 0) { go_up(zipper); } @@ -165,80 +170,198 @@ Node *commit(Zipper *zipper) { static void update_child(Zipper *zipper, uint32_t child_index, Node *child) { Node *node = zipper->focus; if(!zipper->dirty) { node = node_clone(node); zipper->focus = node; zipper->dirty = true; } Node *original_child = node->children[child_index]; node->children[child_index] = child; //node_acquire(child); //node_release(original_child); } static void update_color(Zipper *zipper, Color color) { Node *node = zipper->focus; if(!zipper->dirty) { node = node_clone(node); zipper->focus = node; zipper->dirty = true; } node->color = color; } static void update(Zipper *zipper, uint64_t value) { Node *node = zipper->focus; if(!zipper->dirty) { node = node_clone(node); zipper->focus = node; zipper->dirty = true; } node->value = value; } static void rotate_left(Zipper *zipper) { Node *h = zipper->focus; Color color = h->color; Node *x = h->children[RIGHT]; update_child(zipper, RIGHT, x->children[LEFT]); update_color(zipper, RED); zipper->focus = x; zipper->dirty = x->ref_count == 1; zipper->dont_release = true; update_child(zipper, LEFT, h); update_color(zipper, color); } static void rotate_right(Zipper *zipper) { Node *h = zipper->focus; Color color = h->color; Node *x = h->children[LEFT]; update_child(zipper, LEFT, x->children[RIGHT]); update_color(zipper, RED); zipper->focus = x; zipper->dirty = x->ref_count == 1; zipper->dont_release = true; update_child(zipper, RIGHT, h); update_color(zipper, color); } static void flip_color(Zipper *zipper) { go_down(zipper, LEFT); update_color(zipper, !zipper->focus->color); go_up(zipper); go_down(zipper, RIGHT); update_color(zipper, !zipper->focus->color); go_up(zipper); update_color(zipper, !zipper->focus->color); } static void insert(Zipper *zipper, uint64_t key, uint64_t value) { while(zipper->focus != 0) { Node *node = zipper->focus; if(is_red(node->children[LEFT]) && is_red(node->children[RIGHT])) { flip_color(zipper); } if(key < node->key) { go_down(zipper, LEFT); } else if(key > node->key) { go_down(zipper, RIGHT); } else { assert(!"moo"); return; } } Node *new_node = calloc(1, sizeof(Node)); new_node->key = key; new_node->value = value; new_node->color = RED; new_node->ref_count = 1; zipper->focus = new_node; zipper->dirty = true; while(zipper->path != 0) { go_up(zipper); Node *node = zipper->focus; //balancing if(is_red(node->children[RIGHT]) && !is_red(node->children[LEFT])) { rotate_left(zipper); node = zipper->focus; } if(is_red(node->children[LEFT]) && is_red(node->children[LEFT]->children[LEFT])) { rotate_right(zipper); node = zipper->focus; } } update_color(zipper, BLACK); } static Zipper init_zipper(Node *root) { Zipper zipper = { .focus = root }; return zipper; } static void rb_insert(Tree *tree, uint64_t key, uint64_t value) { } int main() { // A // / \ // B F // / \ / // D E C Node *root = 0; Zipper zipper = init_zipper(0); //A #if 1 for(uint32_t i = 0; i < 10; i++) { insert(&zipper, i, i); } #else insert(&zipper, 50, 'A'); insert(&zipper, 25, 'B'); insert(&zipper, 75, 'C'); insert(&zipper, 12, 'D'); insert(&zipper, 30, 'E'); insert(&zipper, 83, 'F'); #endif root = commit(&zipper); //A { Zipper zipper = init_zipper(root); for(uint32_t i = 10; i < 20; i++) { insert(&zipper, i, i); } Node *root2 = commit(&zipper); int lol = 3; } int lol = 3; /* Zipper zipper = init_zipper(root); //A //update(&zipper, 'W'); //A->W //update(&zipper, 'X'); //W->X go_down(&zipper, LEFT); //B update(&zipper, 'P'); go_down(&zipper, LEFT); //D update(&zipper, 'Y'); //D->Y go_up(&zipper); //B' go_down(&zipper, RIGHT); //E update(&zipper, 'Z'); //Z Node *new_root = commit(&zipper); //X */ // X // / \ // B' C // / \ \ // Y Z F return 0; -
mistymntncop revised this gist
May 16, 2025 . 1 changed file with 10 additions and 7 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -72,6 +72,7 @@ static Node *node_clone(Node *src) { return node; } static Node **bst_search(Node **root_ptr, uint64_t key) { Node **node_ptr = root_ptr; @@ -111,7 +112,7 @@ static void go_down(Zipper *zipper, uint32_t child_index) { assert(child_index < NODE_CHILD_COUNT); Node *child = current->children[child_index]; Node *original_child = original ? original->children[child_index] : 0; ZipperNode *path_node = calloc(1, sizeof(ZipperNode)); path_node->parent = current; @@ -135,14 +136,16 @@ static void go_up(Zipper *zipper) { Node *current = zipper->focus; Node *parent = path_node->parent; Node *new_focus = parent; uint32_t child_index = path_node->child_index; Node *original_child = parent->children[child_index]; if(original_child != current) { if(path_node->original == parent) { Node *new_parent = node_clone(parent); new_focus = new_parent; } node_release(original_child); new_focus->children[child_index] = current; } zipper->focus = new_focus; @@ -182,8 +185,8 @@ static void update(Zipper *zipper, uint64_t value) { } static void replace(Zipper *zipper, Node *new_node) { //Node *old_node = zipper->focus; //node_release(old_node); zipper->focus = new_node; } @@ -192,7 +195,7 @@ Zipper init_zipper(Node *root) { return zipper; } int main() { Node *root = 0; bst_insert(&root, 50, 'A'); bst_insert(&root, 25, 'B'); -
mistymntncop revised this gist
May 16, 2025 . 1 changed file with 20 additions and 17 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -11,6 +11,7 @@ typedef struct Node Node; struct Node { uint64_t key; uint64_t value; uint32_t ref_count; Node *children[NODE_CHILD_COUNT]; @@ -60,8 +61,9 @@ void node_release(Node *node) { } } static Node *node_clone(Node *src) { Node *node = malloc(sizeof(Node)); node->key = src->key; node->value = src->value; node->ref_count = 1; for(uint32_t i = 0; i < NODE_CHILD_COUNT; i++) { @@ -70,15 +72,15 @@ Node *node_clone(Node *src) { return node; } static Node **bst_search(Node **root_ptr, uint64_t key) { Node **node_ptr = root_ptr; while((*node_ptr)) { Node *node = *node_ptr; if(key < node->key) { node_ptr = &node->children[0]; } else if(key > node->key) { node_ptr = &node->children[1]; } else { return node_ptr; @@ -87,14 +89,15 @@ Node **bst_search(Node **root_ptr, uint64_t find) { return node_ptr; } static Node *bst_insert(Node **root_ptr, uint64_t key, uint64_t value) { Node **best_match_ptr = bst_search(root_ptr, key); Node *best_match = *best_match_ptr; if(best_match && best_match->key == key) { return 0; } Node *node = calloc(1, sizeof(Node)); node->ref_count = 1; node->key = key; node->value = value; *best_match_ptr = node; @@ -191,12 +194,12 @@ Zipper init_zipper(Node *root) { int main() { Node *root = 0; bst_insert(&root, 50, 'A'); bst_insert(&root, 25, 'B'); bst_insert(&root, 75, 'C'); bst_insert(&root, 12, 'D'); bst_insert(&root, 83, 'E'); bst_insert(&root, 30, 'F'); // 50 // / \ @@ -206,20 +209,20 @@ int main() { Zipper zipper = init_zipper(root); update(&zipper, 'W'); update(&zipper, 'X'); go_down(&zipper, 0); go_down(&zipper, 0); update(&zipper, 'Y'); go_up(&zipper); go_down(&zipper, 1); update(&zipper, 'Z'); Node *new_root = commit(&zipper); -
mistymntncop revised this gist
May 16, 2025 . 1 changed file with 50 additions and 18 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -12,6 +12,7 @@ typedef struct Node Node; struct Node { uint64_t value; uint32_t ref_count; Node *children[NODE_CHILD_COUNT]; }; @@ -33,16 +34,42 @@ struct ZipperNode { typedef struct Zipper Zipper; struct Zipper { //focus in the unmodified tree Node *original; //context Node *focus; ZipperNode *path; uint32_t path_count; }; Node *node_acquire(Node *node) { if(node == 0) return 0; node->ref_count++; return node; } void node_release(Node *node) { if(node == 0) return; if(--node->ref_count == 0) { for(uint32_t i = 0; i < NODE_CHILD_COUNT; i++) { node_release(node->children[i]); } free(node); } } Node *node_clone(Node *src) { Node *node = malloc(sizeof(Node)); node->value = src->value; node->ref_count = 1; for(uint32_t i = 0; i < NODE_CHILD_COUNT; i++) { node->children[i] = node_acquire(src->children[i]); } return node; } Node **bst_search(Node **root_ptr, uint64_t find) { Node **node_ptr = root_ptr; @@ -67,14 +94,15 @@ Node *bst_insert(Node **root_ptr, uint64_t value) { return 0; } Node *node = calloc(1, sizeof(Node)); node->ref_count = 1; node->value = value; *best_match_ptr = node; return node; } static void go_down(Zipper *zipper, uint32_t child_index) { Node *current = zipper->focus; Node *original = zipper->original; @@ -95,28 +123,29 @@ void go_down(Zipper *zipper, uint32_t child_index) { zipper->original = original_child; } static void go_up(Zipper *zipper) { if(zipper->path != 0) { ZipperNode *path_node = zipper->path; zipper->path = path_node->prev; zipper->path_count--; Node *current = zipper->focus; Node *parent = path_node->parent; Node *new_focus = parent; Node *original_child = parent->children[path_node->child_index]; if(original_child != current) { if(path_node->original == parent) { Node *new_parent = node_clone(parent); new_focus = new_parent; } new_focus->children[path_node->child_index] = current; } zipper->focus = new_focus; zipper->original = path_node->original; free(path_node); } } @@ -128,27 +157,30 @@ Node *commit(Zipper *zipper) { return root; } static void update_child(Zipper *zipper, uint32_t child_index, Node *child) { Node *node = zipper->focus; if(node == zipper->original) { node = node_clone(node); zipper->focus = node; } Node *original_child = node->children[child_index]; node_release(original_child); node->children[child_index] = child; } static void update(Zipper *zipper, uint64_t value) { Node *node = zipper->focus; if(node == zipper->original) { node = node_clone(node); zipper->focus = node; } node->value = value; } static void replace(Zipper *zipper, Node *new_node) { Node *old_node = zipper->focus; node_release(old_node); zipper->focus = new_node; } -
mistymntncop revised this gist
May 14, 2025 . 1 changed file with 12 additions and 9 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -128,15 +128,14 @@ Node *commit(Zipper *zipper) { return root; } void update_child(Zipper *zipper, uint32_t child_index, Node *children) { Node *node = zipper->focus; if(node == zipper->original) { node = malloc(sizeof(Node)); memcpy(node, zipper->focus, sizeof(*node)); zipper->focus = node; } node->children[child_index] = children; } void update(Zipper *zipper, uint64_t value) { @@ -149,6 +148,10 @@ void update(Zipper *zipper, uint64_t value) { node->value = value; } void replace(Zipper *zipper, Node *new_node) { zipper->focus = new_node; } Zipper init_zipper(Node *root) { Zipper zipper = { .focus = root, .original = root }; return zipper; -
mistymntncop revised this gist
May 14, 2025 . 1 changed file with 8 additions and 2 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -76,21 +76,23 @@ Node *bst_insert(Node **root_ptr, uint64_t value) { void go_down(Zipper *zipper, uint32_t child_index) { Node *current = zipper->focus; Node *original = zipper->original; assert(child_index < NODE_CHILD_COUNT); Node *child = current->children[child_index]; Node *original_child = original->children[child_index]; ZipperNode *path_node = calloc(1, sizeof(ZipperNode)); path_node->parent = current; path_node->child_index = child_index; path_node->original = original; path_node->prev = zipper->path; zipper->path = path_node; zipper->path_count++; zipper->focus = child; zipper->original = original_child; } void go_up(Zipper *zipper) { @@ -186,6 +188,10 @@ int main() { Node *new_root = commit(&zipper); go_down(&zipper, 0); go_down(&zipper, 0); // 2222 // / \ -
mistymntncop revised this gist
May 14, 2025 . 1 changed file with 7 additions and 0 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -185,6 +185,13 @@ int main() { update(&zipper, 777); Node *new_root = commit(&zipper); // 2222 // / \ // 25 75 // / \ \ // 666 777 83 return 0; -
mistymntncop revised this gist
May 14, 2025 . 1 changed file with 15 additions and 4 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -138,10 +138,13 @@ void replace(Zipper *zipper, Node *new_node) { } void update(Zipper *zipper, uint64_t value) { Node *node = zipper->focus; if(node == zipper->original) { node = malloc(sizeof(Node)); memcpy(node, zipper->focus, sizeof(*node)); zipper->focus = node; } node->value = value; } Zipper init_zipper(Node *root) { @@ -158,9 +161,17 @@ int main() { bst_insert(&root, 83); bst_insert(&root, 30); // 50 // / \ // 25 75 // / \ \ // 12 30 83 Zipper zipper = init_zipper(root); update(&zipper, 1111); update(&zipper, 2222); go_down(&zipper, 0); go_down(&zipper, 0); -
mistymntncop revised this gist
May 14, 2025 . 1 changed file with 1 addition and 2 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -91,7 +91,6 @@ void go_down(Zipper *zipper, uint32_t child_index) { zipper->focus = child; zipper->original = child; } void go_up(Zipper *zipper) { @@ -161,8 +160,8 @@ int main() { Zipper zipper = init_zipper(root); //update(&zipper, 1111); go_down(&zipper, 0); go_down(&zipper, 0); -
mistymntncop renamed this gist
May 14, 2025 . 1 changed file with 0 additions and 0 deletions.There are no files selected for viewing
File renamed without changes. -
mistymntncop created this gist
May 14, 2025 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,181 @@ #include <stdio.h> #include <stdlib.h> #include <stdint.h> #include <stdbool.h> #include <malloc.h> #include <assert.h> //Just pedagogical. No proper memory managagement here, would use Arenas in practice #define NODE_CHILD_COUNT 2 typedef struct Node Node; struct Node { uint64_t value; Node *children[NODE_CHILD_COUNT]; }; typedef struct Tree Tree; struct Tree { Node *root; uint32_t node_count; }; typedef struct ZipperNode ZipperNode; struct ZipperNode { Node *parent; uint32_t child_index; Node *original; ZipperNode *prev; }; typedef struct Zipper Zipper; struct Zipper { Node *focus; //focus in the unmodified tree Node *original; //context ZipperNode *path; uint32_t path_count; }; Node **bst_search(Node **root_ptr, uint64_t find) { Node **node_ptr = root_ptr; while((*node_ptr)) { Node *node = *node_ptr; if(find < node->value) { node_ptr = &node->children[0]; } else if(find > node->value) { node_ptr = &node->children[1]; } else { return node_ptr; } } return node_ptr; } Node *bst_insert(Node **root_ptr, uint64_t value) { Node **best_match_ptr = bst_search(root_ptr, value); Node *best_match = *best_match_ptr; if(best_match && best_match->value == value) { return 0; } Node *node = calloc(1, sizeof(Node)); node->value = value; *best_match_ptr = node; return node; } void go_down(Zipper *zipper, uint32_t child_index) { Node *current = zipper->focus; assert(child_index < NODE_CHILD_COUNT); Node *child = current->children[child_index]; ZipperNode *path_node = calloc(1, sizeof(ZipperNode)); path_node->parent = current; path_node->child_index = child_index; path_node->original = zipper->original; path_node->prev = zipper->path; zipper->path = path_node; zipper->path_count++; zipper->focus = child; zipper->original = child; } void go_up(Zipper *zipper) { if(zipper->path != 0) { ZipperNode *path_node = zipper->path; Node *current = zipper->focus; Node *parent = path_node->parent; Node *new_focus = parent; Node *original_child = parent->children[path_node->child_index]; if(original_child != current) { if(path_node->original == parent) { //allow in-place mutation of in-progress uncommitted tree Node *new_parent = malloc(sizeof(Node)); memcpy(new_parent, parent, sizeof(*new_parent)); new_focus = new_parent; } new_focus->children[path_node->child_index] = current; } zipper->path = path_node->prev; zipper->path_count--; zipper->focus = new_focus; zipper->original = path_node->original; } } Node *commit(Zipper *zipper) { while(zipper->path != 0) { go_up(zipper); } Node *root = zipper->focus; return root; } void insert_children(Zipper *zipper, Node *children[NODE_CHILD_COUNT]) { Node *node = malloc(sizeof(Node)); memcpy(&node->children, children, sizeof(node->children)); node->value = zipper->focus->value; zipper->focus = node; } void replace(Zipper *zipper, Node *new_node) { zipper->focus = new_node; } void update(Zipper *zipper, uint64_t value) { Node *node = malloc(sizeof(Node)); memcpy(node, zipper->focus, sizeof(*node)); node->value = value; zipper->focus = node; } Zipper init_zipper(Node *root) { Zipper zipper = { .focus = root, .original = root }; return zipper; } int main() { Node *root = 0; bst_insert(&root, 50); bst_insert(&root, 25); bst_insert(&root, 75); bst_insert(&root, 12); bst_insert(&root, 83); bst_insert(&root, 30); Zipper zipper = init_zipper(root); //go_down(&zipper, 0); //update(&zipper, 1111); go_down(&zipper, 0); update(&zipper, 666); go_up(&zipper); go_down(&zipper, 1); update(&zipper, 777); Node *new_root = commit(&zipper); return 0; }