Back (Current repo: scraps)

random scraps and notes that are useful to me
To clone this repository:
git clone https://git.viktor1993.net/scraps.git
Log | Download | Files | Refs

b_plus_tree.awk (4163B)


#!/usr/bin/awk -f

function new_node(leaf, id) {
    id = ++node_count;
    node[id]["leaf"] = leaf;
    node[id]["n"] = 0;
    node[id]["next"] = 0;
    return id;
}

function insert(r, key, s) {
    if (node[r]["n"] == 2 * order - 1) {
        s = new_node(0);
        node[s]["children"][1] = r;
        split_child(s, 1, r);
        insert_nonfull(s, key);
        root = s;
    } else {
        insert_nonfull(r, key);
    }
}

function insert_nonfull(x, k, i, c) {
    i = node[x]["n"]
    if (node[x]["leaf"]) {
        while (i >= 1 && k < node[x]["keys"][i]) {
            node[x]["keys"][i+1] = node[x]["keys"][i];
            i--;
        }
        node[x]["keys"][i+1] = k;
        node[x]["n"]++;
    } else {
        while (i >= 1 && k < node[x]["keys"][i]) i--
        i++;
        c = node[x]["children"][i];
        if (node[c]["n"] == 2 * order - 1) {
            split_child(x, i, c);
            if (k >= node[x]["keys"][i]) {
                i++;
            }
        }
        insert_nonfull(node[x]["children"][i], k);
    }
}

function split_child(p, i, y, z, t, j) {
    t = order;
    z = new_node(node[y]["leaf"]);

    if (node[y]["leaf"]) {
        for (j = 1; j <= t - 1; j++) {
            node[z]["keys"][j] = node[y]["keys"][j + t];
        }

        node[z]["n"] = t - 1;

        node[z]["next"] = node[y]["next"];
        node[y]["next"] = z;

        node[y]["n"] = t;

        promote_key = node[z]["keys"][1];

    } else {
        for (j = 1; j <= t - 1; j++) {
            node[z]["keys"][j] = node[y]["keys"][j + t];
        }

        for (j = 1; j <= t; j++) {
            node[z]["children"][j] = node[y]["children"][j + t];
        }

        node[z]["n"] = t - 1;
        node[y]["n"] = t - 1;

        promote_key = node[y]["keys"][t];
    }

    for (j = node[p]["n"]; j >= i; j--) {
        node[p]["keys"][j+1] = node[p]["keys"][j];
    }
    node[p]["keys"][i] = promote_key;

    for (j = node[p]["n"] + 1; j > i; j--) {
        node[p]["children"][j+1] = node[p]["children"][j];
    }
    node[p]["children"][i+1] = z;
    node[p]["n"]++;
}

function search(x, k, i, child) {
    if (node[x]["leaf"]) {
        for (i = 1; i <= node[x]["n"]; i++)
            if (node[x]["keys"][i] == k) {
                printf("Found %d in leaf node %d\n", k, x)
                return 1
            }
        printf("%d not found (reached leaf %d)\n", k, x)
        return 0
    }
    i = 1
    while (i <= node[x]["n"] && k >= node[x]["keys"][i]) i++
    child = node[x]["children"][i]
    return search(child, k)
}

function search_range(r, a, b, x, i) {
    x = r;
    while (!node[x]["leaf"]) {
        i = 1;
        while (i <= node[x]["n"] && a >= node[x]["keys"][i]) {
            i++;
        }
        x = node[x]["children"][i];
    }

    while (x) {
        for (i = 1; i <= node[x]["n"]; i++) {
            k = node[x]["keys"][i];
            if (k >= a && k <= b) {
                printf "%d ", k;
            }
            if (k > b) {
                print "";
                return;
            }
        }
        x = node[x]["next"];
    }
    print "";
}

function print_tree(x, depth,    i, pad) {
    pad = sprintf("%" (depth*4) "s", "");
    printf("%sNode %d: ", pad, x);
    for (i = 1; i <= node[x]["n"]; i++) {
        printf("%d ", node[x]["keys"][i]);
    }
    print (node[x]["leaf"] ? "(leaf)" : "");
    if (!node[x]["leaf"]) {
        for (i = 1; i <= node[x]["n"] + 1; i++) {
            print_tree(node[x]["children"][i], depth + 1);
        }
    }
}

function range_scan(r, x, i) {
    x = r;
    while (!node[x]["leaf"]) {
        x = node[x]["children"][1];
    }
    while (x) {
        for (i = 1; i <= node[x]["n"]; i++) {
            printf "%d ", node[x]["keys"][i];
        }
        x = node[x]["next"];
    }
    print "";
}

BEGIN{
    order = 3;
    root = new_node(1);

    for (i = 1; i <= 20; i++) {
        insert(root, i);
    }
    print "-----";
    print "Full tree:";
    print_tree(root, 0);

    print "\nSearch tests:";
    search(root, 5);
    search(root, 15);
    search(root, 25);

    print "\nRange search [8..17]:";
    search_range(root, 8, 17);
}