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.

790 lines
16 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1994 - 1995.
  5. //
  6. // File: avl.cxx
  7. //
  8. // Contents:
  9. //
  10. // Classes:
  11. //
  12. // Functions:
  13. //
  14. // History: 6/25/1995 RaviR Created
  15. //
  16. //----------------------------------------------------------------------------
  17. #include "headers.hxx"
  18. #pragma hdrstop
  19. //#include "memory.hxx"
  20. #include "dbg.h"
  21. #include "macros.h"
  22. #include "avl.hxx"
  23. //+---------------------------------------------------------------------------
  24. //
  25. // Member: CAVLTree::Insert
  26. //
  27. // Synopsis: Insert the given atom in the tree.
  28. //
  29. // Arguments: [pa] -- IN The atom to insert.
  30. //
  31. // Returns: HRESULT.
  32. //
  33. // History: 8/29/1995 RaviR Created
  34. //
  35. //----------------------------------------------------------------------------
  36. HRESULT
  37. CAVLTree::Insert(
  38. PAVLNODEATOM pa)
  39. {
  40. _hrInsert = S_OK;
  41. _Insert(&_pFirstNode, pa);
  42. if (_pFirstNode != NULL)
  43. {
  44. _pFirstNode->SetParent(NULL);
  45. }
  46. return _hrInsert;
  47. }
  48. //+---------------------------------------------------------------------------
  49. //
  50. // Member: CAVLTree::_Insert
  51. //
  52. // Synopsis: A recursive function to insert the given atom.
  53. //
  54. // Arguments: [ppNode] -- The root of the current tree.
  55. // [pa] -- The atom to insert.
  56. //
  57. // Returns: TRUE if height changed, FALSE otherwise.
  58. //
  59. // History: 8/29/1995 RaviR Created
  60. //
  61. //----------------------------------------------------------------------------
  62. BOOL
  63. CAVLTree::_Insert(
  64. CTreeNode ** ppNode,
  65. PAVLNODEATOM pa)
  66. {
  67. CTreeNode *t = *ppNode;
  68. CTreeNode *t1 = NULL;
  69. CTreeNode *t2 = NULL;
  70. if (t == NULL)
  71. {
  72. CTreeNode * ptn = new CTreeNode(pa);
  73. if (ptn == NULL)
  74. {
  75. _hrInsert = E_OUTOFMEMORY;
  76. CHECK_HRESULT(_hrInsert);
  77. return FALSE;
  78. }
  79. *ppNode = ptn;
  80. return TRUE;
  81. }
  82. BOOL fHeightChanged = FALSE;
  83. int iComp = pa->Compare(t->Atom());
  84. if (iComp < 0)
  85. {
  86. fHeightChanged = _Insert(&(t->_l), pa);
  87. t->_l->SetParent(t);
  88. if (fHeightChanged == TRUE)
  89. {
  90. switch (t->Balance())
  91. {
  92. case 1:
  93. t->SetBalance(0);
  94. fHeightChanged = FALSE;
  95. break;
  96. case 0:
  97. t->SetBalance(-1);
  98. // fHeightChanged = TRUE; // already TRUE
  99. break;
  100. case -1:
  101. // Reblance
  102. t1 = t->Left();
  103. if (t1->Balance() == -1)
  104. {
  105. t->SetLeft(t1->Right());
  106. t->SetBalance(0);
  107. t1->SetRight(t);
  108. t1->SetBalance(0);
  109. t = t1;
  110. fHeightChanged = FALSE;
  111. }
  112. else
  113. {
  114. Win4Assert(t1->Balance() == 1);
  115. t2 = t1->Right();
  116. t->SetLeft(t2->Right());
  117. t1->SetRight(t2->Left());
  118. t2->SetLeft(t1);
  119. t2->SetRight(t);
  120. if (t2->Balance() == -1)
  121. {
  122. t->SetBalance(1);
  123. t1->SetBalance(0);
  124. }
  125. else if (t2->Balance() == 1)
  126. {
  127. t->SetBalance(0);
  128. t1->SetBalance(-1);
  129. }
  130. else
  131. {
  132. Win4Assert(t2->Balance() == 0);
  133. Win4Assert(t->Left() == NULL);
  134. Win4Assert(t->Right() == NULL);
  135. Win4Assert(t1->Right() == NULL);
  136. Win4Assert(t1->Left() == NULL);
  137. t->SetBalance(0);
  138. t1->SetBalance(0);
  139. }
  140. t = t2;
  141. t->SetBalance(0);
  142. fHeightChanged = FALSE;
  143. }
  144. break;
  145. default:
  146. Win4Assert(0 && "Unknown balance!");
  147. break;
  148. }
  149. }
  150. }
  151. else if (iComp > 0)
  152. {
  153. fHeightChanged = _Insert(&(t->_r), pa);
  154. t->_r->SetParent(t);
  155. if (fHeightChanged == TRUE)
  156. {
  157. switch (t->Balance())
  158. {
  159. case -1:
  160. t->SetBalance(0);
  161. fHeightChanged = FALSE;
  162. break;
  163. case 0:
  164. t->SetBalance(1);
  165. // fHeightChanged = TRUE; // already TRUE
  166. break;
  167. case 1:
  168. // Rebalance
  169. t1 = t->Right();
  170. if (t1->Balance() == 1)
  171. {
  172. t->SetRight(t1->Left());
  173. t->SetBalance(0);
  174. t1->SetLeft(t);
  175. t1->SetBalance(0);
  176. t = t1;
  177. fHeightChanged = FALSE;
  178. }
  179. else
  180. {
  181. Win4Assert(t1->Balance() == -1);
  182. t2 = t1->Left();
  183. t->SetRight(t2->Left());
  184. t1->SetLeft(t2->Right());
  185. t2->SetLeft(t);
  186. t2->SetRight(t1);
  187. if (t2->Balance() == -1)
  188. {
  189. t->SetBalance(0);
  190. t1->SetBalance(1);
  191. }
  192. else if (t2->Balance() == 1)
  193. {
  194. t->SetBalance(-1);
  195. t1->SetBalance(0);
  196. }
  197. else
  198. {
  199. Win4Assert(t2->Balance() == 0);
  200. Win4Assert(t->Left() == NULL);
  201. Win4Assert(t->Right() == NULL);
  202. Win4Assert(t1->Right() == NULL);
  203. Win4Assert(t1->Left() == NULL);
  204. t->SetBalance(0);
  205. t1->SetBalance(0);
  206. }
  207. t2->SetBalance(0);
  208. t = t2;
  209. fHeightChanged = FALSE;
  210. }
  211. break;
  212. default:
  213. Win4Assert(0 && "Unknown balance!");
  214. break;
  215. }
  216. }
  217. }
  218. else
  219. {
  220. _hrInsert = S_FALSE;
  221. }
  222. *ppNode = t;
  223. return fHeightChanged;
  224. }
  225. void
  226. CAVLTree::Delete(
  227. PAVLNODEATOM pa)
  228. {
  229. _Delete(&_pFirstNode, pa);
  230. if (_pFirstNode != NULL)
  231. {
  232. _pFirstNode->SetParent(NULL);
  233. }
  234. }
  235. BOOL
  236. CAVLTree::_Delete(
  237. CTreeNode ** ppNode,
  238. PAVLNODEATOM pa)
  239. {
  240. CTreeNode *t = *ppNode;
  241. if (t == NULL)
  242. {
  243. return FALSE;
  244. }
  245. CTreeNode *lt = t->Left();
  246. CTreeNode *rt = t->Right();
  247. CTreeNode *ct;
  248. CTreeNode *tToDel;
  249. PAVLNODEATOM paTemp = NULL;
  250. BOOL fHeightChanged = FALSE; // value to return
  251. BOOL fTemp;
  252. int iComp = pa->Compare(t->Atom());
  253. if (iComp == 0)
  254. {
  255. if (lt == NULL)
  256. {
  257. tToDel = t;
  258. t = rt;
  259. tToDel->SetLeft(NULL);
  260. tToDel->SetRight(NULL);
  261. delete tToDel;
  262. fHeightChanged = TRUE;
  263. }
  264. else if (rt == NULL)
  265. {
  266. tToDel = t;
  267. t = lt;
  268. tToDel->SetLeft(NULL);
  269. tToDel->SetRight(NULL);
  270. delete tToDel;
  271. fHeightChanged = TRUE;
  272. }
  273. else
  274. {
  275. switch (t->Balance())
  276. {
  277. case -1:
  278. paTemp = lt->GetMax();
  279. fTemp = _Delete(&t->_l, paTemp);
  280. if (t->_l)
  281. {
  282. t->_l->SetParent(t);
  283. }
  284. if (fTemp == TRUE)
  285. {
  286. t->SetBalance(0);
  287. fHeightChanged = TRUE;
  288. }
  289. break;
  290. case 0:
  291. paTemp = lt->GetMax();
  292. fTemp = _Delete(&t->_l, paTemp);
  293. if (t->_l)
  294. {
  295. t->_l->SetParent(t);
  296. }
  297. if (fTemp == TRUE)
  298. {
  299. t->SetBalance(1);
  300. }
  301. break;
  302. case 1:
  303. paTemp = rt->GetMin();
  304. fTemp = _Delete(&t->_r, paTemp);
  305. if (t->_r)
  306. {
  307. t->_r->SetParent(t);
  308. }
  309. if (fTemp == TRUE)
  310. {
  311. t->SetBalance(0);
  312. fHeightChanged = TRUE;
  313. }
  314. break;
  315. }
  316. t->SetAtom(paTemp);
  317. }
  318. }
  319. else if (iComp > 0)
  320. {
  321. fTemp = _Delete(&t->_r, pa);
  322. if (t->_r)
  323. {
  324. t->_r->SetParent(t);
  325. }
  326. if (fTemp == TRUE)
  327. {
  328. switch (t->Balance())
  329. {
  330. case 1:
  331. t->SetBalance(0);
  332. fHeightChanged = TRUE;
  333. break;
  334. case 0:
  335. t->SetBalance(-1);
  336. break;
  337. case -1:
  338. switch (lt->Balance())
  339. {
  340. case -1:
  341. t->SetLeft(lt->Right());
  342. t->SetParent(lt);
  343. lt->SetRight(t);
  344. t->SetBalance(0);
  345. lt->SetBalance(0);
  346. t = lt;
  347. fHeightChanged = TRUE;
  348. break;
  349. case 0:
  350. t->SetLeft(lt->Right());
  351. t->SetParent(lt);
  352. lt->SetRight(t);
  353. t->SetBalance(-1);
  354. lt->SetBalance(1);
  355. t = lt;
  356. break;
  357. case 1:
  358. ct = lt->Right();
  359. Win4Assert(ct != NULL); // becos (lt->Balance() == 1)
  360. t->SetLeft(ct->Right());
  361. t->SetParent(ct);
  362. lt->SetRight(ct->Left());
  363. lt->SetParent(ct);
  364. ct->SetLeft(lt);
  365. ct->SetRight(t);
  366. switch (ct->Balance())
  367. {
  368. case -1:
  369. lt->SetBalance(0);
  370. t->SetBalance(1);
  371. break;
  372. case 0:
  373. lt->SetBalance(0);
  374. t->SetBalance(0);
  375. break;
  376. case 1:
  377. lt->SetBalance(-1);
  378. t->SetBalance(0);
  379. break;
  380. }
  381. ct->SetBalance(0);
  382. t = ct;
  383. fHeightChanged = TRUE;
  384. break;
  385. }
  386. break;
  387. }
  388. }
  389. }
  390. else // if (iComp < 0)
  391. {
  392. fTemp = _Delete(&t->_l, pa);
  393. if (t->_l)
  394. {
  395. t->_l->SetParent(t);
  396. }
  397. if (fTemp == TRUE)
  398. {
  399. switch (t->Balance())
  400. {
  401. case -1:
  402. t->SetBalance(0);
  403. fHeightChanged = TRUE;
  404. break;
  405. case 0:
  406. t->SetBalance(1);
  407. break;
  408. case 1:
  409. switch (rt->Balance())
  410. {
  411. case 1:
  412. t->SetRight(rt->Left());
  413. t->SetParent(rt);
  414. rt->SetLeft(t);
  415. t->SetBalance(0);
  416. rt->SetBalance(0);
  417. t = rt;
  418. fHeightChanged = TRUE;
  419. break;
  420. case 0:
  421. t->SetRight(rt->Left());
  422. t->SetParent(rt);
  423. rt->SetLeft(t);
  424. t->SetBalance(1);
  425. rt->SetBalance(-1);
  426. t = rt;
  427. break;
  428. case -1:
  429. ct = rt->Left();
  430. Win4Assert(ct != NULL); // becos (rt->Balance() == -1)
  431. t->SetRight(ct->Left());
  432. t->SetParent(ct);
  433. rt->SetLeft(ct->Right());
  434. rt->SetParent(ct);
  435. ct->SetLeft(t);
  436. ct->SetRight(rt);
  437. switch (ct->Balance())
  438. {
  439. case -1:
  440. t->SetBalance(0);
  441. rt->SetBalance(1);
  442. break;
  443. case 0:
  444. t->SetBalance(0);
  445. rt->SetBalance(0);
  446. break;
  447. case 1:
  448. t->SetBalance(-1);
  449. rt->SetBalance(0);
  450. break;
  451. }
  452. ct->SetBalance(0);
  453. t = ct;
  454. fHeightChanged = TRUE;
  455. break;
  456. }
  457. break;
  458. }
  459. }
  460. }
  461. *ppNode = t;
  462. return fHeightChanged;
  463. }
  464. //+---------------------------------------------------------------------------
  465. //
  466. // Member: CAVLTree::GetAtom
  467. //
  468. // Arguments: [pa] -- Atom
  469. //
  470. // Returns: The TreeNode containig the atom.
  471. //
  472. // History: 8/29/1995 RaviR Created
  473. //
  474. //----------------------------------------------------------------------------
  475. PAVLNODEATOM
  476. CAVLTree::GetAtom(
  477. PAVLNODEATOM pa)
  478. {
  479. CTreeNode *t = _pFirstNode;
  480. while (t != NULL)
  481. {
  482. int iComp = pa->Compare(t->Atom());
  483. if (iComp == 0)
  484. {
  485. return t->Atom();
  486. }
  487. else if (iComp < 0)
  488. {
  489. t = t->Left();
  490. continue;
  491. }
  492. else
  493. {
  494. t = t->Right();
  495. continue;
  496. }
  497. }
  498. return NULL;
  499. }
  500. //+---------------------------------------------------------------------------
  501. //
  502. // Member: CAVLTree::GetFirst
  503. //
  504. // Synopsis: Returns the first atom in the tree.
  505. //
  506. // History: 8/29/1995 RaviR Created
  507. //
  508. //----------------------------------------------------------------------------
  509. PAVLNODEATOM
  510. CAVLTree::GetFirst(void)
  511. {
  512. if (_pFirstNode == NULL)
  513. {
  514. return NULL;
  515. }
  516. _pFirstNode->ResetTraversedFlag();
  517. CTreeNode *t = _pFirstNode;
  518. while (t->Left() != NULL)
  519. {
  520. t = t->Left();
  521. }
  522. _pCurrentNode = t;
  523. t->SetTraversed();
  524. return t->Atom();
  525. }
  526. //+---------------------------------------------------------------------------
  527. //
  528. // Member: CAVLTree::GetNext
  529. //
  530. // Synopsis: Traverses the tree inorder.
  531. //
  532. // History: 8/29/1995 RaviR Created
  533. //
  534. //----------------------------------------------------------------------------
  535. PAVLNODEATOM
  536. CAVLTree::GetNext(void)
  537. {
  538. CTreeNode *t = _pCurrentNode;
  539. do
  540. {
  541. if (t->Right() != NULL)
  542. {
  543. t = t->Right();
  544. while (t->Left() != NULL)
  545. {
  546. t = t->Left();
  547. }
  548. }
  549. else
  550. {
  551. t = t->Parent();
  552. while (t != NULL && t->IsTraversed())
  553. {
  554. t = t->Parent();
  555. }
  556. }
  557. } while (0);
  558. _pCurrentNode = t;
  559. if (t != NULL)
  560. {
  561. t->SetTraversed();
  562. return t->Atom();
  563. }
  564. return NULL;
  565. }
  566. //////////////////////////////////////////////////////////////////////////
  567. //////////////////////////////////////////////////////////////////////////
  568. //////////////////////////////////////////////////////////////////////////
  569. //////////////////////////////////////////////////////////////////////////
  570. //////////////////////////////////////////////////////////////////////////
  571. #if (DBG == 1)
  572. void
  573. CTreeNode::Dump(void)
  574. {
  575. if (_l)
  576. {
  577. _l->Dump();
  578. }
  579. //printf("<val, bal> = <");
  580. _pa->Dump();
  581. //printf(", %d>\n", (UINT)_b);
  582. if (_r)
  583. {
  584. _r->Dump();
  585. }
  586. }
  587. void
  588. CAVLTree::Dump(void)
  589. {
  590. DEBUG_OUT((DEB_USER1, "Start Dump:\n"));
  591. if (_pFirstNode != NULL)
  592. {
  593. _pFirstNode->Dump();
  594. }
  595. DEBUG_OUT((DEB_USER1, "End Dump.\n"));
  596. }
  597. #endif