Указатели - передача ptr в ptr или передача адреса ptr - PullRequest
4 голосов
/ 30 октября 2011

Я пытаюсь удалить левый дочерний элемент (10) из примера дерева двоичного поиска, используя два метода:

  • Метод 1: путем передачи указателя на указатель на текущий узел.
  • Метод 2: Передавая адрес указателя на текущий узел.Это не удаляет узел, но вызов delete разрушает расположение указателей, вызывая сбой при печати узлов.

Дерево выглядит следующим образом, и я пытаюсь удалить 10 и заменить его на 5

       20
       |  
   10--|---30
    |
5---|

Я немного разбираюсь в указателях.Но, тем не менее, мне не совсем понятно с таким поведением указателей.

#include <iostream>
class Node
{
public:
    Node(int key) : leftChild(0), rightChild(0), m_key (key){}
    ~Node(){}

    Node *leftChild;
    Node *rightChild;
    int m_key;
};

Node* build1234(int, int, int, int);
void print(Node *);
void print1234(Node *);

void removeLeft(Node **nodePtr)
{
    Node *oldPtr = *nodePtr;
    if(*nodePtr)
    {
        *nodePtr = (*nodePtr)->leftChild;
        delete oldPtr;
    }
}

int main()
{
    Node *demo1 = build1234(10, 20, 30, 5);
    Node *demo2 = build1234(10, 20, 30, 5);
    print1234(demo1);
    print1234(demo2);

    //Method1 - 10 is correctly removed with 5
    Node **nodePtr = &demo1;
    nodePtr = &(*nodePtr)->leftChild;
    removeLeft(nodePtr);
    print1234(demo1);

    //Method2 - 10 is not removed
    Node *node = demo2;
    node = node->leftChild;
    removeLeft(&node);
    print1234(demo2);       
    return 0;
}

Node* build1234(int B, int A, int C, int D)
{
    Node *root = new Node(A);
    root->leftChild = new Node(B);
    root->rightChild = new Node(C);
    root->leftChild->leftChild = new Node(D);
    return root;
}
void print(Node *node)
{
    if(node)
    {
        print(node->leftChild);
        std::cout << "[" << node->m_key << "]";
        print(node->rightChild);
    }
}

void print1234(Node *node)
{
    std::cout << std::endl;
    print(node);
}

Примечание: Этот вопрос касается не BST, а указателей.Если вы видите два вызова removeLeft(nodePtr) и removeLeft(&node) в функции main().

  1. Чем они отличаются?
  2. Почему второму способу не удается достичь желаемого результата?

Ответы [ 3 ]

0 голосов
/ 30 октября 2011

Ты слишком обдумываешь это.Все, что вам нужно, это функция removeLeft(Node*), которая открепляет левый узел и рекурсивно удаляет его:

0 голосов
/ 30 октября 2011

Если у вас плохо с указателями, рассмотрите возможность использования умных указателей.
При использовании умных указателей используйте shared_ptr<Node> вместо Node * и make_shared(new Node); вместо new Node и удалите все удаления.теперь вы можете обрабатывать указатели, не заботясь об удалении и повреждении памяти.

0 голосов
/ 30 октября 2011

В первом случае вы передаете адрес указателя, который существует в дереве, поэтому вы изменяете содержимое дерева напрямую.

Во втором случае вы передаете адреспеременная, которая является локальной для main ().Дерево не изменяется, и удаление с адреса приводит к обращению к стековой памяти, поэтому происходит сбой

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...