2015-05-20 79 views
0

我正在編碼紅黑樹,​​通過以下算法介紹。當涉及到右旋功能時,我的一個指針被意外修改了。指針被意外修改

void RBTree::RightRotate(pNode &z) 
{ 
    pNode l=z->lChild; 
    z->lChild = l->rChild;  //link z->l-r to z as a lChild 
    if(l->rChild != nil)   
     l->rChild->p = z;  
    l->p = z->p;    //when pass the tree's root as parameter 
           //z,after executing this line, z was 
           //modified to pointing to nil 
           //(known from debug window), why? 
    if(z->p == nil)    
     root = l; 
    else if (z == z->p->lChild) 
     z->p->lChild = l; 
    else 
     z->p->rChild = l; 
    l->rChild=z; 
    z->p=l; 
} 

而且正如算法導論去,我在我的課設置nil指針。 由於只有當root作爲參數z可以導致此問題時,我推遲nilroot有問題。下面是整個代碼。 :我在一個錯誤的方式使用零



    #include 
    #include 
    #include  
    #define RED 1 
    #define BLACK 0 
    using namespace std; 
    typedef struct Node 
    { 
     int color, val; 
     struct Node* lChild, *rChild, *p; 
     Node(int val_, struct Node* tmp) 
       {color=RED, val=val_,lChild=rChild=p=tmp;} 
     Node(){color=BLACK, val=0,lChild=rChild=p=NULL;} 
    }Node,*pNode; 

    class RBTree 
    { 
    public: 
     RBTree() 
     { 
      root=NULL; 
     } 
     ~RBTree() 
     { 
      Free_(root); 
     } 
     void Free_(pNode p) 
     { 
      if(p!=NULL) 
      { 
       Free_(p->lChild); 
       Free_(p->rChild); 
       delete(p); 
       p=NULL; 
      } 
     } 
     pNode FindMin() const 
     { 
      pNode p=root; 
      if (p) 
       while(p->lChild) 
        p=p->lChild; 
      return p; 
     } 
     pNode FindMax() const 
     { 
      pNode p=root; 
      if (p) 
       while(p->rChild) 
        p=p->rChild; 
      return p; 
     } 
     void Print(pNode p, int n) const 
     { 
      if(!p) 
       return; 
      Print(p->rChild,n+2); 
      for(int i=0;ivalcolor==1)?"R":"B")lChild,n+2); 
     } 
     pNode Root() {return root;} 
     void Insert(int const& val_); 
     void InsertFixup(pNode &z); 
     void LeftRotate(pNode &p); 
     void RightRotate(pNode &p); 
     pNode Search(pNode const &p, int x) const; 
     void Delete(pNode &p, int x); 

    private: 
     pNode root; 
     static pNode nil; 
    }; 

    pNode RBTree::nil = new Node(); 

    /* 
    Inserting pipiline: 
    Insert node into RBTree, then fixup. 
    In the fixup procedure , rotate may be called 
    */ 

    void RBTree::InsertFixup(pNode &z) 
    { 
     while (z->p->color == RED) 
     { 
      pNode y; 
      if (z->p == z->p->p->lChild) 
      { 
       y=z->p->p->rChild; 
       if(y->color == RED) 
       { 
        z->p->color = BLACK; 
        y->color = BLACK; 
        z->p->p->color = RED; 
        z = z->p->p; 
       } 
       else 
       { 
        if(z==z->p->rChild) 
        { 
         z = z->p; 
         LeftRotate(z); 
        } 
        z->p->color = BLACK; 
        z->p->p->color = RED; 
        RightRotate(z->p->p); 
       } 
      } 
      else 
      { 
       y=z->p->p->lChild; 
       if(y->color == RED) 
       { 
        z->p->color = BLACK; 
        y->color = BLACK; 
        z->p->p->color = RED; 
        z=z->p->p; 
       } 
       else 
       { 
        if(z==z->p->lChild) 
        { 
         z = z->p; 
         RightRotate(z); 
        } 
        z->p->color = BLACK; 
        z->p->p->color = RED; 
        LeftRotate(z->p->p); 
       } 
      } 
     } 
     root->color = BLACK; 
    } 
    void RBTree::Insert(int const &val_) 
    { 
     pNode z=new Node(val_, nil);   //set val, lChild, rChild, p to NULL, color to RED 
     pNode x = root; 
     pNode pre = nil; 
     if(NULL == root) 
      root = z; 
     else 
     { 
      while (x!=nil) 
      { 
       pre=x; 
       x=(x->valrChild:x->lChild; 
      } 
      z->p = pre; 
      if (z->val val) 
       pre->lChild = z; 
      else 
       pre->rChild = z; 
     } 
     InsertFixup(z); 
    } 

    //left-rotate 
    //denote z, z's rChild == r 
    //parent changed: z, r, r's lChild 
    //child chagend: z->rChild, r->lChild, z->p->lChild/rChild 
    void RBTree::LeftRotate(pNode &z) 
    { 
     pNode r=z->rChild; 
     z->rChild = r->lChild;  //link p->r-l to p as a r 
     if(r->lChild != nil) 
      r->lChild->p = z; 
     r->p = z->p; 
     if(z->p == nil) 
      root = r; 
     else if (z == z->p->lChild) 
      z->p->lChild = r; 
     else 
      z->p->rChild = r; 

     r->lChild=z; 
     z->p=r; 
    } 
    // right-rotate 
    void RBTree::RightRotate(pNode &z) 
    { 
     pNode l=z->lChild; 
     z->lChild = l->rChild;  //link p->l-r to p as a l 
     if(l->rChild != nil) 
      l->rChild->p = z; 
     l->p = z->p; 
     if(z->p == nil)    //link parent from top to bottom 
      root = l; 
     else if (z == z->p->lChild) 
      z->p->lChild = l; 
     else 
      z->p->rChild = l; 
     l->rChild=z; 
     z->p=l; 
    } 
    int main() 
    { 
     int a[9] = {11, 2, 14, 1, 7, 15, 5, 8, 4}; 
     RBTree tr; 
     for(int i=0;i

是誰? 謝謝。

+2

一個可編譯的測試用例會非常好。至少,您應該顯示'Node'的定義以及通向'RightRotate'的調用。這很可能是一些別名問題。 –

+0

我發佈了整個程序,但似乎在頁面上出現了'<'和之後的內容,你能幫助糾正風格嗎? @SebastianRedl – lincr

回答

1

Nill不是C++表達式。但是有些環境可能會包含它,只是將其用作NULL0的別名。如果您使用C++ 11,我會建議nullptr

嘗試看看是否

l->p < z & & z < l->p + sizeof(z)

如果是這樣的話,您要指派給z

+0

我設置了一個'count'變量,並在該行的前後添加了* cout < val << endl << count ++ << endl; *。輸出是11和0.所以它確實發生了變化。沒有超載,我認爲也沒有多線程運行。真的很困惑。 – lincr

+0

@ArthurTian Mhm也許你可以嘗試獲取'l-> p'的地址和'z'的地址。如果'''''sizeof(z)''。這也可能導致地址改變。 – laurisvr

+0

@ArturTian我改變了我的答案以反映解決方案。我不清楚上下文是否足以知道這本書是否是錯誤的。 – laurisvr