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 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