2014-12-15 5 views
-2

다음과 같이 트리를 만들었습니다. mytree [3] = "red"mytree [4] = "blue"mytree [6] = "yellow"mytree [2] = "at" . 그러나 mytree.delete (3)을 사용하여 루트 노드 3을 삭제하려고하면 AttributeError가 발생합니다. 'TreeNode'객체에는 'findSuccessor'속성이 없습니다. 왜 이런 일이 일어나는 지 아십니까?
바이너리 검색 트리의 파이썬 속성 오류

class TreeNode: 
    def __init__(self,key,val,left=None,right=None,parent=None): 
     self.key = key 
     self.payload = val 
     self.leftChild = left 
     self.rightChild = right 
     self.parent = parent 

    def hasLeftChild(self): 
     return self.leftChild 

    def hasRightChild(self): 
     return self.rightChild 

    def isLeftChild(self): 
     return self.parent and self.parent.leftChild == self 

    def isRightChild(self): 
     return self.parent and self.parent.rightChild == self 

    def isRoot(self): 
     return not self.parent 

    def isLeaf(self): 
     return not (self.rightChild or self.leftChild) 

    def hasAnyChildren(self): 
     return self.rightChild or self.leftChild 

    def hasBothChildren(self): 
     return self.rightChild and self.leftChild 

    def replaceNodeData(self,key,value,lc,rc): 
     self.key = key 
     self.payload = value 
     self.leftChild = lc 
     self.rightChild = rc 
     if self.hasLeftChild(): 
      self.leftChild.parent = self 
     if self.hasRightChild(): 
      self.rightChild.parent = self 


class BinarySearchTree: 

    def __init__(self): 
     self.root = None 
     self.size = 0 

    def length(self): 
     return self.size 

    def __len__(self): 
     return self.size 

    def put(self,key,val): 
     if self.root: 
      self._put(key,val,self.root) 
     else: 
      self.root = TreeNode(key,val) 
     self.size = self.size + 1 

    def _put(self,key,val,currentNode): 
     if key < currentNode.key: 
      if currentNode.hasLeftChild(): 
       self._put(key,val,currentNode.leftChild) 
      else: 
       currentNode.leftChild = TreeNode(key,val,parent=currentNode) 
     else: 
      if currentNode.hasRightChild(): 
       self._put(key,val,currentNode.rightChild) 
      else: 
       currentNode.rightChild = TreeNode(key,val,parent=currentNode) 

    def __setitem__(self,k,v): 
     self.put(k,v) 

    def get(self,key): 
     if self.root: 
      res = self._get(key,self.root) 
      if res: 
       return res.payload 
      else: 
       return None 
     else: 
      return None 

    def _get(self,key,currentNode): 
     if not currentNode: 
      return None 
     elif currentNode.key == key: 
      return currentNode 
     elif key < currentNode.key: 
      return self._get(key,currentNode.leftChild) 
     else: 
      return self._get(key,currentNode.rightChild) 

    def __getitem__(self,key): 
     return self.get(key) 

    def __contains__(self,key): 
     if self._get(key,self.root): 
      return True 
     else: 
      return False 

    def delete(self,key): 
     if self.size > 1: 
      nodeToRemove = self._get(key,self.root) 
      if nodeToRemove: 
       self.remove(nodeToRemove) 
       self.size = self.size-1 
      else: 
       raise KeyError('Error, key not in tree') 
     elif self.size == 1 and self.root.key == key: 
      self.root = None 
      self.size = self.size - 1 
     else: 
      raise KeyError('Error, key not in tree') 

    def __delitem__(self,key): 
     self.delete(key) 

    def spliceOut(self): 
     if self.isLeaf(): 
      if self.isLeftChild(): 
       self.parent.leftChild = None 
      else: 
       self.parent.rightChild = None 
     elif self.hasAnyChildren(): 
      if self.hasLeftChild(): 
       if self.isLeftChild(): 
        self.parent.leftChild = self.leftChild 
       else: 
        self.parent.rightChild = self.leftChild 
        self.leftChild.parent = self.parent 
      else: 
       if self.isLeftChild(): 
        self.parent.leftChild = self.rightChild 
       else: 
        self.parent.rightChild = self.rightChild 
        self.rightChild.parent = self.parent 

    def findSuccessor(self): 
     succ = None 
     if self.hasRightChild(): 
      succ = self.rightChild.findMin() 
     else: 
      if self.parent: 
       if self.isLeftChild(): 
        succ = self.parent 
       else: 
        self.parent.rightChild = None 
        succ = self.parent.findSuccessor() 
        self.parent.rightChild = self 
     return succ 

    def findMin(self): 
     current = self 
     while current.hasLeftChild(): 
      current = current.leftChild 
     return current 

    def remove(self,currentNode): 
     if currentNode.isLeaf(): #leaf 
      if currentNode == currentNode.parent.leftChild: 
       currentNode.parent.leftChild = None 
      else: 
       currentNode.parent.rightChild = None 
     elif currentNode.hasBothChildren(): #interior 
      succ = currentNode.findSuccessor() 
      succ.spliceOut() 
      currentNode.key = succ.key 
      currentNode.payload = succ.payload 

     else: # this node has one child 
      if currentNode.hasLeftChild(): 
       if currentNode.isLeftChild(): 
        currentNode.leftChild.parent = currentNode.parent 
        currentNode.parent.leftChild = currentNode.leftChild 
       elif currentNode.isRightChild(): 
        currentNode.leftChild.parent = currentNode.parent 
        currentNode.parent.rightChild = currentNode.leftChild 
       else: 
        currentNode.replaceNodeData(currentNode.leftChild.key, 
            currentNode.leftChild.payload, 
            currentNode.leftChild.leftChild, 
            currentNode.leftChild.rightChild) 
      else: 
       if currentNode.isLeftChild(): 
        currentNode.rightChild.parent = currentNode.parent 
        currentNode.parent.leftChild = currentNode.rightChild 
       elif currentNode.isRightChild(): 
        currentNode.rightChild.parent = currentNode.parent 
        currentNode.parent.rightChild = currentNode.rightChild 
       else: 
        currentNode.replaceNodeData(currentNode.rightChild.key, 
            currentNode.rightChild.payload, 
            currentNode.rightChild.leftChild, 
            currentNode.rightChild.rightChild) 




