У меня проблема с этой рекурсивной функцией 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 *&
Не могли бы вы помочь мне? Как сохранить указатели на узел во время рекурсии?
Проблема в том, что 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()
было назначено временное расположение памяти, поскольку это выражение и он ожидал, что переменную "положить в". Обычно, когда вы передаете выражение в функцию, оно "помещается в" параметр, в котором он передается как, но если этот параметр является ссылкой, он ожидает, что там уже будет не временное место памяти, которое оно принимает как свой. Поэтому, когда вы передаете выражение (имеющее временную ячейку памяти) к чему-то ожидающему ссылку, оно жалуется, потому что оно ожидает чего-то с уже фиксированной ячейкой памяти, чтобы оно приняло.
left
и right
указатели равны null
. Ваша функция должна изменить значение указателя так, чтобы оно указывало на новый созданный вами узел. Это означает, что вам нужно иметь доступ к ссылке на указатель, а не просто к копии указателя. Потому что изменение копии указателя в функции все равно оставило бы дочерние узлы родителя, указывающие на null
.
Сделайте так, чтобы Left
и Right
возвращали ссылки. Вы пытаетесь передать временные значения в ReadBinaryTree
, которые не привязываются к ссылке non- const
в списке аргументов.
В любом случае ваша рекурсия нарушена, поскольку внутри функции, которую вы используете на локальном NODE p
, а не в аргументе. Возможно, вы имели в виду p = new Node;
, хотя из этого трудно сказать.
ReadBinaryTree
нуждается в ссылке на указатель, чтобы он мог обновить указатель, чтобы указать на вновь созданный объект. Проблема в том, что Left()
и Right()
возвращают только адрес дочерним узлам, но не ссылку на указатель, где хранится адрес.
Таким образом, вы можете изменить подпись Left()
и Right()
:
NODE Left()
чтобы:
NODE & Left()
В качестве альтернативы вы можете напрямую передать указатели, где хранятся дочерние узлы, в ReadBinaryTree
:
ReadBinaryTree (p->left)
(Это, естественно, предполагает, что в Node
есть элемент, называемый left
)