Акинатор — задача сложная: там и «большие данные», и вопросы, уточняющие информацию о герое и позволяющие вписать его в стандартную матрицу, и прочее. Но это офтоп, о дереве.
Таким образом, задача — хранить дерево в файле с возможностью считать его в том же виде, как и записано.
В боевой программе я бы посоветовал использовать XML или его двоичный аналог.
<node question="У него есть колёса?">
<yes><answer value="наркоман" /></yes>
<no><node question="Он живёт в лесу?">…</node></no>
</node>
От двоичного аналога требуется работать с блоками (микропотоками внутри большого файла) и с директориями.
Если считать, что наша XML-библиотека работает методом дописывания тэгов в конец файла, будет такой код записи (считаем, что код объектно-ориентированный, с классами Развилка и Ответ, поддерживающими интерфейс Узел).
функ записатьФайл(xml : XmlПисатель)
xml.записатьЗаголовок
xml.открытьТэг("tree")
дерево.корень.записатьXml(xml)
xml.закрытьТэг("tree")
функ Развилка.записатьXml(xml : XmlПисатель)
xml.открытьТег("node")
xml.атрибут("question", вопрос)
xml.открытьТэг("yes")
да.записатьXml(xml)
xml.закрытьТэг("yes")
xml.открытьТэг("no")
нет.записатьXml(xml)
xml.закрытьТэг("no")
xml.закрытьТэг("node")
функ Ответ.записатьXml(xml : XmlПисатель)
xml.открытьТег("answer")
xml.атрибут("value", результат)
xml.закрытьТэг("answer")
Чтение будет такое (считаем, что читатель потоковый, автоматически пропускает всё внутри тэга, если не дать команду «войти в тэг», в закончившемся тэге ничего не выводит, пока не дать команду «выйти из тэга», и нет никаких препятствий к тому, чтобы собирать дерево в отрыве от корня).
функ считатьУзел(xml : XmlЧитатель) : узел
тэг := xml.считатьТэг
в_зависимости_от (тэг)
если "node":
узел := новый Развилка
узел.вопрос = …
xml.войтиВТэг
xml.затребоватьТэг("yes")
xml.войтиВТэг
узел.да = считатьУзел(xml)
xml.выйтиИзТэга
xml.затребоватьТэг("no")
xml.войтиВТэг
узел.нет = считатьУзел(xml)
xml.выйтиИзТэга
xml.выйтиИзТэга
верни узел
если "answer":
узел := новый Ответ
узел.результат = …
верни узел
иначе:
ошибка
функ Дерево.считатьXml(xml : XmlЧитатель)
xml.затребоватьТэг("tree")
xml.войтиВТэг
узел := считатьУзел(xml)
xml.выйтиИзТэга
установитьКорень(узел)
В учебной задаче — пометить каждый узел (вопрос или ответ), примерно так.
Q
У него есть колёса?
A
наркоман
Q
Он живёт в лесу?
…
Опять-таки, возможен двоичный аналог. Код точно такой же, только команды «войти/выйти» не нужны.
Ах да. У вас в тэгах написано «Си». Скажите хоть, каким образом вы налаживаете указатели на два разных типа узлов (ответы и развилки), и мы придумаем, как это сделать. Например, если ответ — это та же развилка, только без обоих сыновей…
функ записатьXml(xml, узел)
если узел.да≠⌀ и узел.нет≠⌀
ветвь_для развилки
иначе если узел.да=⌀ и узел.нет=⌀
ветвь_для_ответа
иначе ошибка