{"id":97,"date":"2006-07-11T02:12:53","date_gmt":"2006-07-11T06:12:53","guid":{"rendered":"http:\/\/www.rakkar.org\/blog\/?p=97"},"modified":"2006-07-11T02:12:53","modified_gmt":"2006-07-11T06:12:53","slug":"useful-data-structure-of-the-day-bplus-tree","status":"publish","type":"post","link":"https:\/\/rakkar.org\/blog\/index.php\/2006\/07\/11\/useful-data-structure-of-the-day-bplus-tree\/","title":{"rendered":"Useful data structure of the day: BPlus tree"},"content":{"rendered":"<p>\t\t\t\tIn <a HREF=\"http:\/\/www.rakkarsoft.com\">RakNet<\/a>, when I sent a message I put it on a queue.  When an acknowlegment arrives, I look at the head of the queue and assuming that acknowlegement matches what is there, I pop the queue.  Most of the time that works great &#8211; O(1) both ways.  But there is a problem &#8211; with large blocks lost, you get the folloowing bug:<\/p>\n<p>(assuming I missed out on elements 0-1000)<br \/>\nSearch through a 1000 element list for element # 1001<br \/>\nSearch through a 1000 element list for element # 1002<br \/>\nSearch through a 1000 element list for element # 1003<br \/>\nSearch through a 1000 element list for &#8230;                2000<\/p>\n<p>Assuming the list went from 0 to 1000, this is 1 million iterations because in the worst case I did a linear search through the queue.<\/p>\n<p>This rarely happened because usually acknowlegements came in the order I did sends, so 99.99% of the time there wasn&#8217;t a problem and it was O(1).  But I needed a data structure that, given input not in the set, would still do a relatively fast find.  However, it also had to do fast insertions and deletions (which was why I used a queue to begin with).<\/p>\n<p>I could have used my AVL Balanced binary tree.  It&#8217;s a binary tree that automatically rebalances after every insertion and deletion.  It&#8217;s pretty good for unsorted data &#8211; finds, insertions, and deletions are all Log2(n).  However, I wrote it back in college so it wasn&#8217;t as efficient as it could be.  The main problem was that there was a lot of node creation and destruction. <\/p>\n<p>I also wrote a B Tree and a BPlus tree in college.  A BPlus tree is an n-way tree of order o where each node contains o keys and o+1 children.  Each leaf contains an ordered list of key\/data pairs.  The leftmost child of a node points to the subtree where all keys are less than node key 0, the child o+1 is the value of the lowest key of that subtree, and so on.  All leaves are linked in a linked list.  In essence, it&#8217;s an ordered list divided up among leaves with the branches of the tree pointing into that list.<\/p>\n<p>I thought it would be a one day at most project since that&#8217;s about how long it took me in college.  However, I did two things differently:<br \/>\n1. I didn&#8217;t remember how to do it.  Thinking it would be easy, I started coding without full understanding of the data structure.<br \/>\n2. I wanted something very optimal so went to extreme lengths to make it so.<\/p>\n<p>So it took a week \ud83d\ude41<\/p>\n<p>Anyway it&#8217;s done now and it&#8217;s a good data structure.  If you need an ordered list where insertions, deletions, and searches are all fast, and\/or you want to linearly traverse the list, a B+ is the way to go.  If you need fast insertions, deletions, and searches but your data doesn&#8217;t have to be ordered and you don&#8217;t need linear traversals very often, an AVL tree is slightly more efficient.<\/p>\n<p>It&#8217;s in RakNet as the file DS_BPlusTree.h.\t\t<\/p>\n","protected":false},"excerpt":{"rendered":"<p>In RakNet, when I sent a message I put it on a queue. When an acknowlegment arrives, I look at the head of the queue and assuming that acknowlegement matches what is there, I pop the queue. Most of the time that works great &#8211; O(1) both ways. But there is a problem &#8211; with [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[3],"tags":[],"_links":{"self":[{"href":"https:\/\/rakkar.org\/blog\/index.php\/wp-json\/wp\/v2\/posts\/97"}],"collection":[{"href":"https:\/\/rakkar.org\/blog\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/rakkar.org\/blog\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/rakkar.org\/blog\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/rakkar.org\/blog\/index.php\/wp-json\/wp\/v2\/comments?post=97"}],"version-history":[{"count":0,"href":"https:\/\/rakkar.org\/blog\/index.php\/wp-json\/wp\/v2\/posts\/97\/revisions"}],"wp:attachment":[{"href":"https:\/\/rakkar.org\/blog\/index.php\/wp-json\/wp\/v2\/media?parent=97"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/rakkar.org\/blog\/index.php\/wp-json\/wp\/v2\/categories?post=97"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/rakkar.org\/blog\/index.php\/wp-json\/wp\/v2\/tags?post=97"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}