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.

1206 lines
32 KiB

  1. #ifndef BTREE_H
  2. #define BTREE_H
  3. //------------------
  4. // BTreePage
  5. // A BTree page
  6. //------------------
  7. struct PageHeader
  8. {
  9. long Order; // maximum # of page links in page
  10. long MaxKeys; // maximum # of keys in page
  11. long MinKeys; // minimum # of keys in page
  12. long NoOfKeys; // actual # of keys in page
  13. long KeySize; // maximum # of bytes in a key
  14. };
  15. template <class K, class D>
  16. struct BTreeNode
  17. {
  18. K m_Key;
  19. const D * m_pData;
  20. ULONG m_ulHash;
  21. BTreeNode<K, D> * m_pNext;
  22. BTreeNode();
  23. BTreeNode(const K& Key, const D* data);
  24. ~BTreeNode();
  25. void operator = (const BTreeNode& node);
  26. };
  27. template <class K, class D>
  28. BTreeNode<K,D>::BTreeNode() :
  29. m_pData(NULL),
  30. m_pNext(NULL),
  31. m_ulHash(0)
  32. {
  33. }
  34. template <class K, class D>
  35. BTreeNode<K,D>::BTreeNode(const K& Key, const D* pdata) :
  36. m_pData(pdata),
  37. m_pNext(NULL)
  38. {
  39. m_Key = Key;
  40. m_ulHash = Hash(Key);
  41. }
  42. template <class K, class D>
  43. BTreeNode<K,D>::~BTreeNode()
  44. {
  45. m_pNext = NULL;
  46. }
  47. template <class K, class D>
  48. void BTreeNode<K,D>::operator=(const BTreeNode& node)
  49. {
  50. m_Key = node.m_Key;
  51. m_pData = node.m_pData;
  52. m_ulHash = node.m_ulHash;
  53. m_pNext = node.m_pNext;
  54. }
  55. template <class K, class D>
  56. struct BTreePage
  57. {
  58. PageHeader m_hdr; // header information
  59. BTreeNode<K,D> * m_pNodes;
  60. BTreePage<K,D>** m_ppLinks;
  61. BTreePage<K,D>* m_pParent;
  62. BTreePage(long ord);
  63. BTreePage(const BTreePage & p);
  64. ~BTreePage();
  65. void operator = (const BTreePage & page);
  66. void DeleteAllNodes();
  67. void CopyNodes(BTreeNode<K,D>* pDestNodes, BTreeNode<K,D>* pSrcNodes, long cnt);
  68. };
  69. template <class K, class D>
  70. BTreePage<K,D>::BTreePage(long ord)
  71. {
  72. m_hdr.Order = ord;
  73. m_hdr.MaxKeys = ord - 1;
  74. m_hdr.MinKeys = ord / 2;
  75. m_hdr.NoOfKeys = 0;
  76. m_hdr.KeySize = sizeof(K);
  77. if (m_hdr.Order == 0)
  78. {
  79. m_pNodes = NULL;
  80. m_ppLinks = NULL;
  81. return;
  82. }
  83. // allocate key array
  84. m_pNodes = new BTreeNode<K,D> [m_hdr.MaxKeys];
  85. ASSERT(m_pNodes, "Couldn't allocate nodes array!");
  86. memset(m_pNodes,0,m_hdr.MaxKeys * sizeof(BTreeNode<K,D>));
  87. m_ppLinks = new BTreePage<K,D>*[m_hdr.MaxKeys + 1];
  88. ASSERT(m_ppLinks, "Couldn't allocate limks array!");
  89. memset(m_ppLinks,0,((m_hdr.MaxKeys + 1)* sizeof(BTreePage<K,D>*)));
  90. m_pParent = NULL;
  91. }
  92. template <class K, class D>
  93. BTreePage<K, D>::BTreePage(const BTreePage<K,D> & pg)
  94. {
  95. m_hdr = pg.m_hdr;
  96. // allocate key array
  97. m_pNodes = new BTreeNode<K,D>[m_hdr.MaxKeys];
  98. ASSERT(m_pNodes, "Couldn't allocate nodes array!");
  99. CopyNodes(m_pNodes, pg.m_pNodes, m_hdr.Order);
  100. for (int i = 0; i < m_hdr.MaxKeys + 1; i++)
  101. m_ppLinks[i] = pg.m_ppLinks[i];
  102. m_pParent = pg.m_pParent;
  103. }
  104. template <class K, class D>
  105. BTreePage<K, D>::~BTreePage()
  106. {
  107. // delete old buffers
  108. DeleteAllNodes();
  109. delete [] m_ppLinks;
  110. }
  111. template <class K, class D>
  112. void BTreePage<K,D>::operator = (const BTreePage<K,D> & pg)
  113. {
  114. // allocate key array
  115. if (m_pNodes!= NULL)
  116. DeleteAllNodes();
  117. m_pNodes = new BTreeNode<K,D> [pg.m_hdr.MaxKeys];
  118. ASSERT(m_pNodes, "Couldn't allocate nodes array!");
  119. if (m_ppLinks)
  120. delete [] m_ppLinks;
  121. m_ppLinks = new BTreePage<K,D>*[pg.m_hdr.MaxKeys + 1];
  122. ASSERT(m_ppLinks, "Couldn't allocate links array!");
  123. m_hdr = pg.m_hdr;
  124. CopyNodes(m_pNodes, pg.m_pNodes, m_hdr.Order);
  125. for (int i = 0; i < m_hdr.MaxKeys + 1; i++)
  126. m_ppLinks[i] = pg.m_ppLinks[i];
  127. m_pParent = pg.m_pParent;
  128. }
  129. template <class K, class D>
  130. void BTreePage<K,D>::DeleteAllNodes()
  131. {
  132. for (int i = 0; i < m_hdr.NoOfKeys; i++)
  133. {
  134. BTreeNode<K,D>* pIndex = m_pNodes[i].m_pNext;
  135. while(pIndex)
  136. {
  137. BTreeNode<K,D>* pDel = pIndex;
  138. pIndex = pIndex->m_pNext;
  139. delete pDel;
  140. }
  141. }
  142. delete [] m_pNodes;
  143. m_pNodes = NULL;
  144. }
  145. template <class K, class D>
  146. void BTreePage<K,D>::CopyNodes(BTreeNode<K,D>* pDestNodes, BTreeNode<K,D>* pSrcNodes, long cnt)
  147. {
  148. for (int i = 0; i < cnt; i++)
  149. {
  150. pDestNodes[i] = pSrcNodes[i];
  151. BTreeNode<K,D>* pSrcIndex = pSrcNodes[i].m_pNext;
  152. BTreeNode<K,D>* pDestIndex = pDestNodes;
  153. while(pSrcIndex)
  154. {
  155. pDestIndex->m_pNext = new BTreeNode<K,D>(*pSrcIndex);
  156. pSrcIndex = pSrcIndex->m_pNext;
  157. pDestIndex = pDestIndex->m_pNext;
  158. }
  159. }
  160. }
  161. //-----------------------------------------------
  162. // BTree
  163. // A DataFile that uses a BTree for indexing
  164. // NOTE: No copy semantics will exist for a btree
  165. //-----------------------------------------------
  166. template <class K, class D>
  167. class BTree
  168. {
  169. public:
  170. BTree(long ord); // new
  171. BTree(long ord, int (*compare)(const K& key1, const K& key2));
  172. ~BTree();
  173. void Insert(const K & key, const D* data);
  174. const D* Get(const K & key);
  175. void Delete(const K & key);
  176. void InOrder(void (* func)(const K & key, const D* pdata, int depth, int index));
  177. void Clear();
  178. private:
  179. // data members
  180. BTreePage<K,D>* m_pRoot; // root page (always in memory)
  181. void (* TravFunc)(const K & key, const D* pdata, int depth, int index);
  182. int (*CompFunc) (const K& key1, const K& key2);
  183. // search for a node
  184. BOOL Search(BTreePage<K,D>* ppg, const ULONG& thash, const K& searchkey, BTreePage<K,D>** ppkeypage, long & pos);
  185. // insert node into leaf
  186. void InsertKey(const K & inskey, const D* pdata);
  187. // promote a key into a parent node
  188. void PromoteInternal(BTreePage<K, D>* ppg, BTreeNode<K,D> & node, BTreePage<K, D>* pgrtrpage);
  189. // promote a key by creating a new root
  190. void PromoteRoot(BTreeNode<K,D> & node, BTreePage<K, D>* plesspage, BTreePage<K, D>* pgrtrpage);
  191. // adjust tree if leaf has shrunk in size
  192. void AdjustTree(BTreePage<K, D>* pleafpg);
  193. // redistribute keys among siblings and parent
  194. void Redistribute(long keypos, BTreePage<K, D>* plesspage, BTreePage<K, D>* pparpage, BTreePage<K, D>* pgrtrpage);
  195. // concatenate sibling pages
  196. void Concatenate(long keypos, BTreePage<K, D>* plesspage, BTreePage<K, D>* pparpage, BTreePage<K, D>* pgrtrpage);
  197. // recursive traversal function used by InOrder
  198. void RecurseTraverse(const BTreePage<K, D>* ppg, int depth);
  199. // recursively delete a page and all it's sub pages;
  200. void DeletePage(BTreePage<K,D>* ppg);
  201. };
  202. template <class K, class D>
  203. BTree<K,D>::BTree(long ord)
  204. {
  205. CompFunc = NULL;
  206. m_pRoot = new BTreePage<K,D>(ord);
  207. }
  208. template <class K, class D>
  209. BTree<K,D>::BTree(long ord, int (*comp)(const K& key1, const K& key2))
  210. {
  211. CompFunc = comp;
  212. m_pRoot = new BTreePage<K,D>(ord);
  213. }
  214. template <class K, class D>
  215. BTree<K,D>::~BTree()
  216. {
  217. DeletePage(m_pRoot);
  218. }
  219. template <class K, class D>
  220. void BTree<K,D>::Insert(const K & key, const D* pdb)
  221. {
  222. // store the key in a page
  223. InsertKey(key,pdb);
  224. }
  225. template <class K, class D>
  226. const D* BTree<K,D>::Get(const K & key)
  227. {
  228. BTreePage<K,D>* pgetpage = NULL;
  229. long getpos;
  230. if (Search(m_pRoot, Hash(key), key, &pgetpage, getpos))
  231. {
  232. BOOL found = FALSE;
  233. BTreeNode<K,D>* pnode = &pgetpage->m_pNodes[getpos];
  234. if (CompFunc)
  235. {
  236. while(pnode && !found)
  237. {
  238. if (CompFunc(key, pnode->m_Key) == 0)
  239. {
  240. found = TRUE;
  241. return pnode->m_pData;
  242. }
  243. pnode = pnode->m_pNext;
  244. }
  245. }
  246. else
  247. {
  248. while(pnode && !found)
  249. {
  250. if (key == pnode->m_Key)
  251. {
  252. found = TRUE;
  253. return pnode->m_pData;
  254. }
  255. pnode = pnode->m_pNext;
  256. }
  257. }
  258. }
  259. else
  260. {
  261. return NULL;
  262. }
  263. return NULL;
  264. }
  265. template <class K, class D>
  266. void BTree<K,D>::Delete(const K & delkey)
  267. {
  268. BTreePage<K,D>* pdelpage = NULL;
  269. long delpos;
  270. if (!Search(m_pRoot, Hash(delkey), delkey, &pdelpage, delpos))
  271. {
  272. return;
  273. }
  274. if (!pdelpage->m_ppLinks[0]) // is this a leaf page?
  275. {
  276. //Delete all linked nodes.
  277. BOOL bFound = FALSE;
  278. BOOL bDelNode = FALSE;
  279. BTreeNode<K,D>* pDelNode = (pdelpage->m_pNodes + delpos);
  280. BTreeNode<K,D>* pIndex = pDelNode;
  281. while(pDelNode && !bFound)
  282. {
  283. if ((CompFunc && (CompFunc(delkey, pDelNode->m_Key) == 0)) ||
  284. (!CompFunc && (delkey == pDelNode->m_Key)))
  285. {
  286. //If the node we need to delete is the head node in the list AND it's the only node
  287. //then we need to skip to the routine below to delete it from the tree.
  288. // + delpos
  289. if (pDelNode == (pdelpage->m_pNodes + delpos))
  290. {
  291. if (!pDelNode->m_pNext)
  292. {
  293. bDelNode = TRUE;
  294. }
  295. else
  296. {
  297. pDelNode = pDelNode->m_pNext;
  298. *pIndex = *pDelNode;
  299. delete pDelNode;
  300. pDelNode = NULL;
  301. }
  302. }
  303. else
  304. {
  305. pIndex->m_pNext = pDelNode->m_pNext;
  306. delete pDelNode;
  307. pDelNode = NULL;
  308. }
  309. bFound = TRUE;
  310. }
  311. else
  312. {
  313. pIndex = pDelNode;
  314. pDelNode = pDelNode->m_pNext;
  315. }
  316. }
  317. if (bDelNode)
  318. {
  319. --pdelpage->m_hdr.NoOfKeys;
  320. // remove key from leaf
  321. for (long n = delpos; n < pdelpage->m_hdr.NoOfKeys; ++n)
  322. {
  323. pdelpage->m_pNodes[n] = pdelpage->m_pNodes[n + 1];
  324. }
  325. memset((void*)&pdelpage->m_pNodes[pdelpage->m_hdr.NoOfKeys], 0, sizeof(BTreeNode<K,D>));
  326. // adjust tree
  327. if (pdelpage->m_hdr.NoOfKeys < pdelpage->m_hdr.MinKeys)
  328. AdjustTree(pdelpage);
  329. }
  330. }
  331. else // delpage is internal
  332. {
  333. // replace deleted key with immediate successor
  334. BTreePage<K,D>* psucpage = NULL;
  335. // find successor
  336. psucpage = pdelpage->m_ppLinks[delpos + 1];
  337. while (psucpage->m_ppLinks[0])
  338. psucpage = psucpage->m_ppLinks[0];
  339. //Delete all linked nodes.
  340. BOOL bFound = FALSE;
  341. BOOL bDelNode = FALSE;
  342. BTreeNode<K,D>* pDelNode = (pdelpage->m_pNodes + delpos);
  343. BTreeNode<K,D>* pIndex = pDelNode;
  344. while(pDelNode && !bFound)
  345. {
  346. if ((CompFunc && (CompFunc(delkey, pDelNode->m_Key) == 0)) ||
  347. (!CompFunc && (delkey == pDelNode->m_Key)))
  348. {
  349. //If the node we need to delete is the head node in the list AND it's the only node
  350. //then we need to skip to the routine below to delete it from the tree.
  351. if (pDelNode == (pdelpage->m_pNodes + delpos))
  352. {
  353. if (!pDelNode->m_pNext)
  354. {
  355. bDelNode = TRUE;
  356. }
  357. else
  358. {
  359. pDelNode = pDelNode->m_pNext;
  360. pdelpage->m_pNodes[delpos].operator=(*pDelNode);
  361. delete pDelNode;
  362. }
  363. }
  364. else
  365. {
  366. pIndex->m_pNext = pDelNode->m_pNext;
  367. delete pDelNode;
  368. pDelNode = NULL;
  369. }
  370. bFound = TRUE;
  371. }
  372. else
  373. {
  374. pIndex = pDelNode;
  375. pDelNode = pDelNode->m_pNext;
  376. }
  377. }
  378. if (bDelNode)
  379. {
  380. // first key is the "swappee"
  381. pdelpage->m_pNodes[delpos] = psucpage->m_pNodes[0];
  382. // deleted swapped key from sucpage
  383. --psucpage->m_hdr.NoOfKeys;
  384. for (long n = 0; n < psucpage->m_hdr.NoOfKeys; ++n)
  385. {
  386. psucpage->m_pNodes[n] = psucpage->m_pNodes[n + 1];
  387. psucpage->m_ppLinks[n + 1] = psucpage->m_ppLinks[n + 2];
  388. }
  389. memset((void*)&psucpage->m_pNodes[psucpage->m_hdr.NoOfKeys], 0, sizeof(BTreeNode<K,D>));
  390. psucpage->m_ppLinks[psucpage->m_hdr.NoOfKeys + 1] = NULL;
  391. // adjust tree for leaf node
  392. if (psucpage->m_hdr.NoOfKeys < psucpage->m_hdr.MinKeys)
  393. AdjustTree(psucpage);
  394. }
  395. }
  396. }
  397. template <class K, class D>
  398. void BTree<K,D>::InOrder(void (* func)(const K & key, const D* pdata, int depth, int index))
  399. {
  400. // save the address of the function to call
  401. TravFunc = func;
  402. // recurse the tree
  403. RecurseTraverse(m_pRoot, 0);
  404. }
  405. template <class K, class D>
  406. void BTree<K,D>::Clear()
  407. {
  408. DeletePage(m_pRoot);
  409. }
  410. template <class K, class D>
  411. BOOL BTree<K,D>::Search(BTreePage<K,D>* ppg, const ULONG& thash, const K& searchkey, BTreePage<K,D>** ppkeypage, long & pos)
  412. {
  413. BOOL result;
  414. pos = 0;
  415. for (;;)
  416. {
  417. if (pos == ppg->m_hdr.NoOfKeys)
  418. goto getpage;
  419. if (ppg->m_pNodes[pos].m_ulHash == thash)
  420. {
  421. *ppkeypage = (BTreePage<K,D>*)ppg;
  422. result = TRUE;
  423. break;
  424. }
  425. else
  426. {
  427. if (ppg->m_pNodes[pos].m_ulHash < thash)
  428. ++pos;
  429. else
  430. {
  431. // I know this is a label -- so shoot me!
  432. getpage:
  433. // if we're in a leaf page, key wasn't found
  434. if (!ppg->m_ppLinks[pos])
  435. {
  436. *ppkeypage = (BTreePage<K,D>*)ppg;
  437. result = FALSE;
  438. }
  439. else
  440. {
  441. result = Search(ppg->m_ppLinks[pos],thash, searchkey,ppkeypage,pos);
  442. }
  443. break;
  444. }
  445. }
  446. }
  447. return result;
  448. }
  449. template <class K, class D>
  450. void BTree<K,D>::InsertKey(const K & inskey, const D* pdata)
  451. {
  452. BTreePage<K,D>* pinspage = NULL;
  453. long inspos;
  454. BTreeNode<K,D> newnode(inskey, pdata);
  455. BOOL bFound = Search(m_pRoot,Hash(inskey), inskey,&pinspage,inspos);
  456. if (bFound)
  457. {
  458. BOOL found = FALSE;
  459. BTreeNode<K,D>* pnode = &(pinspage->m_pNodes[inspos]);
  460. BTreeNode<K,D>* pparent = NULL;
  461. if (CompFunc != NULL)
  462. {
  463. while(pnode && !found)
  464. {
  465. if (CompFunc(inskey, pnode->m_Key) == 0)
  466. {
  467. found = TRUE;
  468. }
  469. pparent = pnode;
  470. pnode = pnode->m_pNext;
  471. }
  472. }
  473. else
  474. {
  475. while(pnode && !found)
  476. {
  477. if (inskey == pnode->m_Key)
  478. {
  479. found = TRUE;
  480. }
  481. pparent = pnode;
  482. pnode = pnode->m_pNext;
  483. }
  484. }
  485. if (found)
  486. {
  487. return;
  488. }
  489. pparent->m_pNext = new BTreeNode<K,D>(inskey, pdata);
  490. }
  491. else
  492. {
  493. if (pinspage->m_hdr.NoOfKeys == pinspage->m_hdr.MaxKeys)
  494. {
  495. // temporary arrays
  496. BTreeNode<K,D>* ptempkeys = new BTreeNode<K,D>[pinspage->m_hdr.MaxKeys + 1];
  497. // copy entries from inspage to temporaries
  498. long nt = 0; // index into temporaries
  499. long ni = 0; // index into inspage
  500. ptempkeys[inspos] = newnode;
  501. while (ni < pinspage->m_hdr.MaxKeys)
  502. {
  503. if (ni == inspos)
  504. ++nt;
  505. ptempkeys[nt] = pinspage->m_pNodes[ni];
  506. ++ni;
  507. ++nt;
  508. }
  509. // generate a new leaf node
  510. BTreePage<K,D>* psibpage = new BTreePage<K,D>(pinspage->m_hdr.Order);
  511. psibpage->m_pParent = pinspage->m_pParent;
  512. // clear # of keys in pages
  513. pinspage->m_hdr.NoOfKeys = 0;
  514. psibpage->m_hdr.NoOfKeys = 0;
  515. // copy appropriate keys from temp to pages
  516. for (ni = 0; ni < pinspage->m_hdr.MinKeys; ++ni)
  517. {
  518. pinspage->m_pNodes[ni] = ptempkeys[ni];
  519. ++pinspage->m_hdr.NoOfKeys;
  520. }
  521. for (ni = pinspage->m_hdr.MinKeys + 1; ni <= pinspage->m_hdr.MaxKeys; ++ni)
  522. {
  523. psibpage->m_pNodes[ni - 1 - pinspage->m_hdr.MinKeys] = ptempkeys[ni];
  524. ++(psibpage->m_hdr.NoOfKeys);
  525. }
  526. // Fill any remaining entries in inspage with null.
  527. // Note that sibpage is initialized to null values
  528. // by the constructor.
  529. for (ni = pinspage->m_hdr.MinKeys; ni < pinspage->m_hdr.MaxKeys; ++ni)
  530. {
  531. memset((void*)&pinspage->m_pNodes[ni],0,sizeof(BTreeNode<K,D>));
  532. }
  533. // promote key and pointer
  534. if (!pinspage->m_pParent)
  535. {
  536. // we need to create a new root
  537. PromoteRoot(ptempkeys[pinspage->m_hdr.MinKeys], pinspage, psibpage);
  538. }
  539. else
  540. {
  541. BTreePage<K,D>* pparpage;
  542. pparpage = pinspage->m_pParent;
  543. // promote into parent
  544. PromoteInternal(pparpage, ptempkeys[pinspage->m_hdr.MinKeys], psibpage);
  545. }
  546. delete [] ptempkeys;
  547. }
  548. else // simply insert new key and data ptr
  549. {
  550. for (long n = pinspage->m_hdr.NoOfKeys; n > inspos; --n)
  551. {
  552. pinspage->m_pNodes[n] = pinspage->m_pNodes[n - 1];
  553. }
  554. pinspage->m_pNodes[inspos] = newnode;
  555. ++pinspage->m_hdr.NoOfKeys;
  556. }
  557. }
  558. }
  559. template <class K, class D>
  560. void BTree<K,D>::PromoteInternal(BTreePage<K,D>* pinspage, BTreeNode<K,D> & node, BTreePage<K,D>* pgrtrpage)
  561. {
  562. if (pinspage->m_hdr.NoOfKeys == pinspage->m_hdr.MaxKeys)
  563. {
  564. // temporary arrays
  565. BTreeNode<K,D> * ptempkeys = new BTreeNode<K,D>[pinspage->m_hdr.MaxKeys + 1];
  566. BTreePage<K,D>** ptemplnks = new BTreePage<K,D>*[pinspage->m_hdr.Order + 1];
  567. // copy entries from inspage to temporaries
  568. long nt = 0; // index into temporaries
  569. long ni = 0; // index into inspage
  570. ptemplnks[0] = pinspage->m_ppLinks[0];
  571. long inspos = 0;
  572. // find insertion position
  573. while ((inspos < pinspage->m_hdr.MaxKeys)
  574. && (pinspage->m_pNodes[inspos].m_ulHash < node.m_ulHash))
  575. ++inspos;
  576. // store new info
  577. ptempkeys[inspos] = node;
  578. ptemplnks[inspos + 1] = pgrtrpage;
  579. // copy existing keys
  580. while (ni < pinspage->m_hdr.MaxKeys)
  581. {
  582. if (ni == inspos)
  583. ++nt;
  584. ptempkeys[nt] = pinspage->m_pNodes[ni];
  585. ptemplnks[nt + 1] = pinspage->m_ppLinks[ni + 1];
  586. ++ni;
  587. ++nt;
  588. }
  589. // generate a new leaf node
  590. BTreePage<K,D>* psibpage = new BTreePage<K,D>(pinspage->m_hdr.Order);
  591. psibpage->m_pParent = pinspage->m_pParent;
  592. // clear # of keys in pages
  593. pinspage->m_hdr.NoOfKeys = 0;
  594. psibpage->m_hdr.NoOfKeys = 0;
  595. pinspage->m_ppLinks[0] = ptemplnks[0];
  596. // copy appropriate keys from temp to pages
  597. for (ni = 0; ni < pinspage->m_hdr.MinKeys; ++ni)
  598. {
  599. pinspage->m_pNodes[ni] = ptempkeys[ni];
  600. pinspage->m_ppLinks[ni + 1] = ptemplnks[ni + 1];
  601. ++pinspage->m_hdr.NoOfKeys;
  602. }
  603. psibpage->m_ppLinks[0] = ptemplnks[pinspage->m_hdr.MinKeys + 1];
  604. for (ni = pinspage->m_hdr.MinKeys + 1; ni <= pinspage->m_hdr.MaxKeys; ++ni)
  605. {
  606. psibpage->m_pNodes[ni - 1 - pinspage->m_hdr.MinKeys] = ptempkeys[ni];
  607. psibpage->m_ppLinks[ni - pinspage->m_hdr.MinKeys] = ptemplnks[ni + 1];
  608. ++psibpage->m_hdr.NoOfKeys;
  609. }
  610. // Fill any remaining entries in inspage with null.
  611. // Note that sibpage is initialized to null values
  612. // by the constructor.
  613. for (ni = pinspage->m_hdr.MinKeys; ni < pinspage->m_hdr.MaxKeys; ++ni)
  614. {
  615. memset((void*)&pinspage->m_pNodes[ni],0, sizeof(BTreeNode<K,D>));
  616. pinspage->m_ppLinks[ni + 1] = NULL;
  617. }
  618. // update child parent links
  619. BTreePage<K,D>* pchild;
  620. for (ni = 0; ni <= psibpage->m_hdr.NoOfKeys; ++ni)
  621. {
  622. pchild = psibpage->m_ppLinks[ni];
  623. pchild->m_pParent= psibpage;
  624. }
  625. // promote key and pointer
  626. if (!pinspage->m_pParent)
  627. {
  628. // we need to create a new root
  629. PromoteRoot(ptempkeys[pinspage->m_hdr.MinKeys], pinspage, psibpage);
  630. }
  631. else
  632. {
  633. BTreePage<K, D>* pparpage;
  634. pparpage = pinspage->m_pParent;
  635. // promote into parent
  636. PromoteInternal(pparpage, ptempkeys[pinspage->m_hdr.MinKeys], psibpage);
  637. }
  638. delete [] ptempkeys;
  639. delete [] ptemplnks;
  640. }
  641. else // simply insert new key and data ptr
  642. {
  643. long inspos = 0;
  644. // find insertion position
  645. while ((inspos < pinspage->m_hdr.NoOfKeys)
  646. && (pinspage->m_pNodes[inspos].m_ulHash < node.m_ulHash))
  647. ++inspos;
  648. // shift any keys right
  649. for (long n = pinspage->m_hdr.NoOfKeys; n > inspos; --n)
  650. {
  651. pinspage->m_pNodes[n] = pinspage->m_pNodes[n - 1];
  652. pinspage->m_ppLinks[n + 1] = pinspage->m_ppLinks[n];
  653. }
  654. // store new info
  655. pinspage->m_pNodes[inspos] = node;
  656. pinspage->m_ppLinks[inspos + 1] = pgrtrpage;
  657. ++pinspage->m_hdr.NoOfKeys;
  658. }
  659. }
  660. template <class K, class D>
  661. void BTree<K,D>::PromoteRoot(BTreeNode<K,D> & node, BTreePage<K,D> * plesspage, BTreePage<K,D> * pgrtrpage)
  662. {
  663. // create new root page
  664. BTreePage<K,D>* pnewroot = new BTreePage<K,D>(m_pRoot->m_hdr.Order);
  665. // insert key into new root
  666. pnewroot->m_pNodes[0] = node;
  667. pnewroot->m_ppLinks[0] = plesspage;
  668. pnewroot->m_ppLinks[1] = pgrtrpage;
  669. pnewroot->m_hdr.NoOfKeys = 1;
  670. m_pRoot = pnewroot;
  671. plesspage->m_pParent = m_pRoot;
  672. pgrtrpage->m_pParent = m_pRoot;
  673. }
  674. template <class K, class D>
  675. void BTree<K,D>::AdjustTree(BTreePage<K,D>* ppg)
  676. {
  677. if (!ppg->m_pParent)
  678. return;
  679. BTreePage<K,D>* pparpage = ppg->m_pParent;
  680. BTreePage<K,D>* psibless = NULL;
  681. BTreePage<K,D>* psibgrtr = NULL;
  682. // find pointer to pg in parent
  683. for (long n = 0; pparpage->m_ppLinks[n] != ppg; ++n)
  684. ;
  685. // read sibling pages
  686. if (n < pparpage->m_hdr.NoOfKeys)
  687. psibgrtr = pparpage->m_ppLinks[n + 1];
  688. if (n > 0)
  689. psibless = pparpage->m_ppLinks[n - 1];
  690. if (!psibgrtr && !psibless)
  691. return;
  692. // decide to redistribute or concatenate
  693. if (!psibgrtr || (psibgrtr && psibless && (psibless->m_hdr.NoOfKeys > psibgrtr->m_hdr.NoOfKeys)))
  694. {
  695. --n;
  696. if (psibless->m_hdr.NoOfKeys > psibless->m_hdr.MinKeys)
  697. Redistribute(n,psibless,pparpage,ppg);
  698. else
  699. Concatenate(n,psibless,pparpage,ppg);
  700. }
  701. else if (psibgrtr)
  702. {
  703. if (psibgrtr->m_hdr.NoOfKeys > psibgrtr->m_hdr.MinKeys)
  704. Redistribute(n,ppg,pparpage,psibgrtr);
  705. else
  706. Concatenate(n,ppg,pparpage,psibgrtr);
  707. }
  708. }
  709. template <class K, class D>
  710. void BTree<K,D>::Redistribute(long keypos, BTreePage<K,D>* plesspage, BTreePage<K,D>* pparpage, BTreePage<K,D>* pgrtrpage)
  711. {
  712. // note: this function is ONLY called for leaf nodes!
  713. long n;
  714. if (!plesspage->m_ppLinks[0]) // working with leaves
  715. {
  716. if (plesspage->m_hdr.NoOfKeys > pgrtrpage->m_hdr.NoOfKeys)
  717. {
  718. // slide a key from lesser to greater
  719. // move keys in greater to the left by one
  720. for (n = pgrtrpage->m_hdr.NoOfKeys; n > 0; --n)
  721. {
  722. pgrtrpage->m_pNodes[n] = pgrtrpage->m_pNodes[n - 1];
  723. }
  724. // store parent separator key in greater page
  725. pgrtrpage->m_pNodes[0] = pparpage->m_pNodes[keypos];
  726. // increment greater page's key count
  727. ++pgrtrpage->m_hdr.NoOfKeys;
  728. // decrement lessor page's key count
  729. --plesspage->m_hdr.NoOfKeys;
  730. // move last key in less page to parent as separator
  731. pparpage->m_pNodes[keypos] = plesspage->m_pNodes[plesspage->m_hdr.NoOfKeys];
  732. // clear last key in less page
  733. memset((void*)&plesspage->m_pNodes[plesspage->m_hdr.NoOfKeys], 0, sizeof(BTreeNode<K,D>));
  734. }
  735. else
  736. {
  737. // slide a key from greater to lessor
  738. // add parent key to lessor page
  739. plesspage->m_pNodes[plesspage->m_hdr.NoOfKeys] = pparpage->m_pNodes[keypos];
  740. // increment lessor page's key count
  741. ++plesspage->m_hdr.NoOfKeys;
  742. // insert in parent the lowest key in greater page
  743. pparpage->m_pNodes[keypos] = pgrtrpage->m_pNodes[0];
  744. // decrement # of keys in greater page
  745. --pgrtrpage->m_hdr.NoOfKeys;
  746. // move keys in greater page to left
  747. for (n = 0; n < pgrtrpage->m_hdr.NoOfKeys; ++n)
  748. {
  749. pgrtrpage->m_pNodes[n] = pgrtrpage->m_pNodes[n + 1];
  750. }
  751. // make last key blank
  752. memset((void*)&pgrtrpage->m_pNodes[n], 0, sizeof(BTreeNode<K,D>));
  753. }
  754. }
  755. else
  756. {
  757. if (plesspage->m_hdr.NoOfKeys > pgrtrpage->m_hdr.NoOfKeys)
  758. {
  759. // slide a key from lesser to greater
  760. // move keys in greater to the left by one
  761. for (n = pgrtrpage->m_hdr.NoOfKeys; n > 0; --n)
  762. {
  763. pgrtrpage->m_pNodes[n] = pgrtrpage->m_pNodes[n - 1];
  764. pgrtrpage->m_ppLinks[n + 1] = pgrtrpage->m_ppLinks[n];
  765. }
  766. pgrtrpage->m_ppLinks[1] = pgrtrpage->m_ppLinks[0];
  767. // store parent separator key in greater page
  768. pgrtrpage->m_pNodes[0] = pparpage->m_pNodes[keypos];
  769. pgrtrpage->m_ppLinks[0] = plesspage->m_ppLinks[plesspage->m_hdr.NoOfKeys];
  770. // update child link
  771. BTreePage<K,D>* pchild;
  772. pchild = pgrtrpage->m_ppLinks[0];
  773. pchild->m_pParent= pgrtrpage;
  774. // increment greater page's key count
  775. ++pgrtrpage->m_hdr.NoOfKeys;
  776. // decrement lessor page's key count
  777. --plesspage->m_hdr.NoOfKeys;
  778. // move last key in less page to parent as separator
  779. pparpage->m_pNodes[keypos] = plesspage->m_pNodes[plesspage->m_hdr.NoOfKeys];
  780. // clear last key in less page
  781. memset((void*)&plesspage->m_pNodes[plesspage->m_hdr.NoOfKeys], 0, sizeof(BTreeNode<K,D>));
  782. plesspage->m_ppLinks[plesspage->m_hdr.NoOfKeys + 1] = NULL;
  783. }
  784. else
  785. {
  786. // slide a key from greater to lessor
  787. // add parent key to lessor page
  788. plesspage->m_pNodes[plesspage->m_hdr.NoOfKeys] = pparpage->m_pNodes[keypos];
  789. plesspage->m_ppLinks[plesspage->m_hdr.NoOfKeys + 1] = pgrtrpage->m_ppLinks[0];
  790. // update child link
  791. BTreePage<K,D>* pchild;
  792. pchild = pgrtrpage->m_ppLinks[0];
  793. pchild->m_pParent = plesspage;
  794. // increment lessor page's key count
  795. ++plesspage->m_hdr.NoOfKeys;
  796. // insert in parent the lowest key in greater page
  797. pparpage->m_pNodes[keypos] = pgrtrpage->m_pNodes[0];
  798. // decrement # of keys in greater page
  799. --pgrtrpage->m_hdr.NoOfKeys;
  800. // move keys in greater page to left
  801. for (n = 0; n < pgrtrpage->m_hdr.NoOfKeys; ++n)
  802. {
  803. pgrtrpage->m_pNodes[n] = pgrtrpage->m_pNodes[n + 1];
  804. pgrtrpage->m_ppLinks[n] = pgrtrpage->m_ppLinks[n + 1];
  805. }
  806. pgrtrpage->m_ppLinks[n] = pgrtrpage->m_ppLinks[n + 1];
  807. // make last key blank
  808. memset((void*)&pgrtrpage->m_pNodes[n], 0, sizeof(BTreeNode<K,D>));
  809. pgrtrpage->m_ppLinks[n + 1] = NULL;
  810. }
  811. }
  812. if (!pparpage->m_pParent)
  813. m_pRoot = pparpage;
  814. }
  815. template <class K, class D>
  816. void BTree<K,D>::Concatenate(long keypos, BTreePage<K,D>* plesspage, BTreePage<K,D>* pparpage, BTreePage<K,D>* pgrtrpage)
  817. {
  818. long n, ng;
  819. // move separator key from parent into lesspage
  820. plesspage->m_pNodes[plesspage->m_hdr.NoOfKeys] = pparpage->m_pNodes[keypos];
  821. plesspage->m_ppLinks[plesspage->m_hdr.NoOfKeys + 1] = pgrtrpage->m_ppLinks[0];
  822. ++plesspage->m_hdr.NoOfKeys;
  823. // delete separator from parent
  824. --pparpage->m_hdr.NoOfKeys;
  825. for (n = keypos; n < pparpage->m_hdr.NoOfKeys; ++n)
  826. {
  827. pparpage->m_pNodes[n] = pparpage->m_pNodes[n + 1];
  828. pparpage->m_ppLinks[n + 1] = pparpage->m_ppLinks[n + 2];
  829. }
  830. // clear unused key in parent
  831. memset((void*)&pparpage->m_pNodes[n], 0, sizeof(BTreeNode<K,D>));
  832. pparpage->m_ppLinks[n + 1] = NULL;
  833. // copy keys from grtrpage to lesspage
  834. ng = 0;
  835. n = plesspage->m_hdr.NoOfKeys;
  836. while (ng < pgrtrpage->m_hdr.NoOfKeys)
  837. {
  838. ++plesspage->m_hdr.NoOfKeys;
  839. plesspage->m_pNodes[n] = pgrtrpage->m_pNodes[ng];
  840. memset((void*)&pgrtrpage->m_pNodes[ng], 0, sizeof(BTreeNode<K,D>));
  841. plesspage->m_ppLinks[n + 1] = pgrtrpage->m_ppLinks[ng + 1];
  842. pgrtrpage->m_ppLinks[ng + 1] = NULL;
  843. ++ng;
  844. ++n;
  845. }
  846. delete pgrtrpage;
  847. // is this a leaf page?
  848. if (plesspage->m_ppLinks[0])
  849. {
  850. // adjust child pointers to point to less page
  851. BTreePage<K,D>* pchild;
  852. for (n = 0; n <= plesspage->m_hdr.NoOfKeys; ++n)
  853. {
  854. pchild = plesspage->m_ppLinks[n];
  855. pchild->m_pParent = plesspage;
  856. }
  857. }
  858. // write less page and parent
  859. if (pparpage->m_hdr.NoOfKeys == 0)
  860. {
  861. AdjustTree(pparpage);
  862. plesspage->m_pParent = pparpage->m_pParent;
  863. if (!plesspage->m_pParent)
  864. m_pRoot = plesspage;
  865. else
  866. {
  867. for (int n = 0; n <= pparpage->m_pParent->m_hdr.NoOfKeys; n++)
  868. {
  869. if (pparpage == pparpage->m_pParent->m_ppLinks[n])
  870. {
  871. pparpage->m_pParent->m_ppLinks[n] = plesspage;
  872. break;
  873. }
  874. }
  875. }
  876. delete pparpage;
  877. }
  878. else
  879. {
  880. // reset root page, if necessary
  881. if (!pparpage->m_pParent)
  882. m_pRoot = pparpage;
  883. // if parent is too small, adjust tree!
  884. if (pparpage->m_hdr.NoOfKeys < pparpage->m_hdr.MinKeys)
  885. AdjustTree(pparpage);
  886. }
  887. }
  888. template <class K, class D>
  889. void BTree<K,D>::RecurseTraverse(const BTreePage<K,D>* ppg, int depth)
  890. {
  891. long n;
  892. BTreePage<K,D>* p = NULL;
  893. depth++;
  894. // sequence through keys in page, recursively processing links
  895. for (n = 0; n < ppg->m_hdr.NoOfKeys; ++n)
  896. {
  897. // follow each link before processing page
  898. if (ppg->m_ppLinks[n])
  899. {
  900. p = ppg->m_ppLinks[n];
  901. RecurseTraverse(p, depth);
  902. }
  903. int index = 0;
  904. BTreeNode<K,D>* p = &ppg->m_pNodes[n];
  905. while(p)
  906. {
  907. TravFunc(p->m_Key, p->m_pData, depth, index);
  908. index++;
  909. p = p->m_pNext;
  910. }
  911. }
  912. // handle greatest subtree link
  913. if ((ppg->m_ppLinks != NULL) && ppg->m_ppLinks[n])
  914. {
  915. p = ppg->m_ppLinks[n];
  916. RecurseTraverse(p, depth);
  917. }
  918. }
  919. template <class K, class D>
  920. void BTree<K,D>::DeletePage(BTreePage<K,D>* ppg)
  921. {
  922. long n;
  923. BTreePage<K,D>* p = NULL;
  924. if (!ppg)
  925. return;
  926. // sequence through keys in page, recursively processing links
  927. for (n = 0; n < ppg->m_hdr.NoOfKeys; ++n)
  928. {
  929. // follow each link before processing page
  930. if (ppg->m_ppLinks[n])
  931. {
  932. p = ppg->m_ppLinks[n];
  933. DeletePage(p);
  934. ppg->m_ppLinks[n] = NULL;
  935. }
  936. }
  937. // handle greatest subtree link
  938. if ((ppg->m_ppLinks != NULL) && ppg->m_ppLinks[n])
  939. {
  940. p = ppg->m_ppLinks[n];
  941. DeletePage(p);
  942. ppg->m_ppLinks[n] = NULL;
  943. }
  944. delete ppg;
  945. }
  946. #endif