2019宁夏网络赛__E - 2-3-4 Tree

In computer science, a 2-3-4 tree, as a search tree, is a self-balancing data structure that is commonly used to implement dictionaries. The numbers mean a tree where every node with children (internal node) has either two, three or four child nodes.

A 2-node is the same as a binary node, which has one data element, and if internal has two child nodes. A 3-node has two data elements, and if internal has three child nodes. A 4-node has three data elements, and if internal has four child nodes. All leaves are at the same depth, and all data is kept in sorted order.

Here we introduce the procedure of inserting a value into a 2-3-4 tree. If the number of values that have been inserted in is no more than 22, the 2-3-4 tree after the insertion has only one node (the root) with several data elements.

Otherwise, we start the following procedure at the root of the 2-3-4 tree.

  1. If the current node is a 4-node:
    • Remove and save the middle value to get a 3-node
    • Split the remaining 3-node up into a pair of 2-nodes (the now missing middle value is handled in the next step).
    • If this is the root node (which thus has no parent):
      • the middle value becomes the new root 2-node and the tree height increases by 1. Ascend into the root (which means that the current node becomes the new root node).
    • Otherwise, push the middle value up into the parent node. Ascend into the parent node (which means that the current node becomes its parent node).
  2. If the current node is a leaf, insert the value into the node and finish.
  3. Otherwise,
    • Find the child whose interval contains the value to be inserted.
    • Descend into the child and repeat from step 1.

Now you are given a 2-3-4 tree which is empty at first. Then we insert nn values a1,a2,⋯,ana1,a2,⋯,an into the 2-3-4 tree one by one. You are asked to write a program to print the 2-3-4 tree after inserting all the given values along the pre-order traversal. For a node with one or more data elements, your program will print these data elements in one line in ascending order.

Input

The input contains several test cases, and the first line is a positive integer TTindicating the number of test cases which is up to 5050.

For each test case, the first line contains an integer n (1≤n≤5000)n (1≤n≤5000) indicating the number of values that will be inserted into the 2-3-4 tree. The second line contains nn integers a1,a2,⋯,ana1,a2,⋯,an. We guarantee that a1,a2,⋯,ana1,a2,⋯,an is a permutation of 1,2,⋯,n1,2,⋯,n.

Output

For each test case, output a line containing Case #x: at first, where x is the test case number starting from 11. The following several lines describe the 2-3-4 tree along the pre-order traversal, each line of which describes a node with several integers indicating the data elements of a node in the 2-3-4 tree.

Example

Input

3
4
1 2 3 4
4
4 3 2 1
17
6 3 5 7 1 10 2 9 4 8 11 12 13 14 15 16 17

Output

Case #1:
2
1
3 4
Case #2:
3
1 2
4
Case #3:
5 9
2
1
3 4
7
6
8
11 13 15
10
12
14
16 17

这是一道b树的题,原理和课本的b树差不多,但这里的b树建法是重根节点开始遇到三节点的就要拆,注意这个点就行了,我博客里有完整的b树实现代码,可供学习

#include <bits/stdc++.h>

using namespace std;

/**B树的抽象实现**/
const int m=4;              //B树的阶树
const int Max=m-1;          //最大的关键字个数
const int Min=(m-1)/2;      //最小的关键字个数

typedef struct rt{          //定义结点信息
    int key[m+1];           //结点关键字数组,key[0]不用
    int keynum;             //结点关键字个数
    struct rt* parent;      //双亲结点指针
    struct rt* ptr[m+1];    //孩子结点指针
}BNT,*BTree;

typedef struct op{          //查找结果
    int i;                  //结点的关键字位置或需插入位置
    int tag;                //成功与否标志
    BTree pt;               //找到的结点
}result;

typedef struct qp{          //模拟队列
    BTree pt;               //指向B树结点(数据域)
    struct qp* next;        //下一个队列指针(指针域)
}queueBNT,*queueBTree;

int search(BTree p,int k) { //在子树p中寻找结点k
    int i=1;
    while(i<=p->keynum&&p->key[i]<k)i++;
    return i;
}

BTree t;;

void searchBTree(BTree t,int k,result &r) { //在B树t中查找结点
    int finshed=0,i=0;
    BTree p=t,q=NULL;
    while(p!=NULL&&finshed==0) {
        i=search(p,k);
        if(i<=p->keynum&&p->key[i]==k)finshed=1;
        else {
            q=p;
            p=p->ptr[i-1];
        }
    }
    if(finshed==1) {                         //找到结点
        r.tag=1; r.i=i; r.pt=q;
    }
    else {                                   //找不到结点
        r.tag=0; r.i=i; r.pt=q;
    }
}

