Почему мой C ++ код не удалить все узлы в моем BST?

голоса
1

Это должно пересекать BST и удалить все узлы, включая корневой узел. Однако, в конце концов, я получаю сообщение «корень еще имеет левый узел.» Почему не удаляются все узлы?

void deleteTree()
{   
    deleteNode(root);
    if(root->right)
        cout << root still has a right node << endl;
    if(root->left)
        cout << root still has a left node << endl;
    root = 0;

}   

void deleteNode(node *p) 
{   
    if(p->left) 
    {   
        deleteNode(p->left);
        p->left = 0;
    }   
    if(p->right) 
    {   
        deleteNode(p->right);
        p->right = 0;
    }   

    cout << Deleting node containing  << p->data << endl;
    delete p;
}   
Задан 11/02/2010 в 03:57
источник пользователем
На других языках...                            


5 ответов

голоса
6

Вы удаляете pв конце ( root) , а затем пытается получить доступ к его содержимое deleteTree(), где rootбольше не указывает на выделенную память. Результат будет неопределенным.

Ответил 11/02/2010 в 04:00
источник пользователем

голоса
2

Вы удаление root. И тогда ваш код пытается получить доступ к памяти , где она была.

Вы также в неопределенном-поведенческой землю там.

Ответил 11/02/2010 в 04:01
источник пользователем

голоса
2

Вы не должны разыменовать rootпосле удаления его deleteNode. Используйте отладчик , чтобы проверить , почему root->leftне равен нулю.

Ответил 11/02/2010 в 04:01
источник пользователем

голоса
2

Вы смотрите root->leftпосле того, как вы уже удалили корень, что делает его для использования Имеющийся в новом выделенном блоке.

Ответил 11/02/2010 в 04:02
источник пользователем

голоса
-1

Я бы просто изменить само дерево, было бы легче иметь дело с ним, то:

struct Node
{
  Node(data_type data): mLeft(), mRight(), mData(data) {}
  Node(const Node& rhs): mLeft(), mRight(), mData(rhs.mData)
  {
    if (rhs.mLeft.get()) mLeft.reset(new Node(*rhs.mLeft));
    if (rhs.right.get()) mRight.reset(new Node(*rhs.mRight));
  }
  Node& operator=(Node rhs)
  {
    this->swap(rhs);
    return *this;
  }
  ~Node() { }

  void swap(Node& rhs)
  {
    using std::swap;
    swap(mLeft, rhs.mLeft);
    swap(mRight, rhs.mRight);
    swap(mData, rhs.mData);
  }

  Node* left() const { return mLeft.get(); }
  void left(std::auto_ptr<Node> node) { mLeft= node; }

  Node* right() const { return mRight.get(); }
  void right(std::auto_ptr<Node> node) { mRight = node; }

  data_type& data() { return mData; }
  const data_type& data() const { return mData; }

private:
  std::auto_ptr<Node> mLeft;
  std::auto_ptr<Node> mRight;
  data_type mData;
};

Будучи объектно-ориентированным, каждый узел теперь отвечает за память он обрабатывает. Кроме того , использование std::auto_ptrв интерфейсе становится ясно , что он принимает в собственность.

Обратите внимание , что это было специально для глубокого копирования, любой другой подход требует boost::shared_ptrили эквивалента. И да std::auto_ptrоставляет вас дело с копированием самостоятельно, никакой магии там.

Такая конструкция значительно чище , чем при использовании равнину C-structсо всеми быть в состоянии управлять ресурсами. Вы по- прежнему иметь полный доступ к базовым данным через аксессор ... но они заботятся , чтобы не вызвать неопределенное поведение ...

Конечно, вы все еще может привести к сбою его вниз:

Node& node = ...
delete node.left(); // haha

Но если C ++ может защитить от непредусмотренных проблем, он оставляет дверь открытой для злого кода.

Ответил 11/02/2010 в 14:22
источник пользователем

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more