7-3 Self-printable B+ Tree (PAT ADSAA)

#include <cstdio>
#include <iostream>
#include <set>
#include <vector>

struct node {
  bool isLeaf;
  int size;
  int key1;
  int key2;
  int key3;
  node* first;
  node* second;
  node* third;
  node* parent;
};

bool search(node* root, int key) {
  if ((root->size >= 1 && key == root->key1) ||
      (root->size >= 2 && key == root->key2) ||
      (root->size == 3 && key == root->key3)) {
    return true;
  }
  if (root->size >= 1 && key < root->key1 && !root->isLeaf) {
    return search(root->first, key);
  }
  if (!root->isLeaf && root->size == 1 && key > root->key2) {
    return search(root->second, key);
  }
  if (!root->isLeaf && root->size == 2 && key > root->key1 &&
      key < root->key2) {
    return search(root->second, key);
  }
  if (!root->isLeaf && root->size == 2 && key > root->key2) {
    return search(root->third, key);
  }
  return false;
}

void update(node* root, node* child, int flag) {
  if (root->size == 2) {
    if (1 == flag) {
      root->third = root->second;
      root->second = root->first;
      root->first = child;
    } else if (2 == flag) {
      root->third = root->second;
      root->second = child;
    }
  } else if (root->size == 3) {
    auto* tmp = new node;
    tmp->isLeaf = root->isLeaf;
    tmp->third = nullptr;
    tmp->size = 1;
    root->size = 1;
    if (1 == flag) {
      child->parent = tmp;
      root->first->parent = tmp;
      tmp->first = child;
      tmp->second = root->first;
      root->first = root->second;
      root->second = root->third;
    } else if (2 == flag) {
      root->first->parent = tmp;
      child->parent = tmp;
      tmp->first = root->first;
      tmp->second = child;
      root->first = root->second;
      root->second = root->third;
    } else {
      root->first->parent = tmp;
      root->second->parent = tmp;
      child->parent = root;
      tmp->first = root->first;
      tmp->second = root->second;
      root->first = child;
      root->second = root->third;
    }
    root->third = nullptr;
    if (root->parent) {
      int newFlag;
      if (root->parent->first == root) {
        newFlag = 1;
      } else if (root->parent->second == root) {
        newFlag = 2;
      } else {
        newFlag = 3;
      }
      root->parent->size += 1;
      tmp->parent = root->parent;
      update(root->parent, tmp, newFlag);
    } else {
      auto* p = new node;
      p->isLeaf = false;
      p->size = 1;
      p->first = tmp;
      p->second = root;
      p->third = nullptr;
      p->parent = nullptr;
      tmp->parent = p;
      root->parent = p;
    }
  }
}

void insert(node* root, int key) {
  if (root->isLeaf) {
    if (root->size == 0) {
      root->key1 = key;
      root->size = 1;
    } else if (root->size == 1) {
      root->size = 2;
      if (key < root->key1) {
        root->key2 = root->key1;
        root->key1 = key;
      } else if (key > root->key1) {
        root->key2 = key;
      }
    } else if (root->size == 2) {
      root->size = 3;
      if (key < root->key1) {
        root->key3 = root->key2;
        root->key2 = root->key1;
        root->key1 = key;
      } else if (key > root->key1 && key < root->key2) {
        root->key3 = root->key2;
        root->key2 = key;
      } else {
        root->key3 = key;
      }
    } else if (root->size == 3) {
      auto* tmp = new node;
      tmp->first = nullptr;
      tmp->second = nullptr;
      tmp->third = nullptr;
      tmp->size = 2;
      tmp->isLeaf = true;
      root->size = 2;
      if (key < root->key1) {
        tmp->key1 = key;
        tmp->key2 = root->key1;
        root->key1 = root->key2;
        root->key2 = root->key3;
      } else if (key > root->key1 && key < root->key2) {
        tmp->key1 = root->key1;
        tmp->key2 = key;
        root->key1 = root->key2;
        root->key2 = root->key3;
      } else if (key > root->key2 && key < root->key3) {
        tmp->key1 = root->key1;
        tmp->key2 = root->key2;
        root->key1 = key;
        root->key2 = root->key3;
      } else {
        tmp->key1 = root->key1;
        tmp->key2 = root->key2;
        root->key1 = root->key3;
        root->key2 = key;
      }
      if (root->parent) {
        root->parent->size += 1;
        int flag = 4;
        if (root->parent->first == root) {
          flag = 1;
        } else if (root->parent->second == root) {
          flag = 2;
        } else if (root->parent->size >= 2 && root->parent->third == root) {
          flag = 3;
        }
        tmp->parent = root->parent;
        update(root->parent, tmp, flag);
      } else {
        auto* p = new node;
        p->isLeaf = false;
        p->size = 1;
        p->first = tmp;
        p->second = root;
        p->third = nullptr;
        p->parent = nullptr;
        tmp->parent = p;
        root->parent = p;
        p->key1 = p->second->key1;
      }
    }
  } else {
    if (root->size == 1) {
      if (key < root->key1) {
        insert(root->first, key);
      } else {
        insert(root->second, key);
      }
    } else {
      if (key < root->key1) {
        insert(root->first, key);
      } else if (key > root->key1 && key < root->key2) {
        insert(root->second, key);
      } else {
        insert(root->third, key);
      }
    }
  }
}

void updateKeys(node* root) {
  node* curr;
  if (!root->isLeaf) {
    curr = root->second;
    while (!curr->isLeaf) {
      curr = curr->first;
    }
    root->key1 = curr->key1;
    updateKeys(root->first);
    updateKeys(root->second);
    if (root->size == 2) {
      curr = root->third;
      while (!curr->isLeaf) {
        curr = curr->first;
      }
      root->key2 = curr->key1;
      updateKeys(root->third);
    }
  }
}

int main() {
  int N, key, pivot;
  std::cin >> N;
  auto* root = new node;
  root->isLeaf = true;
  root->size = 0;
  root->first = nullptr;
  root->second = nullptr;
  root->third = nullptr;
  root->parent = nullptr;
  for (int i = 0; i < N; ++i) {
    std::cin >> key;
    if (search(root, key)) {
      printf("Key %d is duplicated\n", key);
    } else {
      insert(root, key);
      while (root->parent) {
        root = root->parent;
      }
      updateKeys(root);
    }
  }
  std::vector<node*> vec;
  vec.push_back(root);
  pivot = 0;
  std::set<int> end;
  end.insert(0);
  while (pivot < vec.size()) {
    if (!vec[pivot]->isLeaf) {
      vec.push_back(vec[pivot]->first);
      vec.push_back(vec[pivot]->second);
      if (vec[pivot]->size == 2) {
        vec.push_back(vec[pivot]->third);
      }
      if (end.find(pivot) != end.end()) {
        end.insert(vec.size() - 1);
      }
    }
    ++pivot;
  }
  for (int i = 0; i < vec.size(); ++i) {
    std::cout << "[" << vec[i]->key1;
    if (vec[i]->size >= 2) {
      std::cout << "," << vec[i]->key2;
    }
    if (vec[i]->size == 3) {
      std::cout << "," << vec[i]->key3;
    }
    std::cout << "]";
    if (end.find(i) != end.end() && i != vec.size() - 1) {
      std::cout << std::endl;
    }
  }
  return 0;
}

题目如下:

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]
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值