B-Trees insertion - data-structures

How do I add 35?
How do I know whether to move a key up(up to the node with 34 and 78, and if I do that, which key do I move up) and make more children(to fulfill the "A non-leaf node with k children contains k−1 keys." rule)
OR
just split up the 39,44,56,74(and 35) node into three children, like what I did in step 8.

AFAIK the insertion procedure is the following:
Find a position (node). Insert. Split if necessary. In this case 39,44,56,74 becomes 35,39,44,56,74. You need to split now: the new nodes are 35,39 and 56, 74 and the parent is now 34,44,78
Look at this example.

Related

when exactly should root split in a B Tree

I learned B trees recently and from what I understand a node can have minimum t-1 keys and maximum 2t-1 keys given minimum degree t. Exception being root can have even 1 key.
Here is the example from CLRS 3rd edition Fig 18.7 (Page 498) where t=3
min keys = 3-1 = 2
max keys = 2*3-1 = 5
In the d) example when L is inserted why is the root splitted when it doesn't violate the B tree properties at the moment (It has 5 keys which is maximum allowed).
Why isn't inserting L into [J K L] without splitting [G M P T X] considered.
Should I always split the root when it reaches the maximum?
There are several variants of the insertion algorithm for B-trees. In this case the insertion algorithm is the "single pass down the tree" variant.
The background for this variant is given on page 493:
Since we cannot insert a key into a leaf node that is full, we introduce an operation that splits a full node 𝑦 (having 2𝑡 − 1 keys) around its median key 𝑦:key𝑡 into two nodes having only 𝑡 − 1 keys each. The median key moves up into 𝑦’s parent to identify the dividing point between the two new trees. But if 𝑦’s parent is also full, we must split it before we can insert the new key, and thus we could end up splitting full nodes all the way up the tree.
As with a binary search tree, we can insert a key into a B-tree in a single pass down the tree from the root to a leaf. To do so, we do not wait to find out whether we will actually need to split a full node in order to do the insertion. Instead, as we travel down the tree searching for the position where the new key belongs, we split each full node we come to along the way (including the leaf itself). Thus whenever we want to split a full node 𝑦, we are assured that its parent is not full.
In other words, this insertion algorithm will split a node earlier than might be strictly needed, in order to avoid to have to split nodes while backtracking out of recursion.
This algorithm is further described on page 495 with pseudo code.
This explains why at the insertion of L the root node is split immediately before any recursive call is made.
Alternative algorithms would not do this, and would delay the split up to the point when it is inevitable.

Binary tree without pointers

Below is a representation of a binary tree that I use in my project. In the bottom are the leaf nodes (orange boxes), and every level is the sum of the children below.
So, 3 on the leftmost node is the sum of 1 and 2 (it's left and right children), 10 is the sum of 3 and 7 (again left and right children).
What I am trying to do is, store this tree in a flat array without using any pointers. So this array is basically an integer array, holding 2n-1 nodes (n is the number of the leaf nodes).
So the index of the root element is 0 (let's call it p), and the index of it's left child is 2p+1, index of the right child is 2p+2. Please see Binary Tree (Array implementation)
Everything works nicely if I know the number of leaf values beforehand but I can't seem to find a way to store this tree in a dynamically expanding array.
If I need to add 9 for example as the 9th element to the array, the structure needs to change and I need to recalculate all the indices again which I refrain because there may be hundreds of thousand of elements in the array at any time.
Does anyone know of an implementation that handles dynamic arrays with this implementation?
EDIT:
Below is the demonstration of what happens when I add new elements to the array. 36 was the root before, now it's a second level element and the new root array[0] is 114, which triggers a new layout.

Data structure/ Retrieving elements parent

im looking a way to find out any common elements for two parent elements.
For example, parents here are 1 and 2 (Ignore the below values)
And the common value for those parents are 91.
Parent - value that is on top and has NO parent.
Next example :
Here we have 3 parents. and quite a lot of common elements for them. :
91,
92,
93,
911,
912,
931,
932,
9311,
9312.
Main problem is to get the comon elements. Mabey any suggestions on how could i store them aswell?
Run a BFS/DFS (doesn't really matter which one) from the first node and store a visited bit for every node (say in a vector/array of bool).
Now run the same algorithm again from the second node. Every time you reach a new node check if it has been visited by the first run as well. If it was then the node is one of the common parents so output to whatever you want.

Why is this binary tree not a heap?

I have been teaching myself heaps for an exam and came across the following question:
"Give 2 different reasons why the following binary tree is not a heap"
91
/ \
77 46
/ \ \
68 81 11
I know one of the reasons this is because a heap's children must less than or equal to the value of its parent so 81 violates this rule as 81 > 77, but I am not sure on the other answer.
Could somebody please clarify?
11 should be the left-child of 46, not the right-child.
Wikipedia mentions that a binary heap should be a complete binary tree, which means "every level, except possibly the last, is completely filled, and all nodes are as far left as possible", which is clearly not the case if 11 is where it is now.
The reason why this is advantageous is fairly easy to understand - given the size of the heap, you can quickly determine where the last node on the bottom level is, which is necessary to know for insertion and deletion. If we're using an array representation, it's as simple as the element at heap size - 1 being the last element. For a pointer-based representation, we could easily determine whether we should go left or right to get to the last element.
There may be other ways to get the same performance without the heap being a complete binary tree, but they'd likely add complexity.
That is not a heap because it doesn't conform to the heap property.
In a min-heap, every node's value is less than or equal to its child nodes' values.
In a max-heap, every node's value is greater than or equal to its child nodes' values.
It's clearly not a min-heap because the root node, 91, is larger than either of its children.
And it's clearly not a max-heap because the node 77 is smaller than its right child, 81.
And, as #Dukeling pointed out in his answer, it doesn't conform to the shape property.

How to do B-Tree Insert

I am trying to insert 3 values into this B-Tree, 60, 61, and 62. I understand how to insert values when a node is full, and has an empty parent, but what if the parent is full?
For example, when I insert 60 and 61, that node will now be full. I can't extend the parent, or the parent of the parent (because they are full). So can I change the values of the parent? I have provided an image of the B-tree prior to my insert, and after.
Attempt to insert 60, 61, 62:
Notice I changed the 66 in the root to 62, and added 62 to to the <72 node. Is this the correct way to do this?
With the insertion you've done, you get what's normally referred to as a B* tree. In a "pure" B-tree, the insertion when the root is full would require splitting the current root into two nodes, and creating a new root node above them (B-tree implementations do not require that root node to follow the same rule as other nodes for the minimum number of descendants, so having only two would be allowed).

Resources