Рекурсивная функция void с параметром * &

0

У меня проблема с этой рекурсивной функцией void:

void ReadBinaryTree(NODE &p)
{
    char ch;
    File.get(ch);
    if (ch != '#')
    {
        NODE p = new Node;
        p->SetFreq(ch);
        ReadBinaryTree(p->Left());
        ReadBinaryTree(p->Right());
    }
    else return;
}

NODE - это указатель на класс Node, а File - объект ifstream. Left() и Right() возвращают NODE. Компилятор не принимает p->Left() и p->Right(), ошибка:

no know conversion for argument 1 from 'NODE {aka Node*} to 'Node *&

Не могли бы вы помочь мне? Как сохранить указатели на узел во время рекурсии?

  • 5
    Тьфу, не прячь указатели за typedefs!
  • 0
    @LaszloPapp: Это почти наверняка источник беспорядка, который делает жизнь для ОП здесь трудной. Указатели и типы значений имеют разный синтаксис и семантику; очень редко бывает, когда маскировка одного под другого полезна.
Показать ещё 5 комментариев
Теги:
pointers
recursion
arguments
reference

3 ответа

0
Лучший ответ

Проблема в том, что p->Left() и p->Right() являются значениями r, и это означает, что вы не можете ссылаться на них. Проблема возникает из-за того, что p->Left() возвращает некоторое значение (из типа Node *), которое копируется в параметр ReadBinaryTree.

Чтобы исправить это, ваши функции p->Left() и p->Right() должны возвращать NODE & values (чтобы ваша рекурсия имела доступ к тому же самому указателю, что и в родительском узле, а не только в некоторой копии его).

Кроме того, NODE p = new Node; должен быть просто p = new Node; ,

Однако могу ли я предложить преобразовать эту функцию в одну, которая возвращает значение? т.е.

NODE ReadBinaryTree(ifstream &File)
{
    char ch; File.get(ch);
    if(ch != '#')
    {
        NODE p = new Node;
        p->setFreq(ch);
        p->Left() = ReadBinaryTree(File);
        p->Right() = ReadBinaryTree(File);

        return p;
    } else return null;
}

Этот код по-прежнему нуждается в левых и правых аксессуарах для возврата ссылок.

EDIT: Объяснение того, почему ссылки не могут принимать значения r

p->Left() (функция доступа) возвращается копия левого указателя. Поэтому, когда значение совпадает с p->left (атрибут), расположение в памяти отличается, и важно, p->Left() было назначено временное расположение памяти, поскольку это выражение и он ожидал, что переменную "положить в". Обычно, когда вы передаете выражение в функцию, оно "помещается в" параметр, в котором он передается как, но если этот параметр является ссылкой, он ожидает, что там уже будет не временное место памяти, которое оно принимает как свой. Поэтому, когда вы передаете выражение (имеющее временную ячейку памяти) к чему-то ожидающему ссылку, оно жалуется, потому что оно ожидает чего-то с уже фиксированной ячейкой памяти, чтобы оно приняло.

  • 0
    Большое спасибо! Были 2 серьезные логические ошибки! Я изменил свой код, как вы сказали, и теперь он работает, но я не понимаю, почему мне нужно возвращать ссылку на указатель, где хранится адрес ребенка. Почему, когда я вызываю функцию, я передаю простой указатель на Node, но в рекурсии мне нужна ссылка на указатель?
  • 0
    Потому что изначально left и right указатели равны null . Ваша функция должна изменить значение указателя так, чтобы оно указывало на новый созданный вами узел. Это означает, что вам нужно иметь доступ к ссылке на указатель, а не просто к копии указателя. Потому что изменение копии указателя в функции все равно оставило бы дочерние узлы родителя, указывающие на null .
Показать ещё 3 комментария
2

Сделайте так, чтобы Left и Right возвращали ссылки. Вы пытаетесь передать временные значения в ReadBinaryTree, которые не привязываются к ссылке non- const в списке аргументов.

В любом случае ваша рекурсия нарушена, поскольку внутри функции, которую вы используете на локальном NODE p, а не в аргументе. Возможно, вы имели в виду p = new Node; , хотя из этого трудно сказать.

0

ReadBinaryTree нуждается в ссылке на указатель, чтобы он мог обновить указатель, чтобы указать на вновь созданный объект. Проблема в том, что Left() и Right() возвращают только адрес дочерним узлам, но не ссылку на указатель, где хранится адрес.

Таким образом, вы можете изменить подпись Left() и Right():

NODE Left()

чтобы:

NODE & Left()

В качестве альтернативы вы можете напрямую передать указатели, где хранятся дочерние узлы, в ReadBinaryTree:

ReadBinaryTree (p->left)

(Это, естественно, предполагает, что в Node есть элемент, называемый left)

  • 0
    Почему, когда я вызываю функцию, я передаю простой указатель на Node, но в рекурсии мне нужна ссылка на указатель?

Ещё вопросы

Сообщество Overcoder
Наверх
Меню