Неожиданное поведение оператора стрелки «->» в c

#c #pointers #binary-search-tree

#c #указатели #двоичное дерево поиска

Вопрос:

Предоставленный мной код является простым BST только с обходом по вставке и порядку.

 struct Node{
    int data;
    Node* left;
    Node* right;
};

Node* create(int data){
    Node* node = new Node;
    node -> data = data;
    node->left=node->right=NULL;
    return node; 
}

Node* insert(Node* ptr,int item);
void inorder(Node* ptr);

int main(){
    Node* root = NULL;
    int temp,ch;
    root = insert(root, 10);
    root = insert(root, 20);
    root = insert(root, 30);

    inorder(root);
    cout<<endl;
}

Node* insert(Node* ptr,int item){
    if(ptr==NULL){
        cout<<"Inserted "<<item<<endl;
        return create(item);
    }
    if(item<ptr->data){
        // ptr = ptr->left;
        // ptr = insert(ptr, item)
        ptr->left=insert(ptr->left, item);
    }
    else{
        // ptr=ptr->right;
        // ptr = insert(ptr, item)
        ptr->right=insert(ptr->right, item);
    }
    return ptr;
}

void inorder(Node* ptr){
    if(ptr==NULL)
        return;
    inorder(ptr->left);
    cout<<ptr->data<<" ";
    inorder(ptr->right);
}
  

когда я использую,

 ptr = ptr->left;
ptr = insert(ptr, item)
  

вместо

 ptr->left=insert(ptr->left, item);
  

При обходе по порядку печатается только последний вставленный элемент.

Пожалуйста, объясните, является ли это проблемой c или я неправильно понимаю эту концепцию?

Комментарии:

1. один из них — «скопируйте значение ptr->left в ptr, измените ptr», другой — «измените ptr->left».

2. ptr является локальной переменной. Переназначение его (согласно вашей первой версии) не влияет ни на какой другой объект

3. Попробуйте пошагово выполнить код с помощью отладчика.

Ответ №1:

Важной частью кода является:

 Node* insert(Node* ptr,int item){
  

Для пояснения рассмотрим, что вы называете это так:

 Node x;
Node* p = amp;x;
insert(p, 42);
  

Здесь p передается по значению. Это указатель. Если вы измените ptr , то изменения будут применяться только к локальному, ptr а не к p .

Однако, если вы присваиваете значение ptr->first , то вы изменяете объект, на который указывает ptr . И хотя указатель передается по значению, ptr указывает на тот же объект, что и p . То есть: ptr->first = something; внутри функции действительно изменяет член x .

Ответ №2:

 ptr->left=insert(ptr->left, item);
  

Изменит содержимое ptr объекта. Он выполняет вставку и сохраняет ее.

Однако, когда вы делаете:

 ptr = ptr->left;
ptr = insert(ptr, item)
  

сначала вы получаете указатель на то, на что ptr->left указывал, вы вставляете таким же образом. Но возвращаемое значение не сохраняется в вашем исходном ptr объекте.

Итак, в этом нет ничего странного. Единственный известный мне способ полностью понять это — нарисовать дерево. Создайте окно, показывающее объект, и указатель на него, и для каждой операции обновляйте свой чертеж. Это должно стать понятным.