void newBTreeroot(BTree &t,BTree p,int k,BTree aq) {
    t=(BTree)malloc(sizeof(BNT));
    t->key[1]=k; t->keynum=1;
    t->ptr[0]=p; t->ptr[1]=aq;
    if(p!=NULL)p->parent=t;
    if(aq!=NULL)aq->parent=t;
    t->parent=NULL;
}

void insert(BTree p,int k,BTree &ap,int i) {
    int j;
    for(j=p->keynum;j>=i;j--) {
        p->key[j+1]=p->key[j];
        p->ptr[j+1]=p->ptr[j];
    }
    p->key[i]=k; p->ptr[i]=ap;
    if(ap!=NULL)ap->parent=p;
    p->keynum++;
}

void spilt(BTree p,BTree &ap,int s) {
    int i,j;
    ap=(BTree)malloc(sizeof(BNT));
    ap->ptr[0]=p->ptr[s];
    for(j=s+1,i=1;j<=p->keynum;i++,j++) {
        ap->key[i]=p->key[j];
        ap->ptr[i]=p->ptr[j];
    }
    ap->keynum=p->keynum-s;
    ap->parent=p->parent;
    for(i=0;i<=ap->keynum;i++) {
        if(ap->ptr[i]!=NULL)ap->ptr[i]->parent=ap;
    }
    p->keynum=s-1;
}

void chai(BTree &p){
    BTree ap;int x,s,i,finshed,needNewroot;
    ap=NULL; finshed=needNewroot=0;
    s=(m+1)>>1; spilt(p,ap,s);
    x=p->key[s];
    if(p->parent!=NULL) {
        p=p->parent;
        i=search(p,x);
    }
    else needNewroot=1;
    while(finshed==0&&needNewroot==0){
        insert(p,x,ap,i);
        if(p->keynum<=Max)finshed=1;
        else {
            s=(m+1)>>1; spilt(p,ap,s);
            x=p->key[s];
            if(p->parent!=NULL) {
                p=p->parent;
                i=search(p,x);
            }
            else needNewroot=1;
        }
    }
    if(needNewroot==1) newBTreeroot(t,p,x,ap),p=t;
}

void Print(BTree t,int deep){
    if(t==NULL)return;
    int i;
    for(i = 1; i <= t->keynum; i++){
        printf("%d%c", t->key[i], i == t->keynum ? '\n':' ');
    }
    for(i = 0; i <= t->keynum; i++){
        Print(t->ptr[i], deep+1);
    }
}

void insertBTree(BTree &t,int k){
    BTree q=t,ap=NULL;
    int i;
    while(q!=NULL){
        if(q->keynum==m-1){
            chai(q);
        }
        for(i=1;i<=q->keynum;i++){
            if(q->key[i]>k)break;
        }
        if(q->ptr[i-1]!=NULL){
            q=q->ptr[i-1];
        }
        else break;
    }
    if(q==NULL)newBTreeroot(t,NULL,k,NULL);
    else insert(q,k,ap,i);
}

void DestoryBTree(BTree &t){
    if(t==NULL)return;
    int i;
    BTree p;
    queueBTree pl,pr,ap,q;
    pl=(queueBTree)malloc(sizeof(queueBNT));
    pr=(queueBTree)malloc(sizeof(queueBNT));
    pl->pt=t; pl->next=NULL; pr=pl;
    while(pl){
        p=pl->pt;
        for(i=0;i<=p->keynum;i++){
            if(p->ptr[i]){
                ap=(queueBTree)malloc(sizeof(queueBNT));
                ap->pt=p->ptr[i]; ap->next=NULL;

                pr->next=ap; pr=ap;
            }
        }
        q=pl;
        pl=pl->next;
        free(q->pt);
        free(q);
        q=NULL;
    }
    t=NULL;
}


void Test(){
    int n,key,flag;
    result r;
    int tt;scanf("%d",&tt);
    int cas=1;
    while(tt--){
        t=NULL;
        scanf("%d",&n);
        int x;
        for(int i=1;i<=n;i++){
            scanf("%d",&x);
            insertBTree(t,x);
        }
        if(t==NULL)cout<<666<<endl;
        printf("Case #%d:\n",cas++);
//        printBTree(t);
        Print(t,0);
        DestoryBTree(t);
    }
}


int main(){
//    Test1();
    Test();
    return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章