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;
}

 

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