Пример #1
0
    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
Пример #2
0
 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