2017-08-11 106 views
-2

我試着在二叉樹上做一個程序。在deleteValue()有問題。如果我不打電話deleteValue()該程序運行完美。但如果我打電話deleteValue()它顯示binaryTree.exe已停止工作。二叉樹的C++程序

deleteValue()函數

void deleteValue(T val) 
    { 
     // Node* temp =root; 
     Node* node = search(root,val); 
     Node* parent; 
     Node* child; 

     //leaf node 
     if(node->left == nullptr && node->right == nullptr) 
     { 
      if(parent->left == node) parent->left == nullptr; 
      else if(parent->right == node) parent->right == nullptr; 

      delete node; 
      return; 
     } 

     //node having only one child 
     //replace it with its child and delete 
     if((node->left == nullptr && node->right != nullptr)|| (node->left != nullptr && node->right == nullptr)) 
     { 
      if(node->left == nullptr && node->right != nullptr) //right child present 
      { 
      if(parent->left == node) //line 198 
      { 
       parent->left = node->right; 
       delete node; 
       return; 
      } 
      else 
      { 
       parent->right = node->right; 
       delete node; 
       return; 
      } 
     } 
     else //left child present 
     { 
      if(parent->left == node) 
      { 
       parent->left = node->left; 
       delete node; 
       return; 
      } 
      else 
      { 
       parent->right = node->left; 
       delete node; 
       return; 
      } 
     } 
    } 

    //Node with 2 children 
    // replace node with smallest value in right subtree 
    if (node->left != nullptr && node->right != nullptr) 
    { 
     Node* chkr; 
     chkr = node->right; 
     if((chkr->left == nullptr) && (chkr->right == nullptr)) 
     { 
      node = chkr; 
      delete chkr; 
      node->right = nullptr; 
      return; 
     } 

     else // right child has children 
     { 
      //if the node's right child has a left child 
      // Move all the way down left to locate smallest element 

      if((node->right)->left != nullptr) 
      { 
       Node* lcurrp = node->right; 
       Node* lcurr = minimum(lcurrp); 

     node->data = lcurr->data; 

       lcurrp->left = nullptr; 
       delete lcurr; 
       return; 
      } 
      else 
      { 
       Node* tmp; 
       tmp = node->right; 
       node->data = tmp->data; 
      node->right = tmp->right; 
       delete tmp; 
       return; 
      } 

     } 
     return; 
    } 
    } 

binaryTree.cpp

#include <iostream> 

template<class T> 
class BinaryTree 
{ 
    struct Node 
    { 
     Node* parent; 
     Node* left; 
     Node* right; 
     T data; 
     Node(T const& val):parent(nullptr),left(nullptr),right(nullptr),data(val) {} 

     // This is the move constructor 
     // It moves the content of `val` into the node. For 
     // types like vectors this is much more efficient as it 
     // simply means copying three (or so) pointers and thus 
     // transferring the internal containers without the cost 
     // of copying all the elements in the vector. 
     Node(T&& val):parent(nullptr),left(nullptr),right(nullptr),data(std::move(val)) {} 

     //to enter any number and type of arguments 
     template<typename... Args> 
     Node(Args&&... args):parent(nullptr),left(nullptr),right(nullptr),data(std::forward<Args>(args)...) {} 

     ~Node() 
     { 
      delete left; 
      delete right; 
     } 
    }; 
struct Node* root; 

public: 
    BinaryTree():root(nullptr) {} 
    BinaryTree(BinaryTree const&)   = delete; 
    BinaryTree& operator=(BinaryTree const&) = delete; 
    ~BinaryTree() 
    { 
     delete root; 
    } 

    bool isEmpty() const 
    { 
     return root == nullptr; 
    } 

    //returns node of the element 
    Node* search(Node* root, T val) const 
    { 
     if(root == nullptr||val == root->data) return root; 

     if(val < root->data) return search(root->left,val); 

     else return search(root->right,val); 
    } 

    Node* minimum(Node* root) 
    { 
     while(root->left != nullptr) 
      root = root->left; 
     return root; 
    } 

    Node* maximum(Node* root) 
    { 
     while(root->right != nullptr) 
      root = root->right; 
     return root; 
    } 

    //Successor - a node which has the next higher key 
    Node* successor(Node* node) 
    { 
     if(node->right!=nullptr) return minimum(node->right); 

     Node* temp = node->parent; 

     while(temp != nullptr && node == temp->right) 
     { 
      node = temp; 
      temp = temp->parent; 
     } 
     return temp; 
    } 

    //Predecessor - a node which has the next lower key 
    Node* predecessor(Node* node) 
    { 
     if(node->left != nullptr) return maximum(node->left); 

     Node* temp = node->parent; 

     while(temp != nullptr && node == temp->left) 
     { 
      node = temp; 
      temp = temp->parent; 
     } 
     return temp; 
    } 

    void insertValue(T const& val) 
    { 
     Node* node = new Node(val); 
     Node* parent; 
     node->left = nullptr; 
     node->right = nullptr; 
     parent = nullptr; 

     if(isEmpty()) root = node; 
     else 
     { 
      Node* curr = root; 
      while(curr) 
      { 
       parent = curr; 
       if(node->data > curr->data) curr = curr->right; 
       else curr = curr->left; 
      } 

      if(node->data < parent->data) parent->left = node; 
      else parent->right = node; 
     } 
    } 

