I need to construct a BTree from a sorted array. Any pointers or how can i write such an algorithm? Is there any algoritm that can take advantage of the array being sorted?
I did search it on the google but could not find algorithm for BTree.
I need to construct a BTree from a sorted array. Any pointers or how can i write such an algorithm? Is there any algoritm that can take advantage of the array being sorted?
I did search it on the google but could not find algorithm for BTree.
The way of @rossum is simple, but it is not efficient. His proposal don't use the information, that have a sorted list.
I think, that you have solved the problem of equal keys. (Nodes of the BTree or List in one Node of the BTree)
I understand your question in this way:
You want convert a sorted list/arry directly to a btree with the degree t. I have only a guess/idea. Detect the point of
Step Detect the minimal height h for a given number of elements n be caclulation the range of min and max elements for the given height of a BTree.
n(max) = sum(i=0,i<=h){Res += t^i*(t-1)}
n(min) = sum(i=0,i<h){Res += ceil(t/2)^i*(ceil(t/2)-1))} // ceil the result of the divisions
Step Minimize the range between t and t/2 to t>=x(high) and x(Low)>=(t/2), while n is in the range of x(low) and x(max) 3.Step calculation rekursive the node, where you have to change vorm x(high) to x(Low)
step Construct your BTree, which contains internal nodes with degree (x(high)) and which contains leaves with (x(High)-1) internal keys until you reach your reference node. After reaching your reference node all internal nodes have x(low)=x(high)-1 degrees and all leaf-nodes habe x(low) keys.
But this is only an idea. I havn't programmed it.
@padina Your pretty right. I build something in python for my work. I shrinked it down to the minimum code. Maybe you want to take a look at dbis-btree-git
So it's more pseudocode:
def valuesInFullTree(self):
'''
Determine the number of int-values for corresponding
valuesCountInOneNode, and height value
self : BTree_Creator
return : int
'''
if self.height < 0 or self.valuesCountInOneNode < 0:
return 0
count = self.valuesCountInOneNode
curHeight = 1
for _ in range(0,self.height):
count += pow(self.valuesCountInOneNode+1,curHeight)*self.valuesCountInOneNode
curHeight += 1
return count
def buildTree(self):
'''
This method builds first a full BTree.
self : BTree_Creator
'''
neededValuesCount = self.valuesInFullTree()
if neededValuesCount > self.maxValueInTree:
raise ValueError('Please use a bigger values for self.maxValueInTree, at least bigger than '+str(neededValuesCount))
valuesInTree = random.sample(range(1, self.maxValueInTree), neededValuesCount)
valuesInTree.sort()
# build a BTree with only values from valuesInTree
stackForRecursion = [(0,None,valuesInTree,0)]
self.rekursivSplitArray(stackForRecursion)
def rekursivSplitArray(self, stackForRecursion):
'''
Split Array and generate from new Splitpoints a Node in the Tree
stackForRecursion = [(nodeName, parentNode, values, currentHeight), ( ... ]
stackForRecursion : array with tupels
(nodeName, parentNode, values, currentHeight) : (int, int/None, int-array, int)
'''
if len(stackForRecursion) == 0:
return
(nodeName, parentNode, values,
currentHeight) = stackForRecursion.pop(0)
# self.height must be defined
if currentHeight > self.height:
return
valuesForNode = values
if currentHeight < self.height:
# there are children for the current node
firstSplitIdx = len(values)/(self.valuesCountInOneNode+1)
splitPointIdx = firstSplitIdx
previousSplitIdx = 0
valuesForNode = []
nextNodeName = nodeName * (self.valuesCountInOneNode + 1)
for i in range(0,self.valuesCountInOneNode+1):
if i < self.valuesCountInOneNode:
valuesForNode.append(values[int(splitPointIdx)])
nextNodeName += 1
nodeTupel = (nextNodeName, nodeName,
values[int(previousSplitIdx):int(splitPointIdx)],
currentHeight + 1)
stackForRecursion.append(nodeTupel)
previousSplitIdx = splitPointIdx + 1
splitPointIdx += firstSplitIdx
else:
if len(valuesForNode) != self.valuesCountInOneNode:
raise ValueError('The rekursiv tree build algo doesnt work')
# add Node to myBBaum
# pay ATTENTION this add_node, and add_edge lwad to an error...
self.myBBaum.add_node(BTree_Creator.getNodeName(nodeName), valuesForNode)
# add Edge to myBBaum
if parentNode != None:
thisNodeIsChildNumber = (nodeName % (self.valuesCountInOneNode + 1))
if thisNodeIsChildNumber == 0:
thisNodeIsChildNumber = self.valuesCountInOneNode + 1
self.myBBaum.add_edge(BTree_Creator.getNodeName(parentNode),
BTree_Creator.getNodeName(nodeName),
thisNodeIsChildNumber)
# rekursiv call
for _ in range(0, self.valuesCountInOneNode + 1):
self.rekursivSplitArray(stackForRecursion)
# insert a number and it return the letter combination
# for ex: 2=B,3=C,27=AA
@staticmethod
def getNodeName(num):
numOfA_s = num // 26
nodeName = ''
for _ in range(0, numOfA_s):
nodeName += 'A'
return nodeName + str(chr((num % 26) + ord('A')))
# insert a number and it return the letter combination
# for ex: B=2,C=3,AA=27
@staticmethod
def convertNodeNameInNumber(name):
number = -ord('A')
for char in name:
number += ord(char)
return number
Here’s a simple and efficient algorithm for building the B-tree. First, an observation. If you insert all the values in the sorted sequence in order, then each newly-inserted element will end up being placed in the rightmost leaf node of the tree. From there, you may have too many keys in the rightmost leaf, and you can then use the regular B-tree insertion algorithm to split the node and kick keys higher up in the tree.
So here’s the algorithm: maintain a pointer to the rightmost leaf node. For each element in the sorted sequence, place that item as the largest item in the rightmost leaf. If the leaf overflows, use the regular B-tree insertion fix up logic to split the node and kick a key higher in the tree.
Intuitively, almost all of the insertions you do will not require a split and will run in time O(1) - just follow a pointer and place the key. A small fraction will require one split and kick a key higher up in the tree. An even smaller fraction will require two splits, an even smaller will require three, etc. By either counting exactly how many inserts will require splitting multiple keys or using an amortized analysis, you can show that the total work required here is O(n), which is as fast as you’re going to be able to get things in an asymptotic sense.