Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

501 lines
11 KiB

  1. /* --------------------------------------------------------------------
  2. Microsoft OS/2 LAN Manager
  3. Copyright(c) Microsoft Corp., 1990
  4. RPC - Written by Dov Harel
  5. This file contains the implementation for splay tree self
  6. adjusting binary trees
  7. -------------------------------------------------------------------- */
  8. #if 0
  9. #include "objidl.h"
  10. #include "common.h"
  11. #endif // 0
  12. #include "precomp.hxx"
  13. // handly macros used to define common tree operations
  14. #define ROTATELEFT tmp=t->right; t->right=tmp->left; tmp->left =t; t=tmp
  15. #define ROTATERIGHT tmp=t->left; t->left =tmp->right; tmp->right=t; t=tmp
  16. #define LINKLEFT tmp=t; t = t->right; l = l->right = tmp
  17. #define LINKRIGHT tmp=t; t = t->left; r = r->left = tmp
  18. #define ASSEMBLE r->left = t->right; l->right = t->left; \
  19. t->left = Dummy->right; t->right = Dummy->left
  20. TreeNode Dumbo(Nil);
  21. static TreeNode *Dummy = &Dumbo; // a global dummy node
  22. TreeNode *
  23. GetGlobalTreeNode()
  24. {
  25. return( &Dumbo );
  26. }
  27. // initialize the memory allocator for TreeNode
  28. //*************************************************************************
  29. //***** Core functions (internal) *****
  30. //*************************************************************************
  31. long // return last comparision
  32. Dictionary::SplayUserType( // general top down splay
  33. pUserType keyItem // pointer to a "key item" searched for
  34. ) //-----------------------------------------------------------------------//
  35. {
  36. TreeNode* t; // current search point
  37. TreeNode* l; // root of "left subtree" < keyItem
  38. TreeNode* r; // root of "right subtree" > keyItem
  39. long kcmp; // cash comparison results
  40. TreeNode* tmp;
  41. if ((fCompare = Compare(keyItem, root->item)) == 0)
  42. return (fCompare);
  43. Dummy = l = r = &Dumbo;
  44. Dumbo.left = Dumbo.right = Nil;
  45. t = root;
  46. do {
  47. if ( fCompare < 0 ) {
  48. if ( t->left == Nil ) break;
  49. if ( (kcmp = Compare(keyItem, t->left->item)) == 0 ) {
  50. LINKRIGHT;
  51. }
  52. else if ( kcmp < 0 ) {
  53. ROTATERIGHT;
  54. if ( t->left != Nil ) {
  55. LINKRIGHT;
  56. }
  57. }
  58. else { // keyItem > t->left->item
  59. LINKRIGHT;
  60. if ( t->right != Nil ) {
  61. LINKLEFT;
  62. }
  63. }
  64. }
  65. else { // keyItem > t->item
  66. if ( t->right == Nil ) break;
  67. if ( (kcmp = Compare(keyItem, t->right->item)) == 0 ) {
  68. LINKLEFT;
  69. }
  70. else if ( kcmp > 0 ) {
  71. ROTATELEFT;
  72. if ( t->right != Nil ) {
  73. LINKLEFT;
  74. }
  75. }
  76. else { // keyItem < t->right->item
  77. LINKLEFT;
  78. if ( t->left != Nil ) {
  79. LINKRIGHT;
  80. }
  81. }
  82. }
  83. } while ( (fCompare = Compare(keyItem, t->item)) != 0 );
  84. ASSEMBLE;
  85. // if (fCompare != Compare(keyItem, t->item))
  86. // printf("Dictionary error!");
  87. root = t;
  88. return(fCompare);
  89. }
  90. TreeNode*
  91. SplayLeft(
  92. TreeNode* t // root of tree & current "search" point
  93. ) //-----------------------------------------------------------------------//
  94. {
  95. TreeNode* l=Dummy; // root of "left subtree" < keyItem
  96. TreeNode* r=Dummy; // root of "right subtree" > keyItem
  97. TreeNode* tmp;
  98. if (t == Nil || t->left == Nil)
  99. return(t);
  100. if (t->left->left == Nil) {
  101. ROTATERIGHT;
  102. return(t);
  103. }
  104. Dummy->left = Dummy->right = Nil;
  105. while ( t->left != Nil ) {
  106. ROTATERIGHT;
  107. if ( t->left != Nil ) {
  108. LINKRIGHT;
  109. }
  110. }
  111. ASSEMBLE;
  112. return(t);
  113. }
  114. #ifndef DICT_NOPREV
  115. TreeNode*
  116. SplayRight(
  117. TreeNode* t // root of tree & current "search" point
  118. ) //-----------------------------------------------------------------------//
  119. {
  120. TreeNode* l=Dummy; // root of "left subtree" < keyItem
  121. TreeNode* r=Dummy; // root of "right subtree" > keyItem
  122. TreeNode* tmp;
  123. if (t == Nil || t->right == Nil)
  124. return(t);
  125. Dummy->left = Dummy->right = Nil;
  126. while ( t->right != Nil ) {
  127. ROTATELEFT;
  128. if ( t->right != Nil ) {
  129. LINKLEFT;
  130. }
  131. }
  132. ASSEMBLE;
  133. return(t);
  134. }
  135. #endif
  136. // Class methods for Splay Tree
  137. Dict_Status
  138. Dictionary::Dict_Find( // return a item that matches
  139. pUserType itemI // this value
  140. // Returns:
  141. // itemCur - Nil if at not in Dict, else found item
  142. ) //-----------------------------------------------------------------------//
  143. {
  144. itemCur = Nil;
  145. if (root == Nil)
  146. return (EMPTY_DICTIONARY);
  147. if (itemI == Nil)
  148. return (NULL_ITEM);
  149. if (SplayUserType (itemI) == 0){
  150. itemCur = root->item;
  151. return(SUCCESS);
  152. }
  153. // printf("After NotFound %ld: (", this); PrintItem(itemI); printf(")\n"); Dict_Print();
  154. return(ITEM_NOT_FOUND);
  155. }
  156. #ifndef DICT_NONEXT
  157. Dict_Status
  158. Dictionary::Dict_Next( // return the next item
  159. pUserType itemI // of a key greater then this
  160. // Returns:
  161. // itemCur - Nil if at end of Dict, else current item
  162. ) //-----------------------------------------------------------------------//
  163. {
  164. TreeNode* t;
  165. itemCur = Nil;
  166. if (root == Nil)
  167. return (EMPTY_DICTIONARY);
  168. if (itemI == Nil) { // no arg, return first record
  169. root = SplayLeft (root);
  170. itemCur = root->item;
  171. return (SUCCESS);
  172. }
  173. if (itemI != root->item)
  174. if (SplayUserType (itemI) > 0) {
  175. itemCur = root->item;
  176. return (SUCCESS);
  177. }
  178. if (root->right == Nil)
  179. return (LAST_ITEM);
  180. t = root;
  181. root = SplayLeft (root->right);
  182. root->left = t;
  183. t->right = Nil;
  184. itemCur = root->item;
  185. return (SUCCESS);
  186. }
  187. #endif // DICT_NONEXT
  188. #ifndef DICT_NOPREV
  189. Dict_Status
  190. Dictionary::Dict_Prev( // return the previous item
  191. pUserType itemI // of a key less then this
  192. // Returns:
  193. // itemCur - Nil if at begining of Dict, else current item
  194. ) //-----------------------------------------------------------------------//
  195. {
  196. TreeNode* t;
  197. itemCur = Nil;
  198. if (root == Nil)
  199. return (EMPTY_DICTIONARY);
  200. if (itemI == Nil) { // no arg, return last record
  201. root = SplayRight (root);
  202. itemCur = root->item;
  203. return (SUCCESS);
  204. }
  205. if (itemI != root->item)
  206. if (SplayUserType (itemI) < 0) {
  207. itemCur = root->item;
  208. return (SUCCESS);
  209. }
  210. if (root->left == Nil)
  211. return (LAST_ITEM);
  212. t = root;
  213. root = SplayRight (root->left);
  214. root->right = t;
  215. t->left = Nil;
  216. itemCur = root->item;
  217. return (SUCCESS);
  218. }
  219. #endif // DICT_NOPREV
  220. Dict_Status
  221. Dictionary::Dict_Insert( // insert the given item into the tree
  222. pUserType itemI // the item to be inserted
  223. // Returns:
  224. // itemCur - point to new item
  225. ) //-----------------------------------------------------------------------//
  226. {
  227. TreeNode *newNode, *t;
  228. if ((itemCur = itemI) == Nil)
  229. return (NULL_ITEM);
  230. if (root == Nil) {
  231. root = new TreeNode(itemI);
  232. size++;
  233. return (SUCCESS);
  234. }
  235. if (SplayUserType (itemI) == 0)
  236. return (ITEM_ALREADY_PRESENT);
  237. newNode = new TreeNode(itemI);
  238. size++;
  239. t = root;
  240. if (fCompare > 0) {
  241. newNode->right = t->right; // item >= t->item
  242. newNode->left = t;
  243. t->right = Nil;
  244. }
  245. else {
  246. newNode->left = t->left;
  247. newNode->right = t;
  248. t->left = Nil;
  249. }
  250. root = newNode;
  251. // printf("After Insert %ld: (", this); PrintItem(itemI); printf(")\n"); Dict_Print();
  252. return (SUCCESS);
  253. }
  254. Dict_Status
  255. Dictionary::Dict_Delete( // delete the given item from the tree
  256. pUserType *itemI // points to the (key) item to be deleted
  257. // Returns:
  258. // itemCur is Nil - undefined
  259. ) //-----------------------------------------------------------------------//
  260. {
  261. TreeNode *t, *r;
  262. itemCur = Nil;
  263. if (root == Nil)
  264. return (EMPTY_DICTIONARY);
  265. if (itemI == Nil)
  266. return (NULL_ITEM);
  267. if (itemI != root->item) {
  268. if (SplayUserType (*itemI) != 0)
  269. return(ITEM_NOT_FOUND);
  270. }
  271. *itemI = root->item;
  272. t = root;
  273. if (t->left == Nil)
  274. root = t->right;
  275. else if ( (r = t->right) == Nil)
  276. root = t->left;
  277. else {
  278. r = SplayLeft (r);
  279. r->left = t->left; // at this point r->left == Nil
  280. root = r;
  281. }
  282. delete t;
  283. size--;
  284. return (SUCCESS);
  285. }
  286. pUserType
  287. Dictionary::Dict_Delete_One()
  288. {
  289. TreeNode * pCurrent = root;
  290. TreeNode * pPrev = NULL; // NULL indicates prev is root
  291. pUserType pResult;
  292. int fLeft;
  293. while ( pCurrent )
  294. {
  295. if ( pCurrent->left )
  296. {
  297. pPrev = pCurrent;
  298. pCurrent = pCurrent->left;
  299. fLeft = 1;
  300. continue;
  301. }
  302. if ( pCurrent->right )
  303. {
  304. pPrev = pCurrent;
  305. pCurrent = pCurrent->right;
  306. fLeft = 0;
  307. continue;
  308. }
  309. // found a leaf
  310. break;
  311. }
  312. // we are now at a leaf (or tree empty)
  313. if ( !pCurrent )
  314. return NULL;
  315. // unhook from parent
  316. if ( pPrev )
  317. {
  318. if ( fLeft )
  319. pPrev->left = NULL;
  320. else
  321. pPrev->right = NULL;
  322. }
  323. else
  324. root = NULL;
  325. // return the item, and delete the treenode
  326. pResult = pCurrent->item;
  327. delete pCurrent;
  328. size--;
  329. return pResult;
  330. }
  331. // Utility functions to print of a tree
  332. #ifndef DICT_NOPRINT
  333. static indentCur;
  334. static PrintFN printCur;
  335. static char spaces[] =
  336. " ";
  337. void
  338. Dictionary::PrinTree( // recursively print out a tree
  339. int lmargin, // current depth & margen
  340. TreeNode *np // subtree to print
  341. ) //-----------------------------------------------------------------------//
  342. {
  343. #if 0
  344. if (np == Nil)
  345. return;
  346. PrinTree(lmargin+indentCur, np->right);
  347. if (lmargin > sizeof(spaces))
  348. lmargin = sizeof(spaces);;
  349. spaces[lmargin] = 0;
  350. printf(spaces);
  351. spaces[lmargin] = ' ';
  352. Print(np->item);
  353. printf("\n");
  354. PrinTree(lmargin+indentCur, np->left);
  355. #endif // 0
  356. }
  357. void
  358. Dictionary::Dict_Print(
  359. long indent
  360. // prints the binary tree (indented right subtree,
  361. // followed by the root, followed by the indented right dubtree)
  362. ) //-----------------------------------------------------------------------//
  363. {
  364. indentCur = indent;
  365. PrinTree(0, root);
  366. }
  367. #endif // DICT_PRINT