Advertisement
Guest User

Untitled

a guest
Oct 28th, 2012
409
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 14.40 KB | None | 0 0
  1. //----------------------------------------------------------------------------
  2. //
  3. // PATRICIA Trie Template Class
  4. //
  5. // Released into the public domain on February 3, 2005 by:
  6. //
  7. // Radu Gruian
  8. // web: http://www.gruian.com
  9. //
  10. // This program is free software; you can redistribute it and/or modify
  11. // it under the terms of the GNU General Public License as published by
  12. // the Free Software Foundation; either version 2 of the License, or
  13. // (at your option) any later version.
  14. //
  15. // This program is distributed in the hope that it will be useful,
  16. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  18. // GNU General Public License for more details.
  19. //
  20. // You should have received a copy of the GNU General Public License
  21. // along with this program; if not, write to:
  22. //
  23. // Free Software Foundation, Inc.
  24. // 59 Temple Place, Suite 330
  25. // Boston, MA 02111-1307
  26. // USA
  27. //
  28. //----------------------------------------------------------------------------
  29. //
  30. // File: PatriciaTrie.h
  31. // Date: 02/03/2005
  32. // Purpose: Patricia trie ADT.
  33. //
  34. //----------------------------------------------------------------------------
  35.  
  36. #ifndef PatriciaTrieH
  37. #define PatriciaTrieH
  38.  
  39. #include <stdlib.h>
  40. #include <string.h>
  41.  
  42. typedef char* PatriciaTrieKey;
  43. template <class T> class PatriciaTrie;
  44.  
  45.  
  46. //----------------------------------------------------------------------------
  47. //
  48. // Class: PatriciaTrieNode
  49. // Purpose: A node in a PATRICIA trie.
  50. // Each node stores one key, and the data associated with that key.
  51. //
  52. //----------------------------------------------------------------------------
  53. template <class T>
  54. class PatriciaTrieNode {
  55. private:
  56. friend class PatriciaTrie<T>;
  57. int bit_index;
  58. PatriciaTrieKey key;
  59. T data;
  60. PatriciaTrieNode<T>* left;
  61. PatriciaTrieNode<T>* right;
  62.  
  63. public:
  64.  
  65. // Constructors & destructor
  66. PatriciaTrieNode();
  67. PatriciaTrieNode(PatriciaTrieKey, T, int, PatriciaTrieNode<T>*, PatriciaTrieNode<T>*);
  68. virtual ~PatriciaTrieNode();
  69.  
  70. // Name: Initialize
  71. // Args: key, data, left, right
  72. // Return: void
  73. // Purpose: Initialize this node with the given data.
  74. void Initialize(PatriciaTrieKey, T, int, PatriciaTrieNode<T>*, PatriciaTrieNode<T>*);
  75.  
  76. // Name: GetData/SetData
  77. // Args: data : T
  78. // Return: T | bool
  79. // Purpose: Accessors for the data field.
  80. T GetData();
  81. bool SetData(T);
  82.  
  83. // Name: GetKey
  84. // Args: none
  85. // Return: char*
  86. // Purpose: Getter for the key field.
  87. PatriciaTrieKey GetKey();
  88.  
  89. // Name: GetLeft/GetRight
  90. // Args: none
  91. // Return: PatriciaTrieNode*
  92. // Purpose: Getters for the left/right fields.
  93. PatriciaTrieNode<T>* GetLeft();
  94. PatriciaTrieNode<T>* GetRight();
  95.  
  96. };
  97.  
  98. //----------------------------------------------------------------------------
  99. //
  100. // Class: PatriciaTrie
  101. // Purpose: Implements a PATRICIA trie structure with keys of
  102. // type PatriciaTrieKey (currently char*, but can be changed, see
  103. // the definition of PatriciaTrieKey above).
  104. //
  105. //----------------------------------------------------------------------------
  106. template <class T>
  107. class PatriciaTrie {
  108. private:
  109. void recursive_remove(PatriciaTrieNode<T>*);
  110. int bit_get(PatriciaTrieKey, int);
  111. int bit_first_different(PatriciaTrieKey, PatriciaTrieKey);
  112. bool key_compare(PatriciaTrieKey, PatriciaTrieKey);
  113. void key_copy(PatriciaTrieNode<T>*, PatriciaTrieNode<T>*);
  114. PatriciaTrieNode<T>* head;
  115.  
  116. public:
  117.  
  118. // Constructor and destructor
  119. PatriciaTrie();
  120. virtual ~PatriciaTrie();
  121.  
  122. // Name: Insert(key, data)
  123. // Args: key : PatriciaTrieKey, data : T
  124. // Return: PatriciaTrieNode*
  125. // Purpose: Insert a new key+data pair in the Patricia structure, and
  126. // return the new node.
  127. virtual PatriciaTrieNode<T>* Insert(PatriciaTrieKey, T);
  128.  
  129. // Name: Lookup(key)
  130. // Args: key : PatriciaTrieKey
  131. // Return: T
  132. // Purpose: Search for the given key, and return the data associated
  133. // with it (or NULL).
  134. virtual T Lookup(PatriciaTrieKey);
  135.  
  136. // Name: LookupNode(key)
  137. // Args: key : PatriciaTrieKey
  138. // Return: T
  139. // Purpose: Search for the given key, and return the node that
  140. // contains it (or NULL).
  141. virtual PatriciaTrieNode<T>* LookupNode(PatriciaTrieKey);
  142.  
  143. // Name: Delete(key)
  144. // Args: key : PatriciaTrieKey
  145. // Return: bool
  146. // Purpose: Remove the node containing the given key. Return
  147. // true if the operation succeeded, false otherwise.
  148. virtual bool Delete(PatriciaTrieKey);
  149.  
  150. };
  151.  
  152. //----------------------------------------------------------------------------
  153. template <class T>
  154. PatriciaTrieNode<T>::PatriciaTrieNode() {
  155. Initialize(NULL, NULL, -1, this, this);
  156. }
  157.  
  158. //----------------------------------------------------------------------------
  159. template <class T>
  160. PatriciaTrieNode<T>::PatriciaTrieNode(PatriciaTrieKey k,
  161. T d,
  162. int bi,
  163. PatriciaTrieNode<T>* l,
  164. PatriciaTrieNode<T>* r) {
  165. Initialize(k, d, bi, l, r);
  166. }
  167.  
  168. //----------------------------------------------------------------------------
  169. template <class T>
  170. void PatriciaTrieNode<T>::Initialize(PatriciaTrieKey k,
  171. T d,
  172. int bi,
  173. PatriciaTrieNode<T>* l,
  174. PatriciaTrieNode<T>* r) {
  175. if (k)
  176. key = (PatriciaTrieKey)strdup(k);
  177. else
  178. key = k;
  179. data = d;
  180. left = l;
  181. right = r;
  182. bit_index = bi;
  183. }
  184.  
  185. //----------------------------------------------------------------------------
  186. template <class T>
  187. PatriciaTrieNode<T>::~PatriciaTrieNode() {
  188. if (key) {
  189. free(key);
  190. key = NULL;
  191. }
  192. }
  193.  
  194. //----------------------------------------------------------------------------
  195. template <class T>
  196. T PatriciaTrieNode<T>::GetData() {
  197. return data;
  198. }
  199.  
  200. //----------------------------------------------------------------------------
  201. template <class T>
  202. bool PatriciaTrieNode<T>::SetData(T d) {
  203. memcpy(&data, &d, sizeof(T));
  204. return true;
  205. }
  206.  
  207. //----------------------------------------------------------------------------
  208. template <class T>
  209. PatriciaTrieKey PatriciaTrieNode<T>::GetKey() {
  210. return key;
  211. }
  212.  
  213. //----------------------------------------------------------------------------
  214. template <class T>
  215. PatriciaTrieNode<T>* PatriciaTrieNode<T>::GetLeft() {
  216. return left;
  217. }
  218.  
  219. //----------------------------------------------------------------------------
  220. template <class T>
  221. PatriciaTrieNode<T>* PatriciaTrieNode<T>::GetRight() {
  222. return right;
  223. }
  224.  
  225. //----------------------------------------------------------------------------
  226. template <class T>
  227. PatriciaTrie<T>::PatriciaTrie() {
  228. // Create the head of the structure. The head is never moved
  229. // around in the trie (i.e. it always stays at the top of the structure).
  230. // This prevents further complications having to do with node removal.
  231. head = new PatriciaTrieNode<T>();
  232. #define ZEROTAB_SIZE 256
  233. head->key = (char*)calloc(ZEROTAB_SIZE, 1);
  234. }
  235.  
  236. //----------------------------------------------------------------------------
  237. template <class T>
  238. PatriciaTrie<T>::~PatriciaTrie() {
  239. recursive_remove(head);
  240. }
  241.  
  242. //----------------------------------------------------------------------------
  243. template <class T>
  244. PatriciaTrieNode<T>* PatriciaTrie<T>::Insert(PatriciaTrieKey k, T d) {
  245.  
  246. PatriciaTrieNode<T> *p, *t, *x;
  247.  
  248. // Start at the root
  249. p = head;
  250. t = (PatriciaTrieNode<T>*)(p->right);
  251.  
  252. // Navigate down the tree and look for the key
  253. while (p->bit_index < t->bit_index) {
  254. p = t;
  255. t = (PatriciaTrieNode<T>*)(bit_get(k, t->bit_index) ? t->right : t->left);
  256. }
  257.  
  258. // Is the key already in the tree?
  259. if (key_compare(k, t->key))
  260. return NULL; // Already in the tree!
  261.  
  262. // Find the first bit that does not match.
  263. int i = bit_first_different(k, t->key);
  264.  
  265. // Find the appropriate place in the tree where
  266. // the node has to be inserted
  267. p = head;
  268. x = (PatriciaTrieNode<T>*)(p->right);
  269. while ( ( p->bit_index < x->bit_index ) &&
  270. ( x->bit_index < i) ) {
  271. p = x;
  272. x = (PatriciaTrieNode<T>*)(bit_get(k, x->bit_index) ? x->right : x->left);
  273. }
  274.  
  275. // Allocate a new node and initialize it.
  276. t = new PatriciaTrieNode<T>();
  277. t->Initialize(k, d, i, (bit_get(k, i) ? x : t), (bit_get(k, i) ? t : x));
  278.  
  279. // Rewire
  280. if (bit_get(k, p->bit_index))
  281. p->right = t;
  282. else
  283. p->left = t;
  284.  
  285. // Return the newly created node
  286. return t;
  287.  
  288. }
  289.  
  290. //----------------------------------------------------------------------------
  291. template <class T>
  292. T PatriciaTrie<T>::Lookup(PatriciaTrieKey k) {
  293.  
  294. // Lookup the node
  295. PatriciaTrieNode<T>* node = LookupNode(k);
  296.  
  297. // Failed?
  298. if (!node)
  299. return NULL;
  300.  
  301. // Return the data stored in this node
  302. return node->data;
  303.  
  304. }
  305.  
  306. //----------------------------------------------------------------------------
  307. template <class T>
  308. PatriciaTrieNode<T>* PatriciaTrie<T>::LookupNode(PatriciaTrieKey k) {
  309.  
  310. PatriciaTrieNode<T>* p;
  311. PatriciaTrieNode<T>* x;
  312.  
  313. // Start at the root.
  314. p = head;
  315. x = (PatriciaTrieNode<T>*)(head->right);
  316.  
  317. // Go down the Patricia structure until an upward
  318. // link is encountered.
  319. while (p->bit_index < x->bit_index) {
  320. p = x;
  321. x = (PatriciaTrieNode<T>*)(bit_get(k, x->bit_index) ? x->right : x->left);
  322. }
  323.  
  324. // Perform a full string comparison, and return NULL if
  325. // the key is not found at this location in the structure.
  326. if (!key_compare(k, x->key))
  327. return NULL;
  328.  
  329. // Return the node
  330. return x;
  331.  
  332. }
  333.  
  334. //----------------------------------------------------------------------------
  335. template <class T>
  336. bool PatriciaTrie<T>::Delete(PatriciaTrieKey k) {
  337.  
  338. PatriciaTrieNode<T> *p, *t, *x, *pp, *lp;
  339. int bp, bl, br;
  340. char* key = NULL;
  341.  
  342. // Start at the root
  343. p = head;
  344. t = (PatriciaTrieNode<T>*)(p->right);
  345.  
  346. // Navigate down the tree and look for the key
  347. while (p->bit_index < t->bit_index) {
  348. pp = p;
  349. p = t;
  350. t = (PatriciaTrieNode<T>*)(bit_get(k, t->bit_index) ? t->right : t->left);
  351. }
  352.  
  353. // Is the key in the tree? If not, get out!
  354. if (!key_compare(k, t->key))
  355. return false; // The key could not be found!
  356.  
  357. // Copy p's key to t
  358. if (t != p)
  359. key_copy(p, t);
  360.  
  361. // Is p a leaf?
  362. bp = p->bit_index;
  363. bl = ((PatriciaTrieNode<T>*)(p->left))->bit_index;
  364. br = ((PatriciaTrieNode<T>*)(p->right))->bit_index;
  365.  
  366. if ((bl > bp) || (br > bp)) {
  367.  
  368. // There is at least one downward edge.
  369.  
  370. if (p != t) {
  371.  
  372. // Look for a new (intermediate) key
  373. key = strdup(p->key);
  374.  
  375. lp = p;
  376. x = (PatriciaTrieNode<T>*)(bit_get(key, p->bit_index) ? p->right : p->left);
  377.  
  378. while (lp->bit_index < x->bit_index) {
  379. lp = x;
  380. x = (PatriciaTrieNode<T>*)(bit_get(key, x->bit_index) ? x->right : x->left);
  381. }
  382.  
  383. // If the intermediate key was not found, we have a problem..
  384. if (!key_compare(key, x->key)) {
  385. free(key);
  386. return false; // The key could not be found!
  387. }
  388.  
  389. // Rewire the leaf (lp) to point to t
  390. if (bit_get(key, lp->bit_index))
  391. lp->right = t;
  392. else
  393. lp->left = t;
  394.  
  395. }
  396.  
  397. // Rewire the parent to point to the real child of p
  398. if (pp != p) {
  399. PatriciaTrieNode<T>* ch = (PatriciaTrieNode<T>*)(bit_get(k, p->bit_index) ? p->left : p->right);
  400. if (bit_get(k, pp->bit_index))
  401. pp->right = ch;
  402. else
  403. pp->left = ch;
  404. }
  405.  
  406. // We no longer need 'key'
  407. free(key);
  408. key = NULL;
  409.  
  410. } else {
  411.  
  412. // Both edges (left, right) are pointing upwards or to the node (self-edges).
  413.  
  414. // Rewire the parent
  415. if (pp != p) {
  416. PatriciaTrieNode<T>* blx = (PatriciaTrieNode<T>*)(p->left);
  417. PatriciaTrieNode<T>* brx = (PatriciaTrieNode<T>*)(p->right);
  418. if (bit_get(k, pp->bit_index))
  419. pp->right = (((blx == brx) && (blx == p)) ? pp : ((blx==p)?brx:blx));
  420. else
  421. pp->left = (((blx == brx) && (blx == p)) ? pp : ((blx==p)?brx:blx));
  422. }
  423.  
  424. }
  425.  
  426. // Deallocate p (no longer needed)
  427. delete p;
  428.  
  429. // Success!
  430. return true;
  431.  
  432. }
  433.  
  434. //----------------------------------------------------------------------------
  435. template <class T>
  436. void PatriciaTrie<T>::recursive_remove(PatriciaTrieNode<T>* root) {
  437.  
  438. PatriciaTrieNode<T>* l = (PatriciaTrieNode<T>*)root->left;
  439. PatriciaTrieNode<T>* r = (PatriciaTrieNode<T>*)root->right;
  440.  
  441. // Remove the left branch
  442. if ( (l->bit_index >= root->bit_index) && (l != root) && (l != head) )
  443. recursive_remove(l);
  444.  
  445. // Remove the right branch
  446. if ( (r->bit_index >= root->bit_index) && (r != root) && (r != head) )
  447. recursive_remove(r);
  448.  
  449. // Remove the root
  450. delete root;
  451.  
  452. }
  453.  
  454. //----------------------------------------------------------------------------
  455. template <class T>
  456. int PatriciaTrie<T>::bit_get(PatriciaTrieKey bit_stream, int n) {
  457. if (n < 0) return 2; // "pseudo-bit" with a value of 2.
  458. int k = (n & 0x7);
  459. return ( (*(bit_stream + (n >> 3))) >> k) & 0x1;
  460. }
  461.  
  462. //----------------------------------------------------------------------------
  463. template <class T>
  464. bool PatriciaTrie<T>::key_compare(PatriciaTrieKey k1, PatriciaTrieKey k2) {
  465. if (!k1 || !k2)
  466. return false;
  467. return (strcmp((char*)k1, (char*)k2) == 0);
  468. }
  469.  
  470. //----------------------------------------------------------------------------
  471. template <class T>
  472. int PatriciaTrie<T>::bit_first_different(PatriciaTrieKey k1, PatriciaTrieKey k2) {
  473. if (!k1 || !k2)
  474. return 0; // First bit is different!
  475. int n = 0;
  476. int d = 0;
  477. while ( (k1[n] == k2[n]) &&
  478. (k1[n] != 0) &&
  479. (k2[n] != 0) )
  480. n++;
  481. while (bit_get(&k1[n], d) == bit_get(&k2[n], d))
  482. d++;
  483. return ((n << 3) + d);
  484. }
  485.  
  486. //----------------------------------------------------------------------------
  487. template <class T>
  488. void PatriciaTrie<T>::key_copy(PatriciaTrieNode<T>* src, PatriciaTrieNode<T>* dest) {
  489.  
  490. if (src == dest)
  491. return;
  492.  
  493. // Copy the key from src to dest
  494. if (strlen(dest->key) < strlen(src->key))
  495. dest->key = (PatriciaTrieKey)realloc(dest->key, 1 + strlen(src->key));
  496. strcpy(dest->key, src->key);
  497.  
  498. // Copy the data from src to dest
  499. dest->data = src->data;
  500.  
  501. // How about the bit index?
  502. //dest->bit_index = src->bit_index;
  503.  
  504. }
  505.  
  506.  
  507. #endif
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement