Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Delphi программирование > Паскаль, Turbo Pascal, PascalABC.NET
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 09.11.2014, 16:01   #1
Dvach
Новичок
Джуниор
 
Регистрация: 09.11.2014
Сообщений: 12
По умолчанию Дерево

Доброго времени суток, есть такая проблема: нужно реализовать дерево на паскале, в котором будут звенья с разным количеством указателей в зависимости от количества потомков. Элемент дерева должен иметь тип записи (Record) . Мне не понятно как сделать так чтобы количество полей в записи было не фиксированным(замечу что тут иметься ввиду не нулевые указатели а именно отсутствие указателя). В голову пришла только одна идея это динамический массив внутри записи. Как то так:
Код:
Type
  NodePointer = ^Node;
  Node = record
    data : byte;
    count : integer;
    parent : NodePointer;
    child : array of NodePointer;
  end;
Но при попытке выделить память для типизированного указателя типа NodePointer вылазит ошибка:
Ошибка времени выполнения: Невозможно упаковать тип "ByProCoder.Node" как неуправляемую структуру; невозможно вычислить размер или смещение, имеющие смысл.
Я так полагаю это потому что неизвестно какой объем памяти выделить на динамический массив. Как решить эту проблему?

Последний раз редактировалось Stilet; 09.11.2014 в 16:22.
Dvach вне форума Ответить с цитированием
Старый 09.11.2014, 16:23   #2
Stilet
Белик Виталий :)
Старожил
 
Аватар для Stilet
 
Регистрация: 23.07.2007
Сообщений: 57,097
По умолчанию

Цитата:
звенья с разным количеством указателей в зависимости от количества потомков.
А для чего? Зачем такая динамика? Что там такого хранить будут неожиданного?
I'm learning to live...
Stilet вне форума Ответить с цитированием
Старый 09.11.2014, 16:53   #3
Dvach
Новичок
Джуниор
 
Регистрация: 09.11.2014
Сообщений: 12
Печаль

Цитата:
Сообщение от Stilet Посмотреть сообщение
А для чего? Зачем такая динамика? Что там такого хранить будут неожиданного?
Это лабораторная , не я это придумал. Просто нужно реализовать такую структуру.
Конечно проще делать нулевые указатели , если у узла нет потомков , но в задании надо сделать так чтобы таких указателей вообще не было...

http://pixs.ru/showimage/shemapng_2013252_14653489.png
вот схема такого дерева для примера

Последний раз редактировалось Stilet; 09.11.2014 в 18:06.
Dvach вне форума Ответить с цитированием
Старый 09.11.2014, 18:12   #4
Stilet
Белик Виталий :)
Старожил
 
Аватар для Stilet
 
Регистрация: 23.07.2007
Сообщений: 57,097
По умолчанию

А-ля файловая структура... Ну тогда и FAT для такого нужно выдумывать.
Я бы наверное в каждой ветке сделал поля указателя на данные, размер этих данных и их тип. А потом бы описал методы считывания по указателю этих данных и конвертирования во что-то в зависимости от содержимого поля типа.
На пальцах наверное не расскажешь...
Код:
Type
  NodePointer = ^Node;
  Node = record
    data : pointer;
    count : integer;
    TypeOfData:byte;
    parent, //Это указатель на родителя
    children, // Это указатель на список детей
    Sibling :NodePointer; //Это указатель на следующий элемент в этом списке
  end;
Т.е. NodePointer это не просто указатель а голова списка.
И так получится список списков с данными неопределенного типа
I'm learning to live...
Stilet вне форума Ответить с цитированием
Старый 09.11.2014, 18:23   #5
Dvach
Новичок
Джуниор
 
Регистрация: 09.11.2014
Сообщений: 12
По умолчанию

Не совсем понятно что имееться ввиду , но насколько я понял вы добавили указатель еще на следующий элемент на этом же уровне дерева (брат) , это противоречит варианту задания. Вот условие более подробно:
Каждая вершина содержит следующие поля:
- поле данных;
- поле, в котором указано число координирующих вспомагательных полей;
- вспомагательное поле, содержащее указатель на вершину более высокого уровня (предыдущую вершину). Для корневой вершины в него заносится значение NIL;
- вспомагательные поля, содержащие указатели на вершины нижнего уровня (у листьев - отсутствуют).
Если с текущей вершиной не связаны вершины нижнего уровня, то соответствующие вспомогательные поля отсутствуют

То есть должен быть только указатель на родителя , и указатели на потомков, причем число указателей на потомков должно "растягиваться". "Головы" списка не должно быть, все потомки должны быть равнозначны. Родитель должен указывать не на один "главный" потомок а на каждого отдельно(несколько указателей по числу потомков), как изображено на схеме в моем посте выше.

Последний раз редактировалось Dvach; 09.11.2014 в 18:44.
Dvach вне форума Ответить с цитированием
Старый 09.11.2014, 18:52   #6
Stilet
Белик Виталий :)
Старожил
 
Аватар для Stilet
 
Регистрация: 23.07.2007
Сообщений: 57,097
По умолчанию

Цитата:
вспомагательные поля, содержащие указатели на вершины нижнего уровня
Пичальная какашка...
Ладно. Пусть будет array of NodePointer.
Смысл собственно в описании данных. Вот я и предлагаю их представить нетипированно, но с указанием как именно их понимать.
I'm learning to live...
Stilet вне форума Ответить с цитированием
Старый 09.11.2014, 18:54   #7
Utkin
Старожил
 
Аватар для Utkin
 
Регистрация: 04.02.2009
Сообщений: 17,351
По умолчанию

Самый простой вариант - уйти от ссылок. Все узлы элементы динамического массива. Начинается от глобального корневого узла, который недоступен конечному пользователю. Его потомки будут считаться корневыми узлами. Такое проектирование дерева поможет избежать многих проблем, главная из которых утечка памяти при работе с указателями.
В случае использования только динамических массивов в Вашем рекорде count становится не нужным...
Цитата:
вот схема такого дерева для примера
Примитивизм. Отделите реализацию от модели. Иначе долго будете искать баги.
Маньяк-самоучка
Utkin появился в результате деления на нуль.
Осторожно! Альтернативная логика
Utkin вне форума Ответить с цитированием
Старый 09.11.2014, 18:57   #8
Dvach
Новичок
Джуниор
 
Регистрация: 09.11.2014
Сообщений: 12
По умолчанию

Вот мне тоже нравиться идея с динамачиным массивом, но как выделить память для указателя на record если в нем есть динамический массив размер которого на данном этапе еще неизвестен, я ведь не могу выделить память под массив до того как выделю память для записи.
"Ошибка времени выполнения: Невозможно упаковать тип "ByProCoder.Node" как неуправляемую структуру; невозможно вычислить размер или смещение, имеющие смысл. "

Последний раз редактировалось Dvach; 09.11.2014 в 19:04.
Dvach вне форума Ответить с цитированием
Старый 09.11.2014, 19:03   #9
Utkin
Старожил
 
Аватар для Utkin
 
Регистрация: 04.02.2009
Сообщений: 17,351
По умолчанию

Цитата:
Вот мне тоже нравиться идея с динамачиным массивом, но как выделить память для указателя на record если в нем есть динамический массив размер которого на данном этапе еще неизвестен, я ведь не могу выделить память под массив до того как выделю память для записи.
Значит надо выделить после. Если такая вещь называется инициализация. Просто подготовите функцию, которая и будет выполнять работу с выделением памяти под динамический массив нужного размера. Для примера:
1. Начальная инициализация
SetLength(массив, размер) - установите размер в нуль, уничтожите все данные.
2. Добавить элемент в конец:
Код:
count:=Length(массив);
Inc(count);
SetLength(Массив, count);
3. Удаление элемента
а) Копируете последний элемент в тот который должен быть удален
б) Уменьшаете динамический массив на единицу
Код:
Dec(count);
SetLength(Массив, count);
Это говорит, о том, что Вам нужна еще одна сущность - глобальный идентификатор, поскольку элементы в массиве могут "плавать" независимо от желаний того, кто будет пользоваться Вашим деревом. Чтобы однозначно определять узел должен быть идентификатор независимый от индекса узла в динамическом массиве. Подумайте над этим.
Маньяк-самоучка
Utkin появился в результате деления на нуль.
Осторожно! Альтернативная логика
Utkin вне форума Ответить с цитированием
Старый 09.11.2014, 19:14   #10
Dvach
Новичок
Джуниор
 
Регистрация: 09.11.2014
Сообщений: 12
По умолчанию

Цитата:
Сообщение от Utkin Посмотреть сообщение
Значит надо выделить после. .
1) Нельзя после, так ошибка при выделении памяти под типизированный указатель (размер динамического массива внутри не опеределен)
2) Ну про SetLength я знаю , вот только где мне выделять память под массив? в отдельной функции? и как мне передать указатель в record. Это ведь не экземпляр класса и я не могу вызвать конструктор при выделении памяти под узел.
Я конечно могу описать узел как объект а не запись но это уже не совсем то что требуется в задании.
Dvach вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Дерево на C# No_Comments Помощь студентам 8 26.04.2013 21:22
Дерево Тюха Visual C++ 0 23.05.2011 18:50
Я дерево Кукла_колдуна Паскаль, Turbo Pascal, PascalABC.NET 0 20.03.2011 23:07
Дерево Ikram Помощь студентам 0 05.05.2010 19:42
дерево С# Natok Помощь студентам 0 14.09.2009 23:42