    void insertValue(T&& val) 
    { 
     Node* node = new Node(std::move(val)); 
     Node* parent; 
     node->left = nullptr; 
     node->right = nullptr; 
     parent = nullptr; 

     if(isEmpty()) root = node; 
     else 
     { 
      Node* curr = root; 
      while(curr) 
      { 
       parent = curr; 
       if(node->data > curr->data) curr = curr->right; 
       else curr = curr->left; 
      } 

      if(node->data < parent->data) parent->left = node; 
      else parent->right = node; 
     } 
    } 

    template<typename... Args> 
    void insertValue(Args&&... args) 
    { 
     Node* node = new Node(std::forward<Args>(args)...); 
     Node* parent; 
     node->left = nullptr; 
     node->right = nullptr; 
     parent = nullptr; 

     if(isEmpty()) root = node; 
     else 
     { 
      Node* curr = root; 
      while(curr) 
      { 
       parent = curr; 
       if(node->data > curr->data) curr = curr->right; 
       else curr = curr->left; 
      } 

      if(node->data < parent->data) parent->left = node; 
      else parent->right = node; 
     } 
    } 

void deleteValue(T val) 
    { 
     // Node* temp =root; 
     Node* node = search(root,val); 
     Node* parent; 
     Node* child; 

     //leaf node 
     if(node->left == nullptr && node->right == nullptr) 
     { 
      if(parent->left == node) parent->left == nullptr; 
      else if(parent->right == node) parent->right == nullptr; 

      delete node; 
      return; 
     } 

     //node having only one child 
     //replace it with its child and delete 
     if((node->left == nullptr && node->right != nullptr)|| (node->left != nullptr && node->right == nullptr)) 
     { 
      if(node->left == nullptr && node->right != nullptr) //right child present 
      { 
      if(parent->left == node) //line 198 
      { 
       parent->left = node->right; 
       delete node; 
       return; 
      } 
      else 
      { 
       parent->right = node->right; 
       delete node; 
       return; 
      } 
     } 
     else //left child present 
     { 
      if(parent->left == node) 
      { 
       parent->left = node->left; 
       delete node; 
       return; 
      } 
      else 
      { 
       parent->right = node->left; 
       delete node; 
       return; 
      } 
     } 
    } 

    //Node with 2 children 
    // replace node with smallest value in right subtree 
    if (node->left != nullptr && node->right != nullptr) 
    { 
     Node* chkr; 
     chkr = node->right; 
     if((chkr->left == nullptr) && (chkr->right == nullptr)) 
     { 
      node = chkr; 
      delete chkr; 
      node->right = nullptr; 
      return; 
     } 

     else // right child has children 
     { 
      //if the node's right child has a left child 
      // Move all the way down left to locate smallest element 

      if((node->right)->left != nullptr) 
      { 
       Node* lcurrp = node->right; 
       Node* lcurr = minimum(lcurrp); 

     node->data = lcurr->data; 

       lcurrp->left = nullptr; 
       delete lcurr; 
       return; 
      } 
      else 
      { 
       Node* tmp; 
       tmp = node->right; 
       node->data = tmp->data; 
      node->right = tmp->right; 
       delete tmp; 
       return; 
      } 

     } 
     return; 
    } 
    } 

    void inOrder(Node* node) 
    { 
     if(node != nullptr) 
     { 
      if(node->left) inOrder(node->left); 
      std::cout<<" "<<node->data; 
      if(node->right) inOrder(node->right); 
     } 
     else return; 
    } 

    void print_inOrder() 
    { 
     inOrder(root); 
    } 

    void preOrder(Node* node) 
    { 
     if(node != NULL) 
    { 
     std::cout<<" "<<node->data; 
     if(node->left) preOrder(node->left); 
     if(node->right) preOrder(node->right); 
    } 
    else return; 
    } 

    void print_preOrder() 
    { 
     preOrder(root); 
    } 

    void postOrder(Node* node) 
    { 
     if(node != NULL) 
    { 
     if(node->left) postOrder(node->left); 
     if(node->right) postOrder(node->right); 
     std::cout<<" "<<node->data; 
    } 
    else return; 
    } 

    void print_postOrder() 
    { 
     postOrder(root); 
    } 
}; 

int main() 
{ 
    BinaryTree<int> bt1; 
    bt1.insertValue(100); 
    bt1.insertValue(20); 
    bt1.insertValue(30); 
    bt1.insertValue(400); 
    bt1.insertValue(50); 
    bt1.print_inOrder(); 
    std::cout<<"\n"; 
    bt1.print_preOrder(); 
    std::cout<<"\n"; 
    bt1.print_postOrder(); 
    bt1.deleteValue(20); 
    std::cout<<"\n"; 
    bt1.print_inOrder(); 
    std::cout<<"\n"; 
    bt1.print_preOrder(); 
    std::cout<<"\n"; 
    bt1.print_postOrder(); 


    return 0; 
} 

我越來越

20 30 50 100 400 
100 20 30 50 400 
Segmentation fault (core dumped) 

輸出調試我得到錯誤

Program received signal SIGSEGV, Segmentation fault. 
0x08048c4e in BinaryTree<int>::deleteValue (this=0xbfffed04, val=20) at bt1.cpp:206 
206      parent->right = node->right; 

回答

0

當您刪除Node時,它也會同時刪除兩個子節點(leftright)。在deleteValue內,將左(或右)節點複製到父節點,然後刪除節點。這將刪除左側(或右側)節點,並且父節點將有一個懸掛指針指向它。

解決這個問題的一種方法是在刪除它之前(在刪除該節點時)在Node之內將左指針和右指針都空出。