ЗАДАНИЕ XXXV

Тема: Операции с деревьями.
Цель: Знакомство с деревьями в среде Stratum .

Для работы необходимо:

уметь работать с клавиатурой и мышкой
владеть основными приемами работы в Stratum 2000
владеть основными приемами использования языка Stratum

Основные сведения о деревьях.

    Деревья, как и динамические массивы, представляют собой хранилища данных, которые могут менять в ходе работы свою структуру. Главной особенностью дерева является то, что оно позволяет представлять информацию в иерархическом виде. Информация хранится в узлах, обращаться к которым можно с помощью уникальных индексов. В узлах деревьев хранящаяся информация может быть произвольного типа, как и в динамических массивах.

    Механизм деревьев поддерживается с помощью набора специальных функций. Они позволяют производить с деревьями все необходимые манипуляции.

Создание дерева
    Для создания нового дерева используется функция CreateTree().Функция возвращает дескриптор дерева, с помощью которого к нему осуществляется в дальнейшем доступ.

Удаление дерева
    Дерево удаляется с помощью функции DeleteTree(). Для корректности следует удалять только пустые деревья, не содержащие ни одного узла.

Добавление узла в дерево
    Для добавления узла в дерево применятся функция TreeAddRec(). Ей необходимо указывать, к какому существующему узлу добавляется новый и тип структуры добавляемого узла. Индекс добавляемого узла должен быть уникальным и отличным от нуля. В противном случае добавления не произойдет.
Замечание
: в описании структуры, используемой в качестве узла, всегда должна присутствовать переменная HANDLE point. В ходе работы с деревом запрещено менять значение этой переменной в узлах, так как это может привести к непредсказуемым последствиям.

Удаление ветви дерева
Для удаления ветви дерева используется функция
TreeDeleteBranch(). Она удаляет выбранный узел со всеми его подузлами. Если указать корневой узел дерева, то получится пустое дерево.

Изменение значения поля в узле
После добавления узла в дерево все его поля имеют нулевое значение. Для того, чтобы их изменить, имеются функции
TreeSetFieldF(), TreeSetFieldS() и TreeSetFieldH(). Они изменяют, соответственно, поля типа FLOAT, STRING и HANDLE. Как уже было сказано выше, изменять поле “point” запрещено.

Получение значения поля в узле
Для получения значения поля в узле используются функции
TreeGetFieldF(), TreeGetFieldH() и TreeGetFieldS().

Нахождение вышестоящего узла
Для каждого узла, за исключением корневого, существует вышестоящий. Для того, чтобы найти вышестоящий узел, используется функция
TreeUpRec().

Нахождение нижестоящих узлов
Для этого используется функция
TreeDownRec(). Она возвращает массив, в котором содержатся индексы вершин, лежащих ниже по отношению к указанной. Если узел не имеет нижележащих вершин, то массив - пустой.

Изменение индекса узла
В случае необходимости можно при помощи функции
TreeUpdateInd() изменить индекс узла. При этом новый индекс должен быть тоже уникальным и отличным от нуля.

Просмотр деревьев
Непосредственно деревья просмотреть системными средствами среды
Stratum нет возможности. Но так как они представляют собой совокупности динамических массивов, то возможно просмотреть деревья, используя средства для массивов. Для того, чтобы найти узел с заданным индексом, надо:

  1. Нажать на кнопку “Информация о системе
  2. В разделе “Динамические массивы” найти массив с дескриптором, соответствующим дескриптору дерева.
  3. Посмотреть значение первой записи в этом массиве. Это будет дескриптор массива, содержащего индексы дерева.
  4. Перейти к массиву индексов и найти там элемент с полем Key, значение которого совпадает с искомым. Запомнить значение полей “Mas” и “Zap”.

Найти динамический массив с дескриптором, равным Mas и его Zap-й элемент (нумерация в массивах начинается с нуля). Данный элемент и будет искомым узлом.


Задание 1.

Заполнение дерева информацией о блоках, входящих в состав ПК

    Создадим новый проект. Теперь опишем структуру узла дерева.
Для этого создадим новый имидж с именем
Struct. Текст его будет иметь вид:

HANDLE Point // Дескриптор массива верхнего уровня
STRING Name // Название блока
FLOAT Cost // Цена блока

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

Далее создадим новый имидж, который будет создавать и заполнять дерево. Текст его следующий:

HANDLE Tree
FLOAT ret

Tree := CreateTree()
ret := TreeAddRec(~Tree,0,1,"Struct") // Добавляем корень дерева
ret := TreeSetFieldS(~Tree,1,"Name",“ПК”) // Заполняем
ret := TreeSetFieldF(~Tree,1,"Cost",1000) // корневой узел
ret := TreeAddRec(~Tree,1,2,"Struct") // Добавляем узел к корню
ret := TreeSetFieldS(~Tree,2,"Name",“Системный блок”) // Заполняем узел
ret := TreeSetFieldF(~Tree,2,"Cost",500) // информацией о системном блоке
ret := TreeAddRec(~Tree,1,3,"Struct") // Добавляем узел к корню
ret := TreeSetFieldS(~Tree,3,"Name",“Монитор”) // Заполняем узел
ret := TreeSetFieldF(~Tree,3,"Cost",400) // информацией о мониторе
ret := TreeAddRec(~Tree,1,4,"Struct") // Добавляем узел к корню
ret := TreeSetFieldS(~Tree,4,"Name",“Клавиатура”) // Заполняем узел
ret := TreeSetFieldF(~Tree,4,"Cost",80) // информацией о клавиатуре
ret := TreeAddRec(~Tree,1,5,"Struct") // Добавляем узел к корню
ret := TreeSetFieldS(~Tree,5,"Name",“Мышь”) // Заполняем узел
ret := TreeSetFieldF(~Tree,5,"Cost",20) // информацией о мыши

_disable := 1 // Отключение имиджа

    Запустите проект. После этого посмотрите значение переменной Tree и по этому значению убедитесь в существовании дерева.

 

Задание 2

Поиск в дереве и преобразование его структуры

    Создадим новый имидж, который позволяет искать и выводить информацию из узлов в дереве и преобразовывать его.
Текст следующий:

HANDLE Tree,Mas
STRING NameBlock // Имя блока, информация по которому ищется
FLOAT i,ok,index

if (~Tree != #0) // Если дерево существует
Mas := TreeDownRec(~Tree, 1) // Ищем все узлы, которые находятся
                                                    // непосредственно под корневым

i := 0
ok := 0
while ((~i < vGetCount(~Mas))&&not(~ok)) // Просматриваем массив
  index := vGetF(~Mas,~i,"") // Индекс узла
  if (vGetFieldS(~Tree,~index,"Name") == ~NameBlock)
   ok := 1
   // Выводим результат поиска
   MessageBox("Цена: "+string(vGetFieldF(~Tree,~index,"Cost")),"",mb_ok)
  endif
  i := ~i + 1
endwhile

if (not(~ok)) // Если узел не найден
  // Сообщаем, что такого блока нет
  MessageBox("Блок с именем "+~NameBlock+" не найден","",mb_ok)
endif

// Далее удаляем дерево
ret := TreeDeleteBranch(~Tree,1) // Удаляем корневой узел вместе с подузлами
ret := DeleteTree
endif

Далее необходимо в свойствах имиджа установить значение переменной NameBlock (например, “Монитор”). После этого имидж нужно соединить связью с созданным ранее и связать переменные Tree в них.

Теперь можно запустить проект и на экране должно появиться окно, где сообщается результат поиска.