y_bintree.inc 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576
  1. #if defined _INC_y_bintree
  2. #endinput
  3. #endif
  4. #define _INC_y_bintree
  5. /**
  6. * <library name="y_bintree">
  7. * <section>
  8. * Description
  9. * </section>
  10. * Provides functions to generate balanced binary search trees for efficient
  11. * searching of large arrays by value. Left branch is less than, right branch
  12. * is greater than or equal to for multiple matching values.
  13. * <section>
  14. * Version
  15. * </section>
  16. * 0.1.3
  17. * <section>
  18. * Functions
  19. * </section>
  20. * <subsection>
  21. * Core
  22. * </subsection><ul>
  23. * <symbol name="Bintree_QSort">Custom implementaion of QSort to keep pointers.</symbol>
  24. * <symbol name="Bintree_SortHalf">Itteratively balances halves of an array.</symbol>
  25. * </ul><subsection>
  26. * Stock
  27. * </subsection><ul>
  28. * <symbol name="Bintree_Generate">Generates a balanced binary tree from given input.</symbol>
  29. * <symbol name="Bintree_Reset">Resets a position in a tree.</symbol>
  30. * <symbol name="Bintree_FindValue">Finds the pointer for a value in the tree.</symbol>
  31. * <symbol name="Bintree_Add">Adds an item to a generated tree.</symbol>
  32. * <symbol name="Bintree_Delete">Removes an item from a tree.</symbol>
  33. * <symbol name="Bintree_UpdatePointers">Updates the pointers after a target change.</symbol>
  34. * </ul><subsection>
  35. * Static
  36. * </subsection><ul>
  37. * <symbol name="Bintree_Compress">Removes space from an altered tree.</symbol>
  38. * <symbol name="Bintree_FindMin">Finds the smallest value on a branch.</symbol>
  39. * <symbol name="Bintree_FindMax">Finds the largest value on a branch.</symbol>
  40. * </ul><subsection>
  41. * Inline
  42. * </subsection><ul>
  43. * <symbol name="Bintree_Sort">Entry point for Bintree_QSort.</symbol>
  44. * <symbol name="Bintree_Fill">Entry point for Bintree_SortHalf.</symbol>
  45. * </ul><section>
  46. * Definitions
  47. * </section><ul>
  48. * <symbol name="BINTREE_NO_BRANCH">Nowhere to go from the number in required direction.</symbol>
  49. * <symbol name="BINTREE_NOT_FOUND">Failure return.</symbol>
  50. * </ul><section>
  51. * Enums
  52. * </section><ul>
  53. * <symbol name="E_BINTREE_TREE">Structure of a leaf of a binary tree.</symbol>
  54. * <symbol name="E_BINTREE_INPUT">Structure of an array of data to be added to a tree.</symbol>
  55. * </ul><section>
  56. * Tags
  57. * </section><ul>
  58. * <symbol name="Bintree">Binary tree type.</symbol>
  59. * </ul>
  60. * </library>
  61. *//** *//*
  62. Legal:
  63. Version: MPL 1.1
  64. The contents of this file are subject to the Mozilla Public License Version
  65. 1.1 the "License"; you may not use this file except in compliance with
  66. the License. You may obtain a copy of the License at
  67. http://www.mozilla.org/MPL/
  68. Software distributed under the License is distributed on an "AS IS" basis,
  69. WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  70. for the specific language governing rights and limitations under the
  71. License.
  72. The Original Code is the YSI framework.
  73. The Initial Developer of the Original Code is Alex "Y_Less" Cole.
  74. Portions created by the Initial Developer are Copyright C 2011
  75. the Initial Developer. All Rights Reserved.
  76. Contributors:
  77. Y_Less
  78. koolk
  79. JoeBullet/Google63
  80. g_aSlice/Slice
  81. Misiur
  82. samphunter
  83. tianmeta
  84. maddinat0r
  85. spacemud
  86. Crayder
  87. Dayvison
  88. Ahmad45123
  89. Zeex
  90. irinel1996
  91. Yiin-
  92. Chaprnks
  93. Konstantinos
  94. Masterchen09
  95. Southclaws
  96. PatchwerkQWER
  97. m0k1
  98. paulommu
  99. udan111
  100. Thanks:
  101. JoeBullet/Google63 - Handy arbitrary ASM jump code using SCTRL.
  102. ZeeX - Very productive conversations.
  103. koolk - IsPlayerinAreaEx code.
  104. TheAlpha - Danish translation.
  105. breadfish - German translation.
  106. Fireburn - Dutch translation.
  107. yom - French translation.
  108. 50p - Polish translation.
  109. Zamaroht - Spanish translation.
  110. Los - Portuguese translation.
  111. Dracoblue, sintax, mabako, Xtreme, other coders - Producing other modes for
  112. me to strive to better.
  113. Pixels^ - Running XScripters where the idea was born.
  114. Matite - Pestering me to release it and using it.
  115. Very special thanks to:
  116. Thiadmer - PAWN, whose limits continue to amaze me!
  117. Kye/Kalcor - SA:MP.
  118. SA:MP Team past, present and future - SA:MP.
  119. Optional plugins:
  120. Gamer_Z - GPS.
  121. Incognito - Streamer.
  122. Me - sscanf2, fixes2, Whirlpool.
  123. */
  124. #include "..\YSI_Internal\y_compilerdata"
  125. #include "..\YSI_Internal\y_version"
  126. #include "..\YSI_Core\y_debug"
  127. #include "..\YSI_Core\y_utils"
  128. #define BINTREE_NO_BRANCH -1
  129. #define BINTREE_NOT_FOUND -1
  130. // If this ever changes, update the size reference in y_users.
  131. enum E_BINTREE_TREE
  132. {
  133. E_BINTREE_TREE_VALUE,
  134. E_BINTREE_TREE_LEFT,
  135. E_BINTREE_TREE_RIGHT,
  136. E_BINTREE_TREE_PARENT,
  137. E_BINTREE_TREE_POINTER
  138. }
  139. enum E_BINTREE_INPUT
  140. {
  141. E_BINTREE_INPUT_VALUE,
  142. E_BINTREE_INPUT_POINTER
  143. }
  144. //#define leafs<%1> %1][E_BINTREE_TREE
  145. //#define Bintree:%1[%2] Bintree:%1[%2][E_BINTREE_TREE]
  146. #define BinaryTree:%1<%2> Bintree:%1[%2][E_BINTREE_TREE]
  147. #define BinaryInput:%1<%2> %1[%2][E_BINTREE_INPUT]
  148. #if defined YSI_TESTS
  149. #include "..\YSI_Core\y_testing"
  150. #include "y_bintree/tests"
  151. #endif
  152. // Update at a later date...
  153. #define Bintree_DisplayOutput(%0) "<bintree output>"
  154. #define Bintree_DisplayInput(%0) "<bintree input>"
  155. /*-------------------------------------------------------------------------*//**
  156. * <param name="input">Data to sort.</param>
  157. * <param name="size">Size of data to sort.</param>
  158. * <remarks>
  159. * Entry point for Bintree_QSort.
  160. * </remarks>
  161. *//*------------------------------------------------------------------------**/
  162. P:D(Bintree_Sort(numbers[][E_BINTREE_INPUT], size = sizeof (data)));
  163. #define Bintree_Sort(%1,%2) \
  164. Bintree_QSort((%1), 0, (%2) - 1)
  165. /*-------------------------------------------------------------------------*//**
  166. * <param name="output">Destination for balanced tree.</param>
  167. * <param name="data">Source data.</param>
  168. * <param name="size">Size of data.</param>
  169. * <returns>
  170. * Bintree_SortHalf.
  171. * </returns>
  172. * <remarks>
  173. * Entry point for Bintree_SortHalf.
  174. * </remarks>
  175. *//*------------------------------------------------------------------------**/
  176. P:D(Bintree_Fill(BinaryTree:output<>, data[][E_BINTREE_INPUT], size = sizeof (data)));
  177. #define Bintree_Fill(%1,%2,%3) \
  178. Bintree_SortHalf((%1), (%2), 0, (%3), 0, BINTREE_NO_BRANCH)
  179. /*-------------------------------------------------------------------------*//**
  180. * <param name="output">Binary tree to store the data in.</param>
  181. * <param name="input">Input data to get the data from.</param>
  182. * <param name="size">Number of items to sort.</param>
  183. * <remarks>
  184. * Just calls the sort and fill routines.
  185. * </remarks>
  186. *//*------------------------------------------------------------------------**/
  187. stock Bintree_Generate(BinaryTree:output<>, BinaryInput:input<>, size = sizeof (input))
  188. {
  189. P:3("Bintree_Generate called: %s, %s, %i", Bintree_DisplayOutput(output), Bintree_DisplayInput(input), size);
  190. if (!size)
  191. {
  192. output[0][E_BINTREE_TREE_PARENT] = BINTREE_NO_BRANCH;
  193. output[0][E_BINTREE_TREE_LEFT] = BINTREE_NO_BRANCH;
  194. output[0][E_BINTREE_TREE_RIGHT] = BINTREE_NO_BRANCH;
  195. return 0;
  196. }
  197. Bintree_Sort(input, size);
  198. Bintree_Fill(output, input, size);
  199. return 1;
  200. }
  201. /*-------------------------------------------------------------------------*//**
  202. * <param name="tree">Array to reset.</param>
  203. * <param name="pointer">Position to reset.</param>
  204. * <remarks>
  205. * Initialises the array for use.
  206. * </remarks>
  207. *//*------------------------------------------------------------------------**/
  208. stock Bintree_Reset(BinaryTree:tree<>, pointer = 0)
  209. {
  210. P:3("Bintree_Reset called: %s, %i", Bintree_DisplayOutput(tree), pointer);
  211. tree[pointer][E_BINTREE_TREE_VALUE] = 0;
  212. tree[pointer][E_BINTREE_TREE_LEFT] = BINTREE_NO_BRANCH;
  213. tree[pointer][E_BINTREE_TREE_RIGHT] = BINTREE_NO_BRANCH;
  214. tree[pointer][E_BINTREE_TREE_PARENT] = BINTREE_NO_BRANCH;
  215. tree[pointer][E_BINTREE_TREE_POINTER] = BINTREE_NOT_FOUND;
  216. }
  217. /*-------------------------------------------------------------------------*//**
  218. * <param name="tree">Tree to find the data in.</param>
  219. * <param name="value">Value to search for.</param>
  220. * <param name="cont">Start point.</param>
  221. * <param name="old">The last real leaf.</param>
  222. * <remarks>
  223. * Itterates through the array following the various paths till it locates
  224. * the value provided or reaches a dead end. If the current value is greater
  225. * than the search value, the search goes left, otherwise right.
  226. *
  227. * If cont is not -1 the search will start from the data pointed to by the
  228. * data pointed to by conts' right path, this is to allow collisions to be
  229. * passed over if you want a subsequent one.
  230. * </remarks>
  231. *//*------------------------------------------------------------------------**/
  232. stock Bintree_FindValue(BinaryTree:tree<>, value, &cont = 0, &old = 0)
  233. {
  234. P:3("Bintree_FindValue called: %s, %i, %i, %i", Bintree_DisplayOutput(tree), value, cont, old);
  235. new
  236. treeValue;
  237. while (cont != BINTREE_NO_BRANCH)
  238. {
  239. P:7("Bintree_FindValue: search %d %d %d %d", cont, old, tree[cont][E_BINTREE_TREE_VALUE], value);
  240. old = cont;
  241. treeValue = tree[old][E_BINTREE_TREE_VALUE];
  242. if (value < treeValue) cont = tree[old][E_BINTREE_TREE_LEFT];
  243. else
  244. {
  245. cont = tree[old][E_BINTREE_TREE_RIGHT];
  246. if (value == treeValue)
  247. {
  248. return tree[old][E_BINTREE_TREE_POINTER];
  249. }
  250. }
  251. }
  252. return BINTREE_NOT_FOUND;
  253. }
  254. /*-------------------------------------------------------------------------*//**
  255. * <param name="numbers">Data to sort.</param>
  256. * <param name="left">Start index.</param>
  257. * <param name="right">End index.</param>
  258. * <remarks>
  259. * Custom version of QSort (see YSI_misc) allows for E_BINTREE_INPUT data
  260. * types, preserving the relative pointers for the sorted data.
  261. * </remarks>
  262. *//*------------------------------------------------------------------------**/
  263. stock Bintree_QSort(numbers[][E_BINTREE_INPUT], left, right)
  264. {
  265. P:3("Bintree_QSort called: %s, %i, %i", Bintree_DisplayInput(numbers), left, right);
  266. new
  267. pivot = numbers[left][E_BINTREE_INPUT_VALUE],
  268. pointer = numbers[left][E_BINTREE_INPUT_POINTER],
  269. l_hold = left,
  270. r_hold = right;
  271. while (left < right)
  272. {
  273. while ((numbers[right][E_BINTREE_INPUT_VALUE] >= pivot) && (left < right)) right--;
  274. if (left != right)
  275. {
  276. numbers[left][E_BINTREE_INPUT_VALUE] = numbers[right][E_BINTREE_INPUT_VALUE];
  277. numbers[left][E_BINTREE_INPUT_POINTER] = numbers[right][E_BINTREE_INPUT_POINTER];
  278. left++;
  279. }
  280. while ((numbers[left][E_BINTREE_INPUT_VALUE] <= pivot) && (left < right)) left++;
  281. if (left != right)
  282. {
  283. numbers[right][E_BINTREE_INPUT_VALUE] = numbers[left][E_BINTREE_INPUT_VALUE];
  284. numbers[right][E_BINTREE_INPUT_POINTER] = numbers[left][E_BINTREE_INPUT_POINTER];
  285. right--;
  286. }
  287. }
  288. numbers[left][E_BINTREE_INPUT_VALUE] = pivot;
  289. numbers[left][E_BINTREE_INPUT_POINTER] = pointer;
  290. pivot = left;
  291. left = l_hold;
  292. right = r_hold;
  293. if (left < pivot) Bintree_QSort(numbers, left, pivot - 1);
  294. if (right > pivot) Bintree_QSort(numbers, pivot + 1, right);
  295. }
  296. /*-------------------------------------------------------------------------*//**
  297. * <param name="output">Destination array.</param>
  298. * <param name="data">Source array.</param>
  299. * <param name="index">Start index of the source for processing.</param>
  300. * <param name="upper">End index of the source for processing.</param>
  301. * <param name="offset">Current offset in the destination array for writing.</param>
  302. * <returns>
  303. * Size of balanced tree.
  304. * </returns>
  305. * <remarks>
  306. * Recursively calls itself. Bisects the passed array and passed each half
  307. * back to itself, with the middle value of each half being the left and
  308. * right branches of the middle value of the passed array (which isn't
  309. * included in either bisected half). This is itterative so those are again
  310. * split and again split. If the passed array is only one or two elements
  311. * big the behaviour is set and hardcoded.
  312. *
  313. * Equal values SHOULD branch right, the code is designed for this however
  314. * the generation is not fully tested (it mostly branches right but adjacent
  315. * after bisecting values haven't been tested).
  316. *
  317. * Based on code written for PHP by me.
  318. * </remarks>
  319. *//*------------------------------------------------------------------------**/
  320. stock Bintree_SortHalf(BinaryTree:output<>, data[][E_BINTREE_INPUT], index, upper, offset, parent)
  321. {
  322. P:3("Bintree_SortHalf called: %s, %s, %i, %i, %i, %i", Bintree_DisplayOutput(output), Bintree_DisplayInput(data), index, upper, offset, parent);
  323. new
  324. num = upper - index;
  325. if (!num) return offset;
  326. if (num == 1)
  327. {
  328. output[offset][E_BINTREE_TREE_VALUE] = data[index][E_BINTREE_INPUT_VALUE];
  329. output[offset][E_BINTREE_TREE_POINTER] = data[index][E_BINTREE_INPUT_POINTER];
  330. output[offset][E_BINTREE_TREE_PARENT] = parent;
  331. output[offset][E_BINTREE_TREE_LEFT] = BINTREE_NO_BRANCH;
  332. output[offset][E_BINTREE_TREE_RIGHT] = BINTREE_NO_BRANCH;
  333. }
  334. else if (num == 2)
  335. {
  336. P:3("Bintree_SortHalf: adding %i %i %i", index, data[index][E_BINTREE_INPUT_VALUE], data[index + 1][E_BINTREE_INPUT_VALUE]);
  337. output[offset][E_BINTREE_TREE_VALUE] = data[index][E_BINTREE_INPUT_VALUE];
  338. output[offset][E_BINTREE_TREE_POINTER] = data[index][E_BINTREE_INPUT_POINTER];
  339. output[offset][E_BINTREE_TREE_PARENT] = parent;
  340. output[offset][E_BINTREE_TREE_LEFT] = BINTREE_NO_BRANCH;
  341. output[offset][E_BINTREE_TREE_RIGHT] = offset + 1;
  342. ++offset;
  343. ++index;
  344. output[offset][E_BINTREE_TREE_VALUE] = data[index][E_BINTREE_INPUT_VALUE];
  345. output[offset][E_BINTREE_TREE_POINTER] = data[index][E_BINTREE_INPUT_POINTER];
  346. output[offset][E_BINTREE_TREE_PARENT] = offset - 1;
  347. output[offset][E_BINTREE_TREE_LEFT] = BINTREE_NO_BRANCH;
  348. output[offset][E_BINTREE_TREE_RIGHT] = BINTREE_NO_BRANCH;
  349. }
  350. else
  351. {
  352. new
  353. half = num / 2,
  354. off = half + index,
  355. right;
  356. while (off && data[off][E_BINTREE_INPUT_VALUE] == data[off - 1][E_BINTREE_INPUT_VALUE]) off--;
  357. right = Bintree_SortHalf(output, data, index, off, offset + 1, offset);
  358. output[offset][E_BINTREE_TREE_VALUE] = data[off][E_BINTREE_INPUT_VALUE];
  359. output[offset][E_BINTREE_TREE_POINTER] = data[off][E_BINTREE_INPUT_POINTER];
  360. output[offset][E_BINTREE_TREE_PARENT] = parent;
  361. output[offset][E_BINTREE_TREE_LEFT] = offset + 1;
  362. output[offset][E_BINTREE_TREE_RIGHT] = right;
  363. return Bintree_SortHalf(output, data, off + 1, upper, right, offset);
  364. }
  365. return offset + 1;
  366. }
  367. /*-------------------------------------------------------------------------*//**
  368. * <param name="data">Array to add to.</param>
  369. * <param name="pointer">Pointer to add.</param>
  370. * <param name="value">Value to add.</param>
  371. * <param name="offset">Location in the array to store the data.</param>
  372. * <param name="maxsize">Size of data.</param>
  373. * <returns>
  374. * Next free location
  375. * </returns>
  376. * <remarks>
  377. * -
  378. *
  379. * native Bintree_Add(BinaryTree:tree<>, pointer, value, offset, maxsize = sizeof (data));
  380. *
  381. * </remarks>
  382. *//*------------------------------------------------------------------------**/
  383. stock Bintree_Add(BinaryTree:data<>, pointer, value, offset, maxsize = sizeof (data))
  384. {
  385. P:3("Bintree_Add called: %s, %i, %i, %i, %i", Bintree_DisplayOutput(data), pointer, value, offset, maxsize);
  386. if (offset >= maxsize) return BINTREE_NOT_FOUND;
  387. if (offset)
  388. {
  389. new
  390. leaf,
  391. old;
  392. while (Bintree_FindValue(data, value, leaf, old) != BINTREE_NOT_FOUND) continue;
  393. //Bintree_Reset(data, offset);
  394. if (value < data[old][E_BINTREE_TREE_VALUE]) data[old][E_BINTREE_TREE_LEFT] = offset;
  395. else data[old][E_BINTREE_TREE_RIGHT] = offset;
  396. data[offset][E_BINTREE_TREE_PARENT] = old;
  397. data[offset][E_BINTREE_TREE_LEFT] = BINTREE_NO_BRANCH;
  398. data[offset][E_BINTREE_TREE_RIGHT] = BINTREE_NO_BRANCH;
  399. data[offset][E_BINTREE_TREE_VALUE] = value;
  400. data[offset][E_BINTREE_TREE_POINTER] = pointer;
  401. return offset + 1;
  402. }
  403. else
  404. {
  405. data[0][E_BINTREE_TREE_PARENT] = BINTREE_NO_BRANCH;
  406. data[0][E_BINTREE_TREE_LEFT] = BINTREE_NO_BRANCH;
  407. data[0][E_BINTREE_TREE_RIGHT] = BINTREE_NO_BRANCH;
  408. data[0][E_BINTREE_TREE_VALUE] = value;
  409. data[0][E_BINTREE_TREE_POINTER] = pointer;
  410. return 1;
  411. }
  412. }
  413. /*-------------------------------------------------------------------------*//**
  414. * <param name="tree">Data.</param>
  415. * <param name="index">Index to remove.</param>
  416. * <param name="count">Number of binary tree items.</param>
  417. * <remarks>
  418. * The left branch is usually larger due to the division
  419. * method used so we start there. Even though right is
  420. * >= and left is only < in even sized arrays the greater
  421. * chunk (unless there's only 2 items) goes left.
  422. *
  423. * Called itteratively to ensure branches are maintained.
  424. * </remarks>
  425. *//*------------------------------------------------------------------------**/
  426. stock Bintree_Delete(BinaryTree:source<>, index, count)
  427. {
  428. P:3("Bintree_Delete called: %s, %i, %i", Bintree_DisplayOutput(source), index, count);
  429. new
  430. branch,
  431. old = index;
  432. while (TRUE)
  433. {
  434. if ((branch = source[old][E_BINTREE_TREE_LEFT]) != BINTREE_NO_BRANCH) branch = Bintree_FindMax(source, branch);
  435. else if ((branch = source[old][E_BINTREE_TREE_RIGHT]) != BINTREE_NO_BRANCH) branch = Bintree_FindMin(source, branch);
  436. else
  437. {
  438. if ((branch = source[old][E_BINTREE_TREE_PARENT]) != BINTREE_NO_BRANCH)
  439. {
  440. if (source[branch][E_BINTREE_TREE_LEFT] == old) source[branch][E_BINTREE_TREE_LEFT] = BINTREE_NO_BRANCH;
  441. else source[branch][E_BINTREE_TREE_RIGHT] = BINTREE_NO_BRANCH;
  442. }
  443. return Bintree_Compress(source, old, count);
  444. }
  445. new
  446. value = source[old][E_BINTREE_TREE_VALUE],
  447. pointer = source[old][E_BINTREE_TREE_POINTER];
  448. source[old][E_BINTREE_TREE_VALUE] = source[branch][E_BINTREE_TREE_VALUE];
  449. source[old][E_BINTREE_TREE_POINTER] = source[branch][E_BINTREE_TREE_POINTER];
  450. source[branch][E_BINTREE_TREE_VALUE] = value;
  451. source[branch][E_BINTREE_TREE_POINTER] = pointer;
  452. old = branch;
  453. }
  454. return BINTREE_NO_BRANCH;
  455. }
  456. /*-------------------------------------------------------------------------*//**
  457. * <param name="tree">Array to compress.</param>
  458. * <param name="index">Point to start at.</param>
  459. * <param name="count">Number of items total.</param>
  460. *//*------------------------------------------------------------------------**/
  461. static stock Bintree_Compress(BinaryTree:data<>, index, count)
  462. {
  463. P:4("Bintree_Compress called: %s, %i, %i", Bintree_DisplayOutput(data), index, count);
  464. new
  465. index2 = index + 1;
  466. while (index < count)
  467. {
  468. new
  469. left = (data[index][E_BINTREE_TREE_LEFT] = data[index2][E_BINTREE_TREE_LEFT]),
  470. right = (data[index][E_BINTREE_TREE_RIGHT] = data[index2][E_BINTREE_TREE_RIGHT]),
  471. parent = (data[index][E_BINTREE_TREE_PARENT] = data[index2][E_BINTREE_TREE_PARENT]);
  472. data[index][E_BINTREE_TREE_VALUE] = data[index2][E_BINTREE_TREE_VALUE];
  473. data[index][E_BINTREE_TREE_POINTER] = data[index2][E_BINTREE_TREE_POINTER];
  474. if (left != BINTREE_NO_BRANCH) data[left][E_BINTREE_TREE_PARENT] = index;
  475. if (right != BINTREE_NO_BRANCH) data[right][E_BINTREE_TREE_PARENT] = index;
  476. if (parent != BINTREE_NO_BRANCH)
  477. {
  478. if (data[parent][E_BINTREE_TREE_LEFT] == index2) data[parent][E_BINTREE_TREE_LEFT] = index;
  479. else if (data[parent][E_BINTREE_TREE_RIGHT] == index2) data[parent][E_BINTREE_TREE_RIGHT] = index;
  480. }
  481. index++;
  482. index2++;
  483. }
  484. return count - 1;
  485. }
  486. /*-------------------------------------------------------------------------*//**
  487. * <param name="data">Array to search.</param>
  488. * <param name="offset">Start of branch to search.</param>
  489. * <remarks>
  490. * Finds the smallest value on a branch
  491. * </remarks>
  492. *//*------------------------------------------------------------------------**/
  493. static stock Bintree_FindMin(BinaryTree:data<>, offset)
  494. {
  495. P:4("Bintree_FindMin called: %s, %i", Bintree_DisplayOutput(data), offset);
  496. new
  497. branch;
  498. while ((branch = data[offset][E_BINTREE_TREE_LEFT]) != BINTREE_NO_BRANCH) offset = branch;
  499. return offset;
  500. }
  501. /*-------------------------------------------------------------------------*//**
  502. * <param name="data">Array to search.</param>
  503. * <param name="offset">Start of branch to search.</param>
  504. * <remarks>
  505. * Finds the largest value on a branch
  506. * </remarks>
  507. *//*------------------------------------------------------------------------**/
  508. static stock Bintree_FindMax(BinaryTree:data<>, offset)
  509. {
  510. P:4("Bintree_FindMax called: %s, %i", Bintree_DisplayOutput(data), offset);
  511. new
  512. branch;
  513. while ((branch = data[offset][E_BINTREE_TREE_RIGHT]) != BINTREE_NO_BRANCH) offset = branch;
  514. return offset;
  515. }
  516. /*-------------------------------------------------------------------------*//**
  517. * <param name="data">Data to modify.</param>
  518. * <param name="offset">Pointer to modify values after.</param>
  519. * <param name="mod">Value to modify by.</param>
  520. * <remarks>
  521. * Used for updating pointers when the target data has been modifed (i.e. a
  522. * value has been removed from the array and the array shifted).
  523. * </remarks>
  524. *//*------------------------------------------------------------------------**/
  525. stock Bintree_UpdatePointers(BinaryTree:data<>, offset, size, mod = -1)
  526. {
  527. P:3("Bintree_UpdatePointers called: %s, %i, %i, %i", Bintree_DisplayOutput(data), offset, size, mod);
  528. for (new i = 0; i < size; i++)
  529. {
  530. if (data[i][E_BINTREE_TREE_POINTER] > offset) data[i][E_BINTREE_TREE_POINTER] += mod;
  531. }
  532. }