source2.h 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733
  1. #ifndef __source1_H__
  2. #define __source1_H__
  3. #include <iostream>
  4. using namespace std;
  5. class Triehard2 // 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. // no more flag, instead we have a count field which counts the number of instances
  9. // the node represents. A small change, but much more functionality
  10. {
  11. private:
  12. class Trienode2
  13. {
  14. private:
  15. int magnitude;
  16. int count;
  17. Trienode2 * left;
  18. Trienode2 * right;
  19. /*
  20. //Convenient method for printing.
  21. //Returns a string to be able to chain
  22. //printing more easily.
  23. //Side is either 0 (left), or 1 (right)
  24. string getNodeVal(int side)
  25. {
  26. string output = "";
  27. for(int i = 0; i < magnitude; ++i)
  28. {
  29. output += to_string(side);
  30. }
  31. return output;
  32. }*/
  33. public:
  34. Trienode2(int magnitude, int count):
  35. magnitude{magnitude}, count{count}
  36. {
  37. left = nullptr;
  38. right = nullptr;
  39. }
  40. ~Trienode2()
  41. {
  42. delete left;
  43. delete right;
  44. }
  45. int getMag()
  46. {
  47. return magnitude;
  48. }
  49. int getCount()
  50. {
  51. return count;
  52. }
  53. /*
  54. //Side is 0 (left) or 1 (right)
  55. void print(int side, string output = "")
  56. {
  57. string val = getNodeVal(side);
  58. if(getCount())
  59. {
  60. cout << output + val << endl;
  61. }
  62. if(left != nullptr)
  63. {
  64. left->print(0, output + val);
  65. }
  66. if(right != nullptr)
  67. {
  68. right->print(1, output + val);
  69. }
  70. }*/
  71. Trienode2 * getLeft()
  72. {
  73. return left;
  74. }
  75. Trienode2 * getRight()
  76. {
  77. return right;
  78. }
  79. void addMag()
  80. {
  81. ++magnitude;
  82. }
  83. void subMag()
  84. {
  85. --magnitude;
  86. }
  87. void addCount()
  88. {
  89. ++count;
  90. }
  91. void subCount()
  92. {
  93. --count;
  94. }
  95. void zeroCount()
  96. {
  97. count = 0;
  98. }
  99. void setCount(int x)
  100. {
  101. count = x;
  102. }
  103. Trienode2 * setLeft(int mag, int cnt)
  104. {
  105. left = new Trienode2(mag, cnt);
  106. return left;
  107. }
  108. Trienode2 * setRight(int mag, int cnt)
  109. {
  110. right = new Trienode2(mag, cnt);
  111. return right;
  112. }
  113. void copyLeft(Trienode2 * node)
  114. {
  115. left = node;
  116. }
  117. void copyRight(Trienode2 * node)
  118. {
  119. right = node;
  120. }
  121. };
  122. Trienode2 * left;
  123. Trienode2 * right;
  124. public:
  125. Triehard2() // Initializes both sides as empty, but makes it searchable, mutatable
  126. {
  127. left = new Trienode2(0, 0);
  128. right = new Trienode2(0, 0);
  129. }
  130. ~Triehard2() // Same concern (syntax) as nodes, don't forget to write an erase method as well, maybe an empty/wipe
  131. {
  132. delete left;
  133. delete right;
  134. }
  135. /*
  136. void print()
  137. {
  138. //Default param arg seems to be a bit different
  139. //than i thought. Leaving it in the node print
  140. //function, try to fix later perhaps?
  141. if(left != nullptr)left->print(0);
  142. if(right != nullptr)right->print(1);
  143. }*/
  144. // build an array of what is "processed" so far. then when a flag is hit, print that array.
  145. void mainPrint(Trienode * curnode, vector<int> * chars, int right)
  146. {
  147. if (!curnode) return;
  148. int curmag = curnode->getMag();
  149. int curcount = curnode->getCount();
  150. while (curmag)
  151. {
  152. chars->push_back(right);
  153. --curmag;
  154. }
  155. while (curcount)
  156. {
  157. int len = chars->size();
  158. for (int i = 0; i < len; i++)
  159. {
  160. cout << (*chars)[i] << " ";
  161. }
  162. cout << endl;
  163. --curcount;
  164. }
  165. mainPrint(curnode->getLeft(), chars, 0);
  166. mainPrint(curnode->getRight(), chars, 1);
  167. curmag = curnode->getMag();
  168. while (curmag)
  169. {
  170. chars->pop_back();
  171. --curmag;
  172. }
  173. }
  174. void myPrintIsBetterThanYoursLogan()
  175. {
  176. vector<int> * side1 = new vector<int>();
  177. vector<int> * side2 = new vector<int>();
  178. mainPrint(left, side1, 0);
  179. mainPrint(right, side2, 1);
  180. delete side1;
  181. delete side2;
  182. }
  183. int search(int * val, int len) // val is the string, len is its length
  184. {
  185. Trienode2 * curnode;
  186. bool side; // represents if you are on the left or right (right being true)
  187. if (val[0])
  188. {
  189. curnode = right;
  190. side = true;
  191. }
  192. else
  193. {
  194. curnode = left;
  195. side = false;
  196. }
  197. int curmag = curnode->getMag();
  198. 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
  199. {
  200. if (val[i]) // if next digit is 1
  201. {
  202. if (side) // if you're on the right
  203. {
  204. if (curmag) // if your current magnitude is >= 1 (still info "left" in this node)
  205. {
  206. --curmag;
  207. continue;
  208. }
  209. if (curnode->getRight()) // If current node is "exhausted", move on to next one
  210. {
  211. curnode = curnode->getRight();
  212. curmag = curnode->getMag() - 1;
  213. continue;
  214. }
  215. else
  216. {
  217. return 0;
  218. }
  219. }
  220. else
  221. {
  222. if (curmag)
  223. {
  224. return 0;
  225. }
  226. if (curnode->getRight())
  227. {
  228. curnode = curnode->getRight();
  229. curmag = curnode->getMag() - 1;
  230. side = true;
  231. continue;
  232. }
  233. else
  234. {
  235. return 0;
  236. }
  237. }
  238. }
  239. else
  240. {
  241. if (!side)
  242. {
  243. if (curmag)
  244. {
  245. --curmag;
  246. continue;
  247. }
  248. if (curnode->getLeft())
  249. {
  250. curnode = curnode->getLeft();
  251. curmag = curnode->getMag() - 1;
  252. continue;
  253. }
  254. else
  255. {
  256. return 0;
  257. }
  258. }
  259. else
  260. {
  261. if (curmag)
  262. {
  263. return 0;
  264. }
  265. if (curnode->getLeft())
  266. {
  267. curnode = curnode->getLeft();
  268. curmag = curnode->getMag() - 1;
  269. side = false;
  270. continue;
  271. }
  272. else
  273. {
  274. return 0;
  275. }
  276. }
  277. }
  278. }
  279. return curnode->getCount();
  280. }
  281. void insert(int * val, int len) // assumes valid input
  282. {
  283. Trienode2 * curnode; // the node we are checking against our current value
  284. bool side; // represents if you are on the left or right (right being true)
  285. if (val[0])
  286. {
  287. curnode = right;
  288. side = true;
  289. }
  290. else
  291. {
  292. curnode = left;
  293. side = false;
  294. }
  295. int curmag = curnode->getMag(); // "remaining" magnitude of the current node
  296. for (int i = 0; i < len; i++)
  297. {
  298. if (val[i]) // if current digit is 1
  299. {
  300. if (side) // if you're on the right
  301. {
  302. if (curmag) // if your current magnitude is >= 1 (still info "left" in this node)
  303. {
  304. --curmag;
  305. continue;
  306. }
  307. else if (curnode->getRight()) // If current node is "exhausted", move on to next one
  308. {
  309. curnode = curnode->getRight();
  310. curmag = curnode->getMag() - 1;
  311. continue;
  312. }
  313. else if (!(curnode->getLeft()) && !(curnode->getCount())) // if there are no subtrees, just increase this node's magnitude
  314. // also can't do that if the node is flagged, since it needs to retain that info, so check for this
  315. {
  316. curnode->addMag();
  317. continue;
  318. }
  319. 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
  320. // also works if the node is flagged and we just need a new node to represent the unflagged set of 1s
  321. {
  322. curnode = curnode->setRight(1, 0);
  323. continue;
  324. }
  325. }
  326. else // we're on a left subtree, but have a 1 coming up
  327. {
  328. 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
  329. {
  330. Trienode2 * newnode = new Trienode2(0, curnode->getCount()); // this will be the second half of the big node
  331. curnode->zeroCount(); // this and the passing of the count into newnode ensure count is not lost
  332. while (curmag) // fills newnode with the extra magnitude
  333. {
  334. curnode->subMag();
  335. --curmag;
  336. newnode->addMag();
  337. }
  338. newnode->copyLeft(curnode->getLeft()); // move the children to the bottom half
  339. newnode->copyRight(curnode->getRight());
  340. curnode->copyLeft(newnode); // put new node at left of curnode
  341. curnode->copyRight(nullptr); // nothing is in the right yet
  342. goto SKIP1; // skip next if check since we know new right is NULL
  343. }
  344. if (curnode->getRight()) // we can and should move to the right. once there, we sub 1 from magnitude and move on.
  345. {
  346. curnode = curnode->getRight();
  347. curmag = curnode->getMag() - 1;
  348. side = true;
  349. continue;
  350. }
  351. else // we are on left, it is empty, and the right side is empty. create and set that node to curnode->
  352. {
  353. SKIP1:
  354. curnode = curnode->setRight(1, 0);
  355. side = true;
  356. continue;
  357. }
  358. }
  359. }
  360. else // next digit is a 0
  361. {
  362. if (!side) // on a left subtree
  363. {
  364. if (curmag) // still have 0s "remaining" at this node
  365. {
  366. --curmag;
  367. continue;
  368. }
  369. else if (curnode->getLeft()) // no 0s remaining, but there is a left subtree
  370. {
  371. curnode = curnode->getLeft();
  372. curmag = curnode->getMag() - 1;
  373. continue;
  374. }
  375. else if (!(curnode->getRight()) && !(curnode->getCount())) // no subtrees and we're on the correct side, so add to this node's magnitude
  376. // only if this node isn't flagged, since we must retain that info
  377. {
  378. curnode->addMag();
  379. continue;
  380. }
  381. else // no 0s remaining || we are flagged, no left subtree, and we are going to add one.
  382. {
  383. curnode = curnode->setLeft(1, 0);
  384. continue;
  385. }
  386. }
  387. else // we're on a right subtree but have a 0 coming up
  388. {
  389. 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
  390. {
  391. Trienode2 * newnode = new Trienode2(0, curnode->getCount()); // this will be the second half of the big node
  392. curnode->zeroCount(); // This and the passing of getCount to newnode ensure count is not lost
  393. while (curmag) // fills newnode with the extra magnitude
  394. {
  395. curnode->subMag();
  396. --curmag;
  397. newnode->addMag();
  398. }
  399. newnode->copyLeft(curnode->getLeft()); // move the children to the bottom half
  400. newnode->copyRight(curnode->getRight());
  401. curnode->copyLeft(nullptr); // nothing is in the left yet
  402. curnode->copyRight(newnode); // put new node at right of curnode
  403. goto SKIP2; // skip next if check since we know new left is NULL
  404. }
  405. if (curnode->getLeft()) // we can and should move to the left. once there, we sub 1 from magnitude and move on.
  406. {
  407. curnode = curnode->getLeft();
  408. curmag = curnode->getMag() - 1;
  409. side = false;
  410. continue;
  411. }
  412. else // we are on right, it is empty, and the left side is empty. create and set that node to curnode->
  413. {
  414. SKIP2:
  415. curnode = curnode->setLeft(1, 0);
  416. side = false;
  417. continue;
  418. }
  419. }
  420. }
  421. }
  422. // at this point, the node we are at needs to be flagged. However, there is an issue: this node may have magnitude remaining
  423. // if this is the case, we need to split it up at curnode->getMag() - curmag. lets check for the easy case, then proceed
  424. // with that logic if necessary
  425. // basically curmag is our "extra" magnitude that needs to be sent along
  426. if (!curmag)
  427. {
  428. curnode->addCount();
  429. }
  430. else
  431. {
  432. Trienode * newnode = new Trienode(0, curnode->getCount()); // this is our new node, which should retain old flagging
  433. curnode->setCount(1); // curnode will now end where we want to insert, so this should be true
  434. while (curmag) // fills newnode with the extra magnitude
  435. {
  436. curnode->subMag();
  437. --curmag;
  438. newnode->addMag();
  439. }
  440. // now we create the newnode on the appropriate side
  441. newnode->copyLeft(curnode->getLeft());
  442. newnode->copyRight(curnode->getRight());
  443. if (side)
  444. {
  445. curnode->copyLeft(nullptr);
  446. curnode->copyRight(newnode);
  447. }
  448. else
  449. {
  450. curnode->copyLeft(newnode);
  451. curnode->copyRight(nullptr);
  452. }
  453. }
  454. }
  455. void cut(int * val, int len) // this is delete because i can't use delete :(
  456. {
  457. Trienode2 * curnode;
  458. Trienode2 * prevnode = nullptr;
  459. bool side; // represents if you are on the left or right (right being true)
  460. bool side2; // previous node's side
  461. if (val[0])
  462. {
  463. curnode = right;
  464. side = true;
  465. side2 = true;
  466. }
  467. else
  468. {
  469. curnode = left;
  470. side = false;
  471. side2 = false;
  472. }
  473. int curmag = curnode->getMag();
  474. 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
  475. {
  476. if (val[i]) // if next digit is 1
  477. {
  478. if (side) // if you're on the right
  479. {
  480. if (curmag) // if your current magnitude is >= 1 (still info "left" in this node)
  481. {
  482. --curmag;
  483. side2 = side;
  484. continue;
  485. }
  486. if (curnode->getRight()) // If current node is "exhausted", move on to next one
  487. {
  488. prevnode = curnode;
  489. curnode = curnode->getRight();
  490. curmag = curnode->getMag() - 1;
  491. side2 = side;
  492. continue;
  493. }
  494. else // node doesn't exist
  495. {
  496. return;
  497. }
  498. }
  499. else
  500. {
  501. if (curmag) // node doesn't exist
  502. {
  503. return;
  504. }
  505. if (curnode->getRight())
  506. {
  507. prevnode = curnode;
  508. curnode = curnode->getRight();
  509. curmag = curnode->getMag() - 1;
  510. side = true;
  511. side2 = false;
  512. continue;
  513. }
  514. else // node doesn't exist
  515. {
  516. return;
  517. }
  518. }
  519. }
  520. else
  521. {
  522. if (!side)
  523. {
  524. if (curmag)
  525. {
  526. --curmag;
  527. side2 = side;
  528. continue;
  529. }
  530. if (curnode->getLeft())
  531. {
  532. prevnode = curnode;
  533. curnode = curnode->getLeft();
  534. curmag = curnode->getMag() - 1;
  535. side2 = side;
  536. continue;
  537. }
  538. else // node doesn't exist
  539. {
  540. return;
  541. }
  542. }
  543. else
  544. {
  545. if (curmag) // node doesn't exist
  546. {
  547. return;
  548. }
  549. if (curnode->getLeft())
  550. {
  551. prevnode = curnode;
  552. curnode = curnode->getLeft();
  553. curmag = curnode->getMag() - 1;
  554. side = false;
  555. side2 = true;
  556. continue;
  557. }
  558. else // node doesn't exist
  559. {
  560. return;
  561. }
  562. }
  563. }
  564. }
  565. // at this point, we have curnode being the "end" of our value
  566. if (!(prevnode)) // if we are deleting one of the 2 base trees
  567. {
  568. if (side)
  569. {
  570. right->subCount();
  571. }
  572. else
  573. {
  574. left->subCount();
  575. }
  576. return;
  577. }
  578. curnode->subCount(); // Normally this is all that is necessary
  579. if (curnode->getCount) return; // This means we aren't removing a node, so no compression is possible
  580. // Cases where nodes have to be removed/compressed
  581. if (!(curnode->getLeft()) && !(curnode->getRight())) // if our node has no children, destroy it and change parent's reference to NULL
  582. {
  583. if (side)
  584. {
  585. delete curnode;
  586. prevnode->copyRight(nullptr);
  587. }
  588. else
  589. {
  590. delete curnode;
  591. prevnode->copyLeft(nullptr);
  592. }
  593. }
  594. else if (side && curnode->getLeft() && prevnode->getLeft() && side2 && !(prevnode->getCount()) && !(prevnode->getLeft()))
  595. // we are on the right, we have shit to the left, and the parent has nothing to the left, and is not flagged
  596. // this is a rare case where we do have to compress
  597. {
  598. while (curnode->getMag()) // Change mag to parent
  599. {
  600. curnode->subMag();
  601. prevnode->addMag();
  602. }
  603. prevnode->copyLeft(curnode->getLeft()); // Move left side up, delete old data
  604. curnode->copyLeft(nullptr);
  605. prevnode->copyRight(nullptr);
  606. delete curnode;
  607. }
  608. else if (!(side) && curnode->getRight() && prevnode->getRight() && !(side2) && !(prevnode->getCount()) && !(prevnode->getRight()))
  609. // we are on the left, we have shit to the right, and the parent has nothing to the right, and is not flagged
  610. // the same rare case as above
  611. {
  612. while (curnode->getMag()) // Change mag to parent
  613. {
  614. curnode->subMag();
  615. prevnode->addMag();
  616. }
  617. prevnode->copyRight(curnode->getRight()); // Move left side up, delete old data
  618. curnode->copyRight(nullptr);
  619. prevnode->copyLeft(nullptr);
  620. delete curnode;
  621. }
  622. else if (side) // we are on the right and have shit to the right
  623. {
  624. Trienode2 * child = curnode->getRight();
  625. while (child->getMag()) // moves magnitude from child to parent we are removing
  626. {
  627. child->subMag();
  628. curnode->addMag();
  629. }
  630. curnode->setCount(child->getCount()); // Sets count to child's count
  631. curnode->copyLeft(child->getLeft()); // moves child's children to our parent node
  632. curnode->copyRight(child->getRight());
  633. child->copyLeft(nullptr); // Change child's children to null to allow for safe deletion
  634. child->copyRight(nullptr);
  635. delete child;
  636. }
  637. else // we are on the left and have shit to the left
  638. {
  639. Trienode2 * child = curnode->getLeft();
  640. while (child->getMag()) // moves magnitude from child to parent we are removing
  641. {
  642. child->subMag();
  643. curnode->addMag();
  644. }
  645. curnode->setCount(child->getCount()); // Sets count to child's count
  646. curnode->copyLeft(child->getLeft()); // moves child's children to our parent node
  647. curnode->copyRight(child->getRight());
  648. child->copyLeft(nullptr); // Change child's children to null to allow for safe deletion
  649. child->copyRight(nullptr);
  650. delete child;
  651. }
  652. }
  653. };
  654. #endif