PTA Self-printable B+ Tree

789 阅读2分钟

In this project, you are supposed to implement a B+ tree of order 3, with the following operations: initialize, insert (with splitting) and search. The B+ tree should be able to print out itself.

Input Specification:

Each input file contains one test case. For each case, the first line contains a positive number N (≤104), the number of integer keys to be inserted. Then a line of the N positive integer keys follows. All the numbers in a line are separated by spaces.

Output Specification:

For each test case, insert the keys into an initially empty B+ tree of order 3 according to the given order. Print in a line Key X is duplicated where X already exists when being inserted. After all the insertions, print out the B+ tree in a top-down lever-order format as shown by the samples.

Sample Input 1:

6
7 8 9 10 7 4
结尾无空行

Sample Output 1:

Key 7 is duplicated
[9]
[4,7,8][9,10]
结尾无空行

Sample Input 2:

10
3 1 4 5 9 2 6 8 7 0

Sample Output 2:

[6]
[2,4][8]
[0,1][2,3][4,5][6,7][8,9]

Sample Input 3:

3
1 2 3

Sample Output 3:

[1,2,3]

代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
#include <queue>
#include <algorithm>
#include <cmath>

#define ORDER 3

using namespace std;

class Node
{
public:
    int cnt_data = 0;  // 该节点所保存的数据量
    int cnt_child = 0;  // 子节点数
    int data[ORDER + 1];   // 该节点所保存的具体数据(非叶子节点为索引,叶子节点为数据)
    Node *child[ORDER + 2]; // 子节点
    Node *parent = NULL; // 父节点,节点分裂时使用,根节点为NULL
    Node *next; // 作为叶子节点时的相邻节点,实际上并没有用到这个
    Node ()
    {}
    Node (Node *pra, int data_src[], pair<int, int> data_interval, Node *child_src[], pair<int, int> child_interval)
    {
        this->parent = pra;
        this->cnt_data = data_interval.second - data_interval.first;
        memcpy(this->data, data_src + data_interval.first, this->cnt_data * sizeof(data_src[0]));
        this->cnt_child = child_interval.second - child_interval.first;
        memcpy(this->child, child_src + child_interval.first, this->cnt_child * sizeof(child_src[0]));
        for (int i = 0; i < cnt_child; ++i)
        {
            child[i]->parent = this;
        }
    }

    void print ()
    {
        printf("[");
        for (int i = 0; i < cnt_data; ++i)
        {
            if (i)
                printf(",");
            printf("%d", data[i]);
        }
        printf("]");
    }
};

int n;
Node *Root = new Node();
int split_time = 0;

bool cmp (Node *p1, Node *p2)
{
    return p1->data[0] < p2->data[0];
}

void print_tree ()
{
    Node *BlankLine = NULL; 
    queue<Node *> que;
    que.push(Root);
    que.push(BlankLine);
    while (!que.empty())
    {
        Node *t = que.front();
        que.pop();
        if (t == BlankLine)
        {
            printf("\n");
            if (!que.empty())
                que.push(BlankLine);
            continue;
        }
        t->print();
        for (int i = 0; i < t->cnt_child; ++i)
            que.push(t->child[i]);
    }
}

void split (Node *node)
{
    int cntData = node->cnt_data;
    int cntChild = node->cnt_child;
    bool is_leaf = cntChild == 0;
    Node **child = node->child;
    int *data = node->data;
    if ((is_leaf && cntData <= ORDER) ||(!is_leaf && cntData < ORDER))
        return;
    if (node->parent == NULL)
        Root = node->parent = new Node();
    Node *pra = node->parent;
    int mid ;
    Node *l ;
    Node *r ;
    if (is_leaf)
    {
        mid = ceil(1.0*ORDER/2);
        l = new Node(pra, data, make_pair(0, mid), child, make_pair(0, 0));
        r = new Node(pra, data, make_pair(mid, cntData), child, make_pair(0, 0));
    } 
    else
    {
        mid = ceil(1.0*(ORDER-1)/2);
        l = new Node(pra, data, make_pair(0, mid), child, make_pair(0, mid+1));
        r = new Node(pra, data, make_pair(mid+1, cntData), child, make_pair(mid+1, cntChild));
    }
    pra->data[pra->cnt_data++] = data[mid];
    if (pra->cnt_child > 0)
        for (int i = 0; i < pra->cnt_child; ++i)
        {
            if (pra->child[i] == node)
            {
                pra->child[i] = l;
                break;
            }
        }
    else
        pra->child[pra->cnt_child++] = l;
    pra->child[pra->cnt_child++] = r;
    sort(pra->data, pra->data + pra->cnt_data);
    sort(pra->child, pra->child + pra->cnt_child, cmp);
    delete node;
    split(pra);
}

void insert (Node *node, int n)
{
    if (node == NULL)
        node = new Node();
    node->data[node->cnt_data++] = n;
    sort(node->data, node->data + node->cnt_data);
    split(node);
}

Node *find (Node *root, int n)
{
    if (root == NULL)
        return root;
    if (root->cnt_child == 0)
        return root;
    int i = upper_bound(root->data, root->data + root->cnt_data, n) - root->data;
    return find(root->child[i], n);

}

bool exist (Node *node, int n)
{
    if (node == NULL)
        return false;
    return binary_search(node->data, node->data + node->cnt_data, n);
}

int main ()
{

    scanf("%d", &n);
    for (int i = 0; i < n; ++i)
    {
        int num;
        scanf("%d", &num);
        Node *leaf = find(Root, num);
        if (!exist(leaf, num))
            insert(leaf, num);
        else
            printf("Key %d is duplicated\n", num);
    }
    print_tree();
    return 0;
}

提交结果:

3.png