Windows NT 4.0 source code leak
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.

461 lines
9.0 KiB

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