source1.h 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624
  1. #ifndef __source1_H__
  2. #define __source1_H__
  3. #include <iostream>
  4. using namespace std;
  5. class Triehard // compressed binary trie
  6. // constructor should make a left and right that are empty for search to work
  7. // magnitude is 1 for length 1, so it must be >= 1
  8. // flag means the value ending there is being stored
  9. {
  10. private:
  11. class Trienode
  12. {
  13. private:
  14. int magnitude;
  15. bool flag;
  16. Trienode * left;
  17. Trienode * right;
  18. //Convenient method for printing.
  19. //Returns a string to be able to chain
  20. //printing more easily.
  21. //Side is either 0 (left), or 1 (right)
  22. string getNodeVal(int side){
  23. string output = "";
  24. for(int i = 0; i < magnitude; i ++){
  25. output += to_string(side);
  26. }
  27. return output;
  28. }
  29. public:
  30. Trienode(int magnitude, bool flag):
  31. magnitude{magnitude}, flag{flag}
  32. {
  33. left = nullptr;
  34. right = nullptr;
  35. }
  36. ~Trienode() // Unsure about syntax, if this will play nicely with delete method
  37. {
  38. delete left;
  39. delete right;
  40. delete this;
  41. }
  42. int getMag()
  43. {
  44. return magnitude;
  45. }
  46. bool getFlag()
  47. {
  48. return flag;
  49. }
  50. //Side is 0 (left) or 1 (right)
  51. void print(int side,string output = ""){
  52. string val = getNodeVal(side);
  53. if(getFlag()){
  54. cout << output + val << endl;
  55. }
  56. if(left != nullptr){
  57. left->print(0,output + val);
  58. }
  59. if(right != nullptr){
  60. right->print(1,output + val);
  61. }
  62. }
  63. Trienode * getLeft()
  64. {
  65. return left;
  66. }
  67. Trienode * getRight()
  68. {
  69. return right;
  70. }
  71. void addMag()
  72. {
  73. ++magnitude;
  74. }
  75. void subMag()
  76. {
  77. --magnitude;
  78. }
  79. void tFlag()
  80. {
  81. flag = true;
  82. }
  83. void fFlag()
  84. {
  85. flag = false;
  86. }
  87. Trienode * setLeft(int mag, bool flg)
  88. {
  89. left = new Trienode(mag, flg);
  90. return left;
  91. }
  92. Trienode * setRight(int mag, bool flg)
  93. {
  94. right = new Trienode(mag, flg);
  95. return right;
  96. }
  97. void copyLeft(Trienode * node)
  98. {
  99. left = node;
  100. }
  101. void copyRight(Trienode * node)
  102. {
  103. right = node;
  104. }
  105. };
  106. Trienode * left;
  107. Trienode * right;
  108. public:
  109. Triehard() // Initializes both sides as empty, but makes it searchable, mutatable
  110. {
  111. left = new Trienode(0, false);
  112. right = new Trienode(0, false);
  113. }
  114. ~Triehard() // Same concern (syntax) as nodes, don't forget to write an erase method as well, maybe an empty/wipe
  115. {
  116. delete left;
  117. delete right;
  118. delete this;
  119. }
  120. void print()
  121. {
  122. //Default param arg seems to be a bit different
  123. //than i thought. Leaving it in the node print
  124. //function, try to fix later perhaps?
  125. if(left != nullptr)left->print(0);
  126. if(right != nullptr)right->print(1);
  127. }
  128. bool search(int * val, int len) // val is the string, len is its length
  129. {
  130. Trienode * curnode;
  131. bool side; // represents if you are on the left or right (right being true)
  132. if (val[0])
  133. {
  134. curnode = right;
  135. side = true;
  136. }
  137. else
  138. {
  139. curnode = left;
  140. side = false;
  141. }
  142. int curmag = curnode->getMag();
  143. for (int i = 0; i < len; i++) // each iteration checks the current character for accuracy. it does not prepare for the next character like the preamble
  144. {
  145. if (val[i]) // if next digit is 1
  146. {
  147. if (side) // if you're on the right
  148. {
  149. if (curmag) // if your current magnitude is >= 1 (still info "left" in this node)
  150. {
  151. --curmag;
  152. continue;
  153. }
  154. if (curnode->getRight()) // If current node is "exhausted", move on to next one
  155. {
  156. curnode = curnode->getRight();
  157. curmag = curnode->getMag() - 1;
  158. continue;
  159. }
  160. else
  161. {
  162. return false;
  163. }
  164. }
  165. else
  166. {
  167. if (curmag)
  168. {
  169. return false;
  170. }
  171. if (curnode->getRight())
  172. {
  173. curnode = curnode->getRight();
  174. curmag = curnode->getMag() - 1;
  175. side = true;
  176. continue;
  177. }
  178. else
  179. {
  180. return false;
  181. }
  182. }
  183. }
  184. else
  185. {
  186. if (!side)
  187. {
  188. if (curmag)
  189. {
  190. --curmag;
  191. continue;
  192. }
  193. if (curnode->getLeft())
  194. {
  195. curnode = curnode->getLeft();
  196. curmag = curnode->getMag() - 1;
  197. continue;
  198. }
  199. else
  200. {
  201. return false;
  202. }
  203. }
  204. else
  205. {
  206. if (curmag)
  207. {
  208. return false;
  209. }
  210. if (curnode->getLeft())
  211. {
  212. curnode = curnode->getLeft();
  213. curmag = curnode->getMag() - 1;
  214. side = false;
  215. continue;
  216. }
  217. else
  218. {
  219. return false;
  220. }
  221. }
  222. }
  223. }
  224. return curnode->getFlag();
  225. }
  226. void insert(int * val, int len) // assumes valid input
  227. {
  228. Trienode * curnode;
  229. bool side; // represents if you are on the left or right (right being true)
  230. if (val[0])
  231. {
  232. curnode = right;
  233. side = true;
  234. }
  235. else
  236. {
  237. curnode = left;
  238. side = false;
  239. }
  240. int curmag = curnode->getMag();
  241. for (int i = 0; i < len; i++)
  242. {
  243. if (val[i]) // if next digit is 1
  244. {
  245. if (side) // if you're on the right
  246. {
  247. if (curmag) // if your current magnitude is >= 1 (still info "left" in this node)
  248. {
  249. --curmag;
  250. continue;
  251. }
  252. else if (curnode->getRight()) // If current node is "exhausted", move on to next one
  253. {
  254. curnode = curnode->getRight();
  255. curmag = curnode->getMag() - 1;
  256. continue;
  257. }
  258. else if (!(curnode->getLeft())) // if there are no subtrees, just increase this node's magnitude
  259. {
  260. curnode->addMag();
  261. continue;
  262. }
  263. else // we're on a "1" node, but it is depleted, and there is a left subtree. so, we create a new node to the right to represent this bit
  264. {
  265. curnode = curnode->setRight(1, false);
  266. continue;
  267. }
  268. }
  269. else // we're on a left subtree, but have a 1 coming up
  270. {
  271. if (curmag) // this means we have a value here, so we need to split this node up, branching to the right will be handled by following code
  272. {
  273. Trienode * newnode = new Trienode(0, false); // this will be the second half of the big node
  274. while (curmag) // fills newnode with the extra magnitude
  275. {
  276. curnode->subMag();
  277. newnode->addMag();
  278. }
  279. newnode->copyLeft(curnode->getLeft()); // move the children to the bottom half
  280. newnode->copyRight(curnode->getRight());
  281. curnode->copyLeft(newnode); // put new node at left of curnode
  282. curnode->copyRight(nullptr); // nothing is in the right yet
  283. goto SKIP1; // skip next if check since we know new right is NULL
  284. }
  285. if (curnode->getRight()) // we can and should move to the right. once there, we sub 1 from magnitude and move on.
  286. {
  287. curnode = curnode->getRight();
  288. curmag = curnode->getMag() - 1;
  289. side = true;
  290. continue;
  291. }
  292. else // we are on left, it is empty, and the right side is empty. create and set that node to curnode->
  293. {
  294. SKIP1:
  295. curnode = curnode->setRight(1, false);
  296. continue;
  297. }
  298. }
  299. }
  300. else // next digit is a 0
  301. {
  302. if (!side) // on a left subtree
  303. {
  304. if (curmag) // still have 0s "remaining" at this node
  305. {
  306. --curmag;
  307. continue;
  308. }
  309. else if (curnode->getLeft()) // no 0s remaining, but there is a left subtree
  310. {
  311. curnode = curnode->getLeft();
  312. curmag = curnode->getMag() - 1;
  313. continue;
  314. }
  315. else if (!(curnode->getRight())) // no subtrees and we're on the correct side, so add to this node's magnitude
  316. {
  317. curnode->addMag();
  318. continue;
  319. }
  320. else // no 0s remaining, no left subtree, and we are going to add one.
  321. {
  322. curnode = curnode->setLeft(1, false);
  323. continue;
  324. }
  325. }
  326. else // we're on a right subtree but have a 0 coming up
  327. {
  328. if (curmag) // this means we have a value here, so we need to split this node up and branch to the left before this point
  329. {
  330. Trienode * newnode = new Trienode(0, false); // this will be the second half of the big node
  331. while (curmag) // fills newnode with the extra magnitude
  332. {
  333. curnode->subMag();
  334. newnode->addMag();
  335. }
  336. newnode->copyLeft(curnode->getLeft()); // move the children to the bottom half
  337. newnode->copyRight(curnode->getRight());
  338. curnode->copyLeft(nullptr); // nothing is in the left yet
  339. curnode->copyRight(newnode); // put new node at right of curnode
  340. goto SKIP2; // skip next if check since we know new left is NULL
  341. }
  342. if (curnode->getLeft()) // we can and should move to the left. once there, we sub 1 from magnitude and move on.
  343. {
  344. curnode = curnode->getLeft();
  345. curmag = curnode->getMag() - 1;
  346. side = false;
  347. continue;
  348. }
  349. else // we are on right, it is empty, and the left side is empty. create and set that node to curnode->
  350. {
  351. SKIP2:
  352. curnode = curnode->setLeft(1, false);
  353. continue;
  354. }
  355. }
  356. }
  357. }
  358. curnode->tFlag();
  359. }
  360. void cut(int * val, int len) // this is delete because i can't use delete :(
  361. {
  362. Trienode * curnode;
  363. Trienode * prevnode = nullptr;
  364. bool side; // represents if you are on the left or right (right being true)
  365. bool side2; // previous node's side
  366. if (val[0])
  367. {
  368. curnode = right;
  369. side = true;
  370. side2 = true;
  371. }
  372. else
  373. {
  374. curnode = left;
  375. side = false;
  376. side2 = false;
  377. }
  378. int curmag = curnode->getMag();
  379. for (int i = 0; i < len; i++) // each iteration checks the current character for accuracy. it does not prepare for the next character like the preamble
  380. {
  381. if (val[i]) // if next digit is 1
  382. {
  383. if (side) // if you're on the right
  384. {
  385. if (curmag) // if your current magnitude is >= 1 (still info "left" in this node)
  386. {
  387. --curmag;
  388. side2 = side;
  389. continue;
  390. }
  391. if (curnode->getRight()) // If current node is "exhausted", move on to next one
  392. {
  393. prevnode = curnode;
  394. curnode = curnode->getRight();
  395. curmag = curnode->getMag() - 1;
  396. side2 = side;
  397. continue;
  398. }
  399. else // node doesn't exist
  400. {
  401. return;
  402. }
  403. }
  404. else
  405. {
  406. if (curmag) // node doesn't exist
  407. {
  408. return;
  409. }
  410. if (curnode->getRight())
  411. {
  412. prevnode = curnode;
  413. curnode = curnode->getRight();
  414. curmag = curnode->getMag() - 1;
  415. side = true;
  416. side2 = false;
  417. continue;
  418. }
  419. else // node doesn't exist
  420. {
  421. return;
  422. }
  423. }
  424. }
  425. else
  426. {
  427. if (!side)
  428. {
  429. if (curmag)
  430. {
  431. --curmag;
  432. side2 = side;
  433. continue;
  434. }
  435. if (curnode->getLeft())
  436. {
  437. prevnode = curnode;
  438. curnode = curnode->getLeft();
  439. curmag = curnode->getMag() - 1;
  440. side2 = side;
  441. continue;
  442. }
  443. else // node doesn't exist
  444. {
  445. return;
  446. }
  447. }
  448. else
  449. {
  450. if (curmag) // node doesn't exist
  451. {
  452. return;
  453. }
  454. if (curnode->getLeft())
  455. {
  456. prevnode = curnode;
  457. curnode = curnode->getLeft();
  458. curmag = curnode->getMag() - 1;
  459. side = false;
  460. side2 = true;
  461. continue;
  462. }
  463. else // node doesn't exist
  464. {
  465. return;
  466. }
  467. }
  468. }
  469. }
  470. // at this point, we have curnode being the "end" of our value
  471. if (!(prevnode)) // if we are deleting one of the 2 base trees
  472. {
  473. if (side)
  474. {
  475. right->fFlag();
  476. }
  477. else
  478. {
  479. left->fFlag();
  480. }
  481. }
  482. else if (curnode->getLeft() && curnode->getRight()) // we have shit to both sides, just unflag
  483. {
  484. curnode->fFlag();
  485. }
  486. else if (!(curnode->getLeft()) && !(curnode->getRight())) // if our node has no children, destroy it and change parent's reference to NULL
  487. {
  488. if (side)
  489. {
  490. delete curnode;
  491. prevnode->copyRight(nullptr);
  492. }
  493. else
  494. {
  495. delete curnode;
  496. prevnode->copyLeft(nullptr);
  497. }
  498. }
  499. else if (side && curnode->getLeft() && prevnode->getLeft() && side2 && !(prevnode->getFlag()) && !(prevnode->getLeft()))
  500. // we are on the right, we have shit to the left, and the parent has nothing to the left, and is not flagged
  501. // this is a rare case where we do have to compress
  502. {
  503. while (curnode->getMag()) // Change mag to parent
  504. {
  505. curnode->subMag();
  506. prevnode->addMag();
  507. }
  508. prevnode->copyLeft(curnode->getLeft()); // Move left side up, delete old data
  509. curnode->copyLeft(nullptr);
  510. prevnode->copyRight(nullptr);
  511. delete curnode;
  512. }
  513. else if (!(side) && curnode->getRight() && prevnode->getRight() && !(side2) && !(prevnode->getFlag()) && !(prevnode->getRight()))
  514. // we are on the left, we have shit to the right, and the parent has nothing to the right, and is not flagged
  515. // the same rare case as above
  516. {
  517. while (curnode->getMag()) // Change mag to parent
  518. {
  519. curnode->subMag();
  520. prevnode->addMag();
  521. }
  522. prevnode->copyRight(curnode->getRight()); // Move left side up, delete old data
  523. curnode->copyRight(nullptr);
  524. prevnode->copyLeft(nullptr);
  525. delete curnode;
  526. }
  527. else if ((side && curnode->getLeft()) || (!(side) && curnode->getRight()))
  528. // we are to the right and have shit to the left or vice versa
  529. {
  530. curnode->fFlag();
  531. }
  532. else if (side) // we are on the right and have shit to the right
  533. {
  534. Trienode * child = curnode->getRight();
  535. while (child->getMag()) // moves magnitude from child to parent we are removing
  536. {
  537. child->subMag();
  538. curnode->addMag();
  539. }
  540. if (child->getFlag()) curnode->tFlag(); // Sets flag based on child
  541. else curnode->fFlag();
  542. curnode->copyLeft(child->getLeft()); // moves child's children to our parent node
  543. curnode->copyRight(child->getRight());
  544. child->copyLeft(nullptr); // Change child's children to null to allow for safe deletion
  545. child->copyRight(nullptr);
  546. delete child;
  547. }
  548. else // we are on the left and have shit to the left
  549. {
  550. Trienode * child = curnode->getLeft();
  551. while (child->getMag()) // moves magnitude from child to parent we are removing
  552. {
  553. child->subMag();
  554. curnode->addMag();
  555. }
  556. if (child->getFlag()) curnode->tFlag(); // Sets flag based on child
  557. else curnode->fFlag();
  558. curnode->copyLeft(child->getLeft()); // moves child's children to our parent node
  559. curnode->copyRight(child->getRight());
  560. child->copyLeft(nullptr); // Change child's children to null to allow for safe deletion
  561. child->copyRight(nullptr);
  562. delete child;
  563. }
  564. }
  565. };
  566. #endif