fork download
  1. #ifndef STORAGE_H
  2. #define STORAGE_H
  3.  
  4. #include <algorithm>
  5. #include <string>
  6. #include <stack>
  7. #include <vector>
  8. #include <utility>
  9. #include <chrono>
  10. #include <iostream>
  11. #include <fstream>
  12. #include <iomanip>
  13. #include <cmath>
  14.  
  15. using namespace std;
  16. using namespace chrono;
  17.  
  18. typedef struct tree_s tree_t;
  19. typedef struct node_s node_t;
  20. typedef struct data_s data_t;
  21.  
  22. struct data_s {
  23. string key;
  24. string val;
  25. };
  26.  
  27. struct node_s {
  28. data_t data;
  29.  
  30. uint64_t weight; // количество узлов у данного узла
  31.  
  32. node_t *left;
  33. node_t *right;
  34.  
  35. node_t *parent;
  36. };
  37.  
  38. struct tree_s
  39. {
  40. node_t *root; // указатель на корень дерева
  41. };
  42.  
  43. class bntree
  44. {
  45. public:
  46. bntree();
  47. ~bntree();
  48.  
  49. // Вставка данных, ключ - значение
  50. void insert(string key, string val = "");
  51. // Удаление узла по индексу
  52. void erase(uint64_t index);
  53. // Удаление узла по ключу
  54. void erase(string key);
  55. // Взятие узла по индексу
  56. data_t *get(uint64_t index);
  57. // Взятие узла по ключу
  58. data_t *get(string key);
  59.  
  60. // Поиск узла по ключу, возвращает индекс узла
  61. uint64_t search(string key);
  62.  
  63. // Кол-во элементов в дереве
  64. uint64_t size();
  65.  
  66. // Печать дерева
  67. void print();
  68.  
  69. private:
  70. tree_t *tree;
  71.  
  72. uint64_t get_child_weight(node_t *node);
  73. node_t *node_new();
  74. void node_free(node_t *e);
  75.  
  76. bool erase_simple(node_t *search_node);
  77.  
  78. void clear(node_t *p);
  79.  
  80. void print(node_t *p, int indent);
  81.  
  82. void balance(node_t *p);
  83.  
  84. public:
  85. // Ближайшая степень 2-ки к числу
  86. uint64_t cpl2(uint64_t x);
  87.  
  88. // Быстрый логарифм
  89. long ilog2(long x);
  90.  
  91. // Вес узла к глубине
  92. uint64_t weight_to_depth(node_t *p);
  93. };
  94.  
  95. #endif
  96.  
  97. bntree::bntree() {
  98. this->tree = new tree_t();
  99. }
  100.  
  101. bntree::~bntree() {
  102. this->clear(this->tree->root);
  103. delete this->tree->root;
  104. }
  105.  
  106. node_t *bntree::node_new() {
  107. return new node_t();
  108. }
  109.  
  110. void bntree::node_free(node_t *n) {
  111. delete n;
  112. }
  113.  
  114. void bntree::clear(node_t *p) {
  115. if (p != NULL) {
  116. if (p->right) {
  117. this->clear(p->right);
  118. this->node_free(p->right);
  119. }
  120.  
  121. if (p->left) {
  122. this->clear(p->left);
  123. this->node_free(p->left);
  124. }
  125. }
  126. }
  127.  
  128. uint64_t bntree::search(string key) {
  129. if (!this->tree->root) {
  130. return -1;
  131. }
  132.  
  133. node_t *search_node = this->tree->root;
  134. uint64_t index_node = this->get_child_weight(search_node->left);
  135.  
  136. for (;;) {
  137. if (key == search_node->data.key) {
  138. return index_node; // найден узел с таким ключем, вернем его индекс
  139. } else if (key > search_node->data.key) {
  140. search_node = search_node->right;
  141.  
  142. if (search_node == NULL)
  143. return -1;
  144.  
  145. index_node += (this->get_child_weight(search_node->left) + 1);
  146. } else {
  147. search_node = search_node->left;
  148.  
  149. if (search_node == NULL)
  150. return -1;
  151.  
  152. index_node -= (this->get_child_weight(search_node->left) + 1);
  153. }
  154. }
  155. }
  156.  
  157. void bntree::insert(string key, string val) {
  158. node_t *search_node, *prev_node, **node;
  159.  
  160. node = &this->tree->root;
  161. search_node = this->tree->root;
  162. prev_node = NULL;
  163. uint64_t index_node;
  164.  
  165. if (!this->tree->root) {
  166. index_node = 0;
  167. } else {
  168. index_node = this->get_child_weight(search_node->left);
  169. }
  170.  
  171. uint64_t index_del = -1;
  172.  
  173. for (;;) {
  174.  
  175. if (search_node == NULL) {
  176. // Добавялем узел
  177. search_node = *node = this->node_new();
  178.  
  179. search_node->data.key = key;
  180. search_node->data.val = val;
  181. search_node->weight = 1; // новый узел имеет вес 1
  182.  
  183. search_node->left = search_node->right = NULL;
  184. search_node->parent = prev_node;
  185.  
  186. break;
  187. } else if (key > search_node->data.key) {
  188. // Идем направо
  189. prev_node = search_node;
  190. search_node->weight++; // увеличиваем вес узла
  191. node = &search_node->right;
  192. search_node = search_node->right;
  193.  
  194. if (search_node)
  195. index_node += (this->get_child_weight(search_node->left) + 1);
  196.  
  197. } else if (key < search_node->data.key) {
  198. // Идем налево
  199. prev_node = search_node;
  200. search_node->weight++; // увеличиваем вес узла
  201. node = &search_node->left;
  202. search_node = search_node->left;
  203.  
  204. if (search_node)
  205. index_node -= (this->get_child_weight(search_node->left) + 1);
  206. } else {
  207. // Если такой ключ уже существует, то обновляем значение.
  208. search_node->data.val = val;
  209.  
  210. // Идем назад и отменяем изменение веса у верхних узлов
  211. for (;;) {
  212.  
  213. if (search_node->parent) {
  214. search_node = search_node->parent;
  215. } else {
  216. return;
  217. }
  218.  
  219. search_node->weight--;
  220. }
  221. }
  222. }
  223.  
  224. this->balance(search_node);
  225.  
  226. return;
  227. }
  228.  
  229. bool bntree::erase_simple(node_t *search_node) {
  230.  
  231. node_t *prev_node = search_node->parent;
  232.  
  233. if (!search_node->left && !search_node->right) {
  234. // Удаляемый узел является листом.
  235.  
  236. // Обнуляем соответствующую ссылку родителя.
  237. if (prev_node == NULL) {
  238. // Удаляемый узел корень.
  239. this->tree->root = NULL;
  240. } else if (prev_node->left == search_node) {
  241. prev_node->left = NULL;
  242. } else if (prev_node->right == search_node) {
  243. prev_node->right = NULL;
  244. }
  245.  
  246. } else if (search_node->left && !search_node->right) {
  247. // Удаляемый узел имеет только левого ребенка.
  248.  
  249. // Перекомпануем ссылки родителя на левого внука.
  250. if (prev_node == NULL) {
  251. // Удаляемый узел корень.
  252. this->tree->root = search_node->left;
  253. this->tree->root->parent = NULL;
  254. } else if (prev_node->left == search_node) {
  255. prev_node->left = search_node->left;
  256. search_node->left->parent = prev_node;
  257. } else if (prev_node->right == search_node) {
  258. prev_node->right = search_node->left;
  259. search_node->left->parent = prev_node;
  260. }
  261.  
  262. } else if (!search_node->left && search_node->right) {
  263. // Удаляемый узел имеет только правого ребенка.
  264.  
  265. // Перекомпануем ссылки родителя на правого внука.
  266. if (prev_node == NULL) {
  267. // Удаляемый узел корень.
  268. this->tree->root = search_node->right;
  269. this->tree->root->parent = NULL;
  270. } else if (prev_node->left == search_node) {
  271. prev_node->left = search_node->right;
  272. search_node->right->parent = prev_node;
  273. } else if (prev_node->right == search_node) {
  274. prev_node->right = search_node->right;
  275. search_node->right->parent = prev_node;
  276. }
  277.  
  278. } else {
  279. // Удаляемый узел имеет двух детей. Здесь не обрабатываем.
  280.  
  281. return false;
  282. }
  283.  
  284. return true;
  285. }
  286.  
  287. void bntree::erase(uint64_t index) {
  288.  
  289. if (index < 0 || index > this->size() - 1) {
  290. return;
  291. }
  292.  
  293. node_t *search_node = this->tree->root;
  294. uint64_t index_node = this->get_child_weight(search_node->left);
  295.  
  296. for (;;) {
  297. if (index == index_node) {
  298. if (this->erase_simple(search_node)) {
  299. // pass
  300. } else if (search_node->left && search_node->right) {
  301. // Самый сложный случай, удаляемый узел имеет 2-х детей.
  302.  
  303. node_t *del_node = search_node;
  304. uint64_t _index;
  305. // Маленькая балансировка, если правый вес больше левого то удаляем через право
  306. // иначе через лево
  307. if (search_node->right->weight > search_node->left->weight) {
  308. _index = index_node + 1;
  309. } else {
  310. _index = index_node - 1;
  311. }
  312.  
  313. // Ищем узел со следующим индексом.
  314. for (;;) {
  315. if (_index == index_node) {
  316. // Узел найден
  317. break;
  318. } else if (_index > index_node) {
  319. search_node->weight--;
  320. search_node = search_node->right;
  321. index_node += (this->get_child_weight(search_node->left) + 1);
  322. } else {
  323. search_node->weight--;
  324. search_node = search_node->left;
  325. index_node -= (this->get_child_weight(search_node->right) + 1);
  326. }
  327. }
  328.  
  329. del_node->data = search_node->data;
  330. this->erase_simple(search_node);
  331. }
  332.  
  333. this->node_free(search_node);
  334.  
  335. return;
  336. } else if (index > index_node) {
  337. search_node->weight--;
  338. search_node = search_node->right;
  339. index_node += (this->get_child_weight(search_node->left) + 1);
  340. } else {
  341. search_node->weight--;
  342. search_node = search_node->left;
  343. index_node -= (this->get_child_weight(search_node->right) + 1);
  344. }
  345. }
  346. }
  347.  
  348. void bntree::erase(string key) {
  349.  
  350. node_t *search_node = this->tree->root;
  351. uint64_t index_node = this->get_child_weight(search_node->left);
  352.  
  353. for (;;) {
  354. if (key == search_node->data.key) {
  355. if (this->erase_simple(search_node)) {
  356. // pass
  357. } else if (search_node->left && search_node->right) {
  358. // Самый сложный случай, удаляемый узел имеет 2-х детей.
  359.  
  360. node_t *del_node = search_node;
  361. uint64_t _index;
  362. // Маленькая балансировка, если правый вес больше левого то удаляем через право
  363. // иначе через лево
  364. if (search_node->right->weight > search_node->left->weight) {
  365. _index = index_node + 1;
  366. } else {
  367. _index = index_node - 1;
  368. }
  369.  
  370. // Ищем узел со следующим индексом.
  371. for (;;) {
  372. if (_index == index_node) {
  373. // Узел найден
  374. break;
  375. } else if (_index > index_node) {
  376. search_node->weight--;
  377. search_node = search_node->right;
  378. index_node += (this->get_child_weight(search_node->left) + 1);
  379. } else {
  380. search_node->weight--;
  381.  
  382. search_node = search_node->left;
  383. index_node -= (this->get_child_weight(search_node->right) + 1);
  384. }
  385. }
  386.  
  387. del_node->data = search_node->data;
  388. this->erase_simple(search_node);
  389. }
  390.  
  391. this->node_free(search_node);
  392.  
  393. return;
  394. } else if (key > search_node->data.key) {
  395. search_node->weight--;
  396. search_node = search_node->right;
  397. index_node += (this->get_child_weight(search_node->left) + 1);
  398. } else {
  399. search_node->weight--;
  400. search_node = search_node->left;
  401. index_node -= (this->get_child_weight(search_node->right) + 1);
  402. }
  403.  
  404. }
  405. }
  406.  
  407. uint64_t bntree::get_child_weight(node_t *node) {
  408. if (node) {
  409. return node->weight;
  410. }
  411.  
  412. return 0;
  413. }
  414.  
  415. data_t *bntree::get(uint64_t index) {
  416. if (index < 0 || index > this->size() - 1) {
  417. return NULL;
  418. }
  419.  
  420. node_t *search_node = this->tree->root;
  421. uint64_t index_node = this->get_child_weight(search_node->left);
  422.  
  423. for (;;) {
  424. if (index == index_node) {
  425. return &search_node->data;
  426. } else if (index > index_node) {
  427. search_node = search_node->right;
  428. index_node += (this->get_child_weight(search_node->left) + 1);
  429. } else {
  430. search_node = search_node->left;
  431. index_node -= (this->get_child_weight(search_node->right) + 1);
  432. }
  433. }
  434. }
  435.  
  436. data_t *bntree::get(string key) {
  437. node_t *search_node = this->tree->root;
  438. uint64_t index_node = this->get_child_weight(search_node->left);
  439.  
  440. for (;;) {
  441. if (key == search_node->data.key) {
  442. return &search_node->data;
  443. } else if (key > search_node->data.key) {
  444. search_node = search_node->right;
  445. index_node += (this->get_child_weight(search_node->left) + 1);
  446. } else {
  447. search_node = search_node->left;
  448. index_node -= (this->get_child_weight(search_node->right) + 1);
  449. }
  450. }
  451.  
  452. return NULL;
  453. }
  454.  
  455. uint64_t bntree::size() {
  456. if (this->tree->root) {
  457. return this->tree->root->weight;
  458. }
  459.  
  460. return 0;
  461. }
  462.  
  463. void bntree::print() {
  464. this->print(this->tree->root, 5);
  465. }
  466.  
  467. void bntree::print(node_t *p, int indent) {
  468. if (p != NULL) {
  469. if (p->right) {
  470. this->print(p->right, indent + 4);
  471. }
  472. if (indent) {
  473. //std::cout << std::setw(indent) << ' ' << p->weight << ' ';
  474. std::cout << std::setw(indent) << ' ';
  475. }
  476. if (p->right) {
  477. std::cout << " /\n" << std::setw(indent) << ' ';
  478. }
  479. //std::cout << p->data.key << ":" << p->data.val << "\n ";
  480. std::cout << p->data.key << ":" << p << ":" << p->parent << "\n ";
  481. if (p->left) {
  482. std::cout << std::setw(indent) << ' ' << " \\\n";
  483. this->print(p->left, indent + 4);
  484. }
  485. }
  486. }
  487.  
  488. /*
  489.  * Балансировка поворотом
  490.  * Балансировка делается на основе весов левого и правого поддерева
  491.  */
  492. void bntree::balance(node_t *p) {
  493. if (!p) {
  494. return;
  495. }
  496.  
  497. node_t *child = NULL;
  498. node_t *parent = NULL;
  499. uint64_t ld = 0;
  500. uint64_t rd = 0;
  501.  
  502. for (;;) {
  503. ld = this->weight_to_depth(p->left);
  504. rd = this->weight_to_depth(p->right);
  505.  
  506. if (ld > rd && ld - rd > 1) {
  507. // Правый поворот.
  508. // Глубина левого поддерева больше, чем глубина правого
  509.  
  510. child = p->left;
  511. parent = p->parent;
  512.  
  513. if (parent) {
  514. if (parent->right == p) {
  515. parent->right = child;
  516. } else if (parent->left == p) {
  517. parent->left = child;
  518. }
  519. } else {
  520. this->tree->root = child;
  521. }
  522. child->parent = parent;
  523. p->parent = child;
  524.  
  525. p->left = child->right;
  526. if (p->left) {
  527. p->left->parent = p;
  528. }
  529.  
  530. child->right = p;
  531.  
  532. p->weight = 1 + this->get_child_weight(p->left) + this->get_child_weight(p->right);
  533. child->weight = 1 + this->get_child_weight(child->left) + this->get_child_weight(child->right);
  534.  
  535. //p = child;
  536. break;
  537. } else if (rd > ld && rd - ld > 1) {
  538. // Левый поворот.
  539. // Глубина правого поддерева больше, чем глубина левого
  540.  
  541. child = p->right;
  542. parent = p->parent;
  543.  
  544. if (parent) {
  545. if (parent->right == p) {
  546. parent->right = child;
  547. } else if (parent->left == p) {
  548. parent->left = child;
  549. }
  550. } else {
  551. this->tree->root = child;
  552. }
  553. child->parent = parent;
  554. p->parent = child;
  555.  
  556. p->right = child->left;
  557. if (p->right) {
  558. p->right->parent = p;
  559. }
  560.  
  561. child->left = p;
  562.  
  563. p->weight = 1 + this->get_child_weight(p->left) + this->get_child_weight(p->right);
  564. child->weight = 1 + this->get_child_weight(child->left) + this->get_child_weight(child->right);
  565.  
  566. //p = child;
  567. break;
  568. }
  569.  
  570. if (p->parent) {
  571. p = p->parent;
  572. } else {
  573. break;
  574. }
  575. }
  576.  
  577. return;
  578. }
  579.  
  580. /*
  581.  * Возвращает первое число в степени 2, которое больше или ровно x
  582.  */
  583. uint64_t bntree::cpl2(uint64_t x) {
  584. x = x - 1;
  585. x = x | (x >> 1);
  586. x = x | (x >> 2);
  587. x = x | (x >> 4);
  588. x = x | (x >> 8);
  589. x = x | (x >> 16);
  590. x = x | (x >> 32);
  591.  
  592. return x + 1;
  593. }
  594.  
  595. /*
  596.  * Двоичный логарифм от числа
  597.  */
  598. long bntree::ilog2(long d) {
  599. int result;
  600. std::frexp(d, &result);
  601. return result - 1;
  602. }
  603.  
  604. /*
  605.  * Вес к глубине
  606.  */
  607. uint64_t bntree::weight_to_depth(node_t *p) {
  608. if (p == NULL) {
  609. return 0;
  610. }
  611.  
  612. if (p->weight == 1) {
  613. return 1;
  614. } else if (p->weight == 2) {
  615. return 2;
  616. }
  617.  
  618. return this->ilog2(this->cpl2(p->weight));
  619. }
  620.  
  621. int main(void){
  622. bntree tree;
  623. int arr[13] = {8, 4, 30, 2, 6, 10, 36, 9, 12,38, 13, 14, 15 };
  624. for(int i=0; i<13; i++) {
  625. string zero_padded = std::to_string(arr[i]*0.000001).substr(4);
  626. tree.insert(zero_padded);
  627. }
  628. tree.print();
  629. }
Success #stdin #stdout 0s 4516KB
stdin
Standard input is empty
stdout
             0038:0x55bffa07d280:0x55bffa07d130
           /
         0036:0x55bffa07d130:0x55bffa07cf70
       /
     0030:0x55bffa07cf70:0
       \
                         0015:0x55bffa07d3d0:0x55bffa07d360
                       /
                     0014:0x55bffa07d360:0x55bffa07d2f0
                   /
                 0013:0x55bffa07d2f0:0x55bffa07d0c0
                   \
                     0012:0x55bffa07d210:0x55bffa07d2f0
               /
             0010:0x55bffa07d0c0:0x55bffa07ce90
               \
                 0009:0x55bffa07d1a0:0x55bffa07d0c0
           /
         0008:0x55bffa07ce90:0x55bffa07cf70
           \
                 0006:0x55bffa07d050:0x55bffa07cf00
               /
             0004:0x55bffa07cf00:0x55bffa07ce90
               \
                 0002:0x55bffa07cfe0:0x55bffa07cf00