2012-03-07 3 views
2

AvlTree 클래스 내에 클래스 반복자를 구현했습니다. 다음과 같이C++ AVL 트리 반복자가 제대로 증가하지 않습니다.

struct AvlNode 
{ 
    Comparable element; 
    list<int> lines; //line occurrences 
    bool flag; //checks validity 
    AvlNode *left; 
    AvlNode *right; 
    AvlNode *parent; //parent pointer 
    int  height; 

    AvlNode(const Comparable & theElement, AvlNode *lt, AvlNode *rt, AvlNode *pt, 
                int h = 0, bool b = true) 
     : element(theElement), left(lt), right(rt), parent(pt), height(h), flag(b) { } 
}; 

내 반복자는 다음과 같습니다 : 다음과 같이 내 AvlTree 노드는

 class iterator 
{ 
    protected: 

     friend class AvlTree<Comparable>; 
     AvlNode * node; 

     AvlNode * findInOrderSuccessor(AvlNode * & t) 
     { 
      AvlNode * temp; 
      //node has a right child 
      // so successor is leftmost node of right subtree 
      if(t->right != NULL) 
      { 
       temp = t->right; //go right 
       //go all the way left 
       while(temp->left != NULL) 
       { 
        temp = temp->left; 
       } 
       return temp; 
      } 

      //node has no right child 
      //if we are someone's left child, go up one 
      if(t->parent->left == t) 
      { 
       //return your parent 
       temp = t->parent; 
       return temp; 
      } 
      //if we are someone's right child, go up until the current node 
      //is someone's left child, then go up one more 
      temp = t->parent; 
      while(temp->parent->left != temp) 
      { 
       temp = temp->parent; //go up 
      } 
      //return your parent 
      temp = t->parent; 
      return temp; 

     } 

    public: 
     iterator(AvlNode * p) : node(p) 
      { } 

     //overload * to make *iterator return the element of its node 
     Comparable & operator*() 
      { return node->element; } 

     iterator operator++ (int) //postfix operator 
     { 
      node = findInOrderSuccessor(node); 
      return iterator(node); 
     } 

     // == comparison overload 
     bool operator==(iterator rhs) 
      { return node == rhs.node; } 
     // != comparison overload 
     bool operator!=(iterator rhs) 
      { return !(*this == rhs); } 
}; 

내 AvlTree도있는 시작 및 공공 구성원으로 끝 반복자 :

//begin iterator points to leftmost node 
iterator begin() 
{ //return pointer to leftmost node 
    AvlNode *temp = root; 
    while(temp->left != NULL) 
     temp = temp->left; 
    return iterator(temp); 
} 

//end iterator points to one after rightmost node 
iterator end() 
{ //return NULL right pointer of rightmost node 
    AvlNode * temp = root; 
    while(temp->right != NULL) 
     temp = temp->right; 
    return iterator(temp->right); 
} 

내 문제가 메인에서 다음을 실행하려고 할 때 :

for(AvlTree<string>::iterator itr = tree.begin(); itr != (tree.end()); itr++) 
     cout << *itr << endl; 

문자열 트리의 모든 단어를 inorder로 출력하는 대신 트리의 첫 번째 주문 항목에 무한 루프가 발생합니다. 나는 그것이 왜 첫 번째 항목을 지나서 움직이지 않는지 알 수는 없다.

+0

'end'연산자는 'return iterator (NULL);'와 같은 것으로 보입니다. 추적 결과를 * findInOrderSuccessor 함수에 추가하고 그 동작이 어디에서 벗어나야하는지 살펴 보시기 바랍니다. (트리 구조가 손상되었다는 것이 문제 일 가능성이 높습니다. 따라서 포인터 값도 기록하고 노드가 자체 노드가 아닌지 확인하십시오.) –

+0

무엇을 설명 할 수 있습니까? 당신은이 줄에서하고 있습니다 :'AvlNode * findInOrderSuccessor (AvlNode * & t)'? 왜 연산자'*'를 다시 작성하고 그것을 어떻게 사용하고 있습니까? – Matteo

+0

@DavidSchwartz 이미 트리 구현의 모든 것이 정확하다는 것을 알고 있습니다. 내가받는 유일한 문제는 반복자입니다. – Netsuki

답변

1

다음 반복 코드 (my AVL tree에서, link[0]link[1]에 대한 leftright 대체) 작동 : 첫째, end()이의 오른쪽 노드를 찾을 필요가 없습니다 지금까지 코드에 관한 한

BAVLNode * BAVL_GetFirst (const BAVL *o) 
{ 
    if (!o->root) { 
     return NULL; 
    } 

    BAVLNode *n = o->root; 
    while (n->link[0]) { 
     n = n->link[0]; 
    } 

    return n; 
} 

BAVLNode * BAVL_GetNext (const BAVL *o, BAVLNode *n) 
{ 
    if (n->link[1]) { 
     n = n->link[1]; 
     while (n->link[0]) { 
      n = n->link[0]; 
     } 
    } else { 
     while (n->parent && n == n->parent->link[1]) { 
      n = n->parent; 
     } 
     n = n->parent; 
    } 

    return n; 
} 

반환 주문 : iterator(NULL); 나무를 보지 않고 그냥 돌려 줄 수 있습니다.

while(temp->parent && temp->parent->left != temp) 

그리고 :

 temp = t->parent; 
WRONG: while(temp->parent->left != temp) 
     { 
      temp = temp->parent; //go up 
     } 
     //return your parent 
WRONG: temp = t->parent; 
     return temp; 

    } 

나는 NULL 포인터 역 참조를 시도하고 있습니다 플래그 첫 번째 줄은 변경되어야합니다

알고리즘의 실제 오류는 그러나 여기에 보인다 두 번째 것은 다음과 같습니다.

temp = temp->parent; 

또한 내 코드에서 followi 지금은 수퍼맨입니다. 그것은 제거 될 수 있고, 고정 된 나머지 코드에 의해 똑같은 방식으로 처리 될 것입니다. 또한 위와 같은 동일한 NULL 포인터 역 참조로 인해 어려움을 겪습니다.

//if we are someone's left child, go up one 
if(t->parent->left == t) 
{ 
    //return your parent 
    temp = t->parent; 
    return temp; 
} 
+0

감사합니다.이 코드는 완벽하게 작동했습니다! – Netsuki