mytree = BinarySearchTree() 
mytree[3]="red" 
mytree[4]="blue" 
mytree[6]="yellow" 
mytree[2]="at" 
mytree.delete(3) 

print(mytree[6]) 
print(mytree[2]) 
+0

'BinarySearchTree'가'TreeNode' (당신은'TreeNode'에서 온 BST 클래스 내에서'self'에 대한 메소드를 호출합니다)에서 상속 받겠지 만 그렇지 않습니다. 또한 나무가 어떻게 구성되어 있습니까 (I.E. 실제 코드)? 당신이 겪고있는 오류는 매우 명백합니다. 'TreeNode' 타입의 객체는 그것에 적용된'BinarySearchTree'의 메소드를 가지고 있습니다. 'BinarySearchTree' 클래스는'BinarySearchTree' 인스턴스가 아닌'TreeNodes' 인스턴스를 자체에 삽입하기 때문에 의미가 있습니다. – aruisdante

+0

간단히 말하면, 다시 코드를 살펴보고'TreeNodes'를 참조하고 있는지 확인하십시오. 'TreeNodes'와'BinarySearchTrees'를 참조하는 것을 의미합니다. – aruisdante

+0

나뭇잎을 삭제하는 것이지만 내부에는 아무것도 없어. –

답변

0

당신은 BinarySearchTree.remove에서 TreeNode의 인스턴스에 findSuccessor을 요구하고있다. TreeNode 구현에는 findSuccessor 메서드가 없지만 BinarySearchTree 클래스는 수행합니다. 메서드 findSuccessorTreeNode에 추가하거나 remove 메서드를 편집하여 BinarySearchTree에서 findSuccessor 메서드를 호출하십시오.

class TreeNode: 

    # ...Omitted code 

    def findSuccessor(self): 
     succ = None 
     if self.hasRightChild(): 
      succ = self.rightChild.findMin() 
     else: 
      if self.parent: 
       if self.isLeftChild(): 
        succ = self.parent 
       else: 
        self.parent.rightChild = None 
        succ = self.parent.findSuccessor() 
        self.parent.rightChild = self 
     return succ 

    def findMin(self): 
     current = self 
     while current.hasLeftChild(): 
      current = current.leftChild 
     return current 

또는 아마 당신은 TreeNode에서 상속 BinarySearchTree 의미 :

TreeNode에 추가

class BinarySearchTree(TreeNode): 
    # ...Omitted code... 

어떤 경우에는 그냥 BinarySearchTree 참조로 TreeNode 클래스에 대한 참조를 대체 할 수있다.

class BinarySearchTree(TreeNode): 

    #### OMITTED CODE ##### 

    def put(self,key,val): 
     if self.root: 
      self._put(key,val,self.root) 
     else: 
      self.root = BinarySearchTree(key,val) ### switched TreeNode for BinarySearchTree 
     self.size = self.size + 1 

    def _put(self,key,val,currentNode): 
     if key < currentNode.key: 
      if currentNode.hasLeftChild(): 
       self._put(key,val,currentNode.leftChild) 
      else: 
       currentNode.leftChild = BinarySearchTree(key,val,parent=currentNode) ### switched TreeNode for BinarySearchTree 
     else: 
      if currentNode.hasRightChild(): 
       self._put(key,val,currentNode.rightChild) 
      else: 
       currentNode.rightChild = BinarySearchTree(key,val,parent=currentNode) ### switched TreeNode for BinarySearchTree 

    ########## Omitted Code ####### 

어느 쪽이든 작동합니다. 나는 후자의 더 큰 팬이다.

+1

그것은 작동합니다! 실제로 나를 도와 줘서 고마워! 정말 감사. –

+0

@SoneNine 문제 없습니다! 학습에 행운을 비네! –

관련 문제