source2.h 15 KB

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