def __init__(self, degree): # This method is complete. self.degree = degree self.rootNode = BTreeNode(degree) # If time, file creation code, etc. self.nodes = {} self.stackOfNodes = MyStack() self.rootNode.setIndex(1) self.writeAt(1, self.rootNode) self.rootIndex = 1 self.freeIndex = 2
def __init__(self, table_dir, column, p) : self.table_dir = table_dir self.column = column infile = open('{}/header'.format(table_dir),'r') header = infile.read().strip().split(',') if column in header: self.colnum = header.index(column) # set this from dir/header and check it exists! else: print('Column named {} does not exist!'.format(column)) infile.close() self.p = p self.root = BTreeNode(p)
def delete(self, anItem): ''' Answer None if a matching item is not found. If found, answer the entire item. ''' searchResult = self.searchTree(anItem) n = self.degree if searchResult['found']: #the item is in the tree; delete it aNode = self.readFrom( searchResult['fileIndex']) #get the node that contains anItem nodeIndex = searchResult['nodeIndex'] done = False if not aNode.isLeaf( ): #if anItem is in a leaf node, find the inorder successor (ioSuc, iosNode) = self.inorderSuccessor(aNode, nodeIndex) searchResult = self.searchTree( ioSuc ) #search the tree in order to get the stack of nodes on the search path aNode.getItems( )[nodeIndex] = ioSuc #replace anItem with the inorder successor iosNode.removeItem( 0) #remove the inorder successor from its original node self.writeAt(aNode.getIndex(), aNode) #write the revised aNode to the file aNode = iosNode #reset what aNode refers to anItem = ioSuc else: #if anItem was already in a leaf node aNode.removeItem(nodeIndex) #remove anItem from the leaf node while not done and aNode.getNumberOfKeys() < n and aNode.getIndex( ) != self.rootIndex: #while aNode has less than n keys and is not the root parentNode = self.stackOfNodes.pop() #get the parent node (parentIndex, siblingNode, sibSide) = self.findParentAndSibling( anItem, parentNode) #get the parent index and the sibling totNumKeys = siblingNode.getNumberOfKeys( ) + aNode.getNumberOfKeys( ) + 1 #find the total number of keys, including the parent item tempNode = BTreeNode(2 * n) #create a temporary BTreeNode if sibSide == "right": #if using the right sibling, copy aNode, then parent, then sibling tempNode.copyItemsAndChildren(aNode, 0, aNode.getNumberOfKeys() - 1, 0) tempNode.getItems()[aNode.getNumberOfKeys( )] = parentNode.getItems()[parentIndex] tempNode.copyItemsAndChildren( siblingNode, 0, siblingNode.getNumberOfKeys() - 1, aNode.getNumberOfKeys() + 1) else: #if using the left sibling, copy the sibling, then parent, then aNode tempNode.copyItemsAndChildren( siblingNode, 0, siblingNode.getNumberOfKeys() - 1, 0) tempNode.getItems()[siblingNode.getNumberOfKeys( )] = parentNode.getItems()[parentIndex] tempNode.copyItemsAndChildren( aNode, 0, aNode.getNumberOfKeys() - 1, siblingNode.getNumberOfKeys() + 1) aNode.clear() #clear the items and children from the two nodes siblingNode.clear() if totNumKeys > 2 * n: #case 2a: redistribute sepKey = (totNumKeys + 1) // 2 #find the new separating key aNode.copyItemsAndChildren( tempNode, 0, sepKey - 2, 0 ) #put the items of the temp node back to where they belong, redistributed parentNode.getItems()[parentIndex] = tempNode.getItems()[ sepKey - 1] siblingNode.copyItemsAndChildren(tempNode, sepKey, totNumKeys - 1, 0) aNode.setNumberOfKeys(sepKey - 1) siblingNode.setNumberOfKeys(totNumKeys - sepKey) else: #case 2b: merge parentNode.removeItem( parentIndex ) #remove the parent item from the parent node if sibSide == "right": #remove the child representing the right sibling parentNode.removeChild(parentIndex + 1) if parentNode.getNumberOfKeys( ) == 0: #if the parent is now empty after the merge, make aNode the root of the tree done = True self.rootNode = aNode self.rootIndex = aNode.getIndex() aNode.copyItemsAndChildren( tempNode, 0, totNumKeys - 1, 0) #merge all the items into aNode aNode.setNumberOfKeys(totNumKeys) else: #remove the child representing the right sibling (aNode) parentNode.removeChild(parentIndex + 1) if parentNode.getNumberOfKeys( ) == 0: #if the parent is now empty after the merge, make sibNode the root of the tree done = True self.rootNode = siblingNode self.rootIndex = siblingNode.getIndex() siblingNode.copyItemsAndChildren( tempNode, 0, totNumKeys - 1, 0) #merge all the items into the sibling node siblingNode.setNumberOfKeys(totNumKeys) self.writeAt(aNode.getIndex(), aNode) #write the updates to the file self.writeAt(siblingNode.getIndex(), siblingNode) self.writeAt(parentNode.getIndex(), parentNode) aNode = parentNode #move up the tree and check if it's ok else: #the item is not in the tree; return None return None
def insert(self, anItem): ''' Answer None if the BTree already contains a matching item. If not, insert a deep copy of anItem and answer anItem. ''' searchResult = self.searchTree(anItem) #search for anItem if searchResult[ 'found']: #if anItem already exists in the tree, return None return None else: #if anItem doesn't exist in the tree insertNode = self.readFrom(searchResult['fileIndex'] ) #get the node anItem should belong in if insertNode.isFull( ): #if the node is full, need to split the node toParent = deepcopy( anItem) #make a deepcopy of the item we want to insert leftChild = None #since inserting into a leaf node, left and right children are None rightChild = None while insertNode.isFull(): splitNode = insertNode.addItemAndSplit( toParent, leftChild, rightChild) #split the full node splitNode.setIndex( self.freeIndex ) #set the index of the new node to be the next available index self.freeIndex += 1 #increment the free index number toParent = deepcopy(insertNode.getItems()[ insertNode.getNumberOfKeys() - 1]) #get the item that will go to the parent node insertNode.getItems()[ insertNode.getNumberOfKeys() - 1] = None #get rid of the record of the parent item insertNode.getChild()[insertNode.getNumberOfKeys( )] = None #get rid of the right child of the parent in the insertNode insertNode.setNumberOfKeys(insertNode.getNumberOfKeys() - 1) leftChild = insertNode.getIndex( ) #get the left and right indices of the parent rightChild = splitNode.getIndex() self.writeAt(leftChild, insertNode) #write both nodes to the file self.writeAt(rightChild, splitNode) insertNode = self.stackOfNodes.pop() #get the parent node if insertNode == None: #if there is no parent, create a new root node insertNode = BTreeNode(self.degree) #create a new node insertNode.setIndex( self.freeIndex ) #set the index of the new root node self.rootNode = insertNode self.rootIndex = self.freeIndex #set the root index self.freeIndex += 1 #increment the free index number insertNode.insertItem( toParent, leftChild, rightChild ) #if the parent node isn't full, just insert the item self.writeAt(insertNode.getIndex(), insertNode) #write the final node to the file else: #there is room for anItem, so just perform an insert insertNode.insertItem(deepcopy(anItem)) self.writeAt(searchResult['fileIndex'], insertNode) #write the node to the file return anItem #return the item