Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Практикум по программированию на языке программирования Си..pdf
Скачиваний:
20
Добавлен:
05.02.2023
Размер:
1.39 Mб
Скачать

98

5.Если это ИЛИ­узел, то определяется единственный сын и номер ва­ рианта для соответствующего поддерева (см. 2.12 для определения сына и номера варианта для ИЛИ­узла).

6.Происходит переход на рассмотрение следующего узла из списка включенных в данный вариант подстановок.

7.Процесс определения варианта подстановок будет происходить до тех пор, пока не будут достигнуты листья для всех рассматриваемых узлов варианта подстановок.

На рис. 8.4 показаны все варианты для дерева И/ИЛИ, приведенного в разделе 2.7.4.

Рис. 8.4 — Все варианты для примера И/ИЛИ дерева

8.4 Программная реализация

В основе программной реализации лежит контейнер древовидного списка (см. раздел «Организация древовидного списка»). Перечислим константы:

Тип узла И

#define AND_NODE 1

Типа узла ИЛИ

#define OR_NODE 2

Описание структуры узда дерева И­ИЛИ

99

typedef struct{

//описание узла

int type;

//тип узла

int var;

//количество вариантов

void* data;

//данные

} KruAOTreeNode;

Описание структуру дерева И­ИЛИ

typedef struct{

//заголовок дерева

NodeTreeList *root; //корень

int size;

//кол­во узлов

int var;

//кол­во вариантов

} KruAOTree;

 

Функция инициализация структуры дерева И­ИЛИ

void InitKruAOTree(KruAOTree *aot){ aot­>root=NULL;

aot­>size=0;

aot­>var=0;

}

Функция создание узла дерева

KruAOTreeNode* CreateKruAOTreeNode(int type,void* data){ KruAOTreeNode *n=new KruAOTreeNode;

if(n==NULL) return NULL; n­>var=0;

n­>data=data;

n­>type=type; return n;

}

Функция вывода узла дерева И­ИЛИ в случае, когда по указателю data хранится строка символов

void OutputKruAOTreeNode(void *n){

printf("%d %d %s\n",((KruAOTreeNode*)n)­>type,((KruAOTreeNode*)n)­ >var,(char*)((KruAOTreeNode*)n)­>data);

//printf("%s\n",(char*)((KruAOTreeNode*)n)­>data);

100

}

Функция удаления узла дерева И­ИЛИ в случае, когда по указателю data хранится строка символов

void DeleteKruAOTreeNode(void *n){ delete []((KruAOTreeNode*)n)­>data; delete (KruAOTreeNode*)n;

}

Функция создания узла дерева И­ИЛИ по описанию в name. Структу­ ра name должна быть следующей:

<Символ типа узла><строка> <Символ типа узла> может быть

1)A — для И­узла;

2)O — для ИЛИ­узла.

Эта функция используется при трансляции скобочной записи дерева в древовидный список

void* CreateKruAOTreeNode(char *name){ KruAOTreeNode *n=new KruAOTreeNode; if(n==NULL) return NULL; if(*name=='A') n­>type=AND_NODE; else n­>type=OR_NODE;

n­>var=0;

char *s=new char[strlen(&name[1])+1]; strcpy(s,&name[1]);

n­>data=s; return n;

}

Функция рекурсивного подсчета вариантов в дереве И­ИЛИ

int CountVarAOTree(NodeTreeList *node){ KruAOTreeNode *d;

int res;

if(node==NULL) return 0; d=(KruAOTreeNode*)node­>data; if(node­>down!=NULL){ NodeTreeList *t=node­>down;

101

if(d­>type==AND_NODE) res=1; else res=0; //установить начальные зна­ чения для res

while(t!=NULL){ //для всех сыновей if(d­>type==AND_NODE)

res=res*CountVarAOTree(t); //рекурсивный подсчет для узла И else res=res+CountVarAOTree(t); //рекурсивный подсчет для узла ИЛИ t=t­>right;

}

}

else res=1; //это лтст

d­>var=res; //установить значение var для данного узла return res;

}

Функция обхода узлов варианта с заданным номером, node — корень дерева, number номер варианта, func — указатель на функцию обработки узла. Функция работает по алгоритму перечисления вариантов дерева И­ ИЛИ

void ForEachVarAOTree(NodeTreeList *node, int number, void (*func)(void*))

{

KruAOTreeNode *d; int res; if(node==NULL) return;

d=(KruAOTreeNode*)node­>data; if(func!=NULL) func(d); //вызов функции if(node­>down!=NULL){

NodeTreeList *t=node­>down; if(d­>type==AND_NODE) res=1; else res=0; while(t!=NULL){

KruAOTreeNode *td=(KruAOTreeNode*)t­>data; if(d­>type==AND_NODE){ //для всех И­узлов ForEachVarAOTree(t,number%td­>var,func); number/=td­>var;

}

else { //для одного ИЛИ­узла

if(number<td­>var) { ForEachVarAOTree(t,number,func); break;} number­=td­>var;

}

t=t­>right;

}

}

102

}

Функция обхода узлов и обработки листьев варианта с заданным но­ мером, node — корень дерева, number номер варианта, func — указатель на функцию обработки листа. Функция работает по алгоритму перечисления вариантов дерева И­ИЛИ.

void ForEachVarAOTreeLeaf(NodeTreeList *node, int number, void (*func) (void*)){

KruAOTreeNode *d; int res; if(node==NULL) return;

d=(KruAOTreeNode*)node­>data; if(node­>down==NULL){ //это лист

if(func!=NULL) func(d); //вызов функции

}

else {

NodeTreeList *t=node­>down; if(d­>type==AND_NODE) res=1; else res=0; while(t!=NULL){

KruAOTreeNode *td=(KruAOTreeNode*)t­>data; if(d­>type==AND_NODE){ //для всех И­узлов ForEachVarAOTree(t,number%td­>var,func); number/=td­>var;

}

else { //для одного ИЛИ­узла

if(number<td­>var) { ForEachVarAOTreeLeaf(t,number,func); break;} number­=td­>var;

}

t=t­>right;

}

}

}

Тестовая функция для показа организации и работы с деревьями И­

ИЛИ

void TestKruAOTree(){

// конструирование дерева

TranslateStateTreeList tsv; //создаем структуру InitTranslateStateTreeList(&tsv,20,CreateKruAOTreeNode); //инициализиру­ ем

103

//трансляция описание дерева И_ИЛИ (см. рис) // в древовидный список

NodeTreeList *ao_tree=TranslateAscizToTreeList(&tsv, "A1._node­1\

(O1.1_node­2(\ A1.1.1_node­4,\ O1.1.2._node_5(\ A1.1.2.1_node­9,\ O1.1.2.2._node_10),\ A1.1.3_node­6),\ O1.2_node­3(\ A1.2.1_node­7,\ A1.2.2_node­8)");

//подсчет количества вариантов int nvar=CountVarAOTree(ao_tree); printf("++++ var =%d\n",nvar);

//левосторонний обход дерева И­ИЛИ печать узлов

ForEachTreeListLeftNode(ao_tree,OutputKruAOTreeNode); printf("+++++++++++++++++\n");

//левосторонний обход дерева И­ИЛИ печать листьев

ForEachTreeListLeftLeaf(ao_tree,OutputKruAOTreeNode); //перечисление вариантов в дереве и печать

for(int num=0; num<nvar; num++){ ForEachVarAOTree(ao_tree,num,OutputKruAOTreeNode); printf("________%d\n",num);

}

//очищение динамической памяти

DeleteTranslateStateTreeList(&tsv); DeleteSubTreeList(ao_tree,DeleteKruAOTreeNode);

while(!kbhit());

}

Листинг работы тестовой программы

++++ var =8

1 8

1._node­1

2 4

1.1_node­2

1 1

1.1.1_node­4

2 2

1.1.2._node_5

1 1

1.1.2.1_node­9

104

2 1

1.1.2.2._node_10

1 1

1.1.3_node­6

2 2

1.2_node­3

1 1

1.2.1_node­7

1 1

1.2.2_node­8

+++++++++++++++++

1 1

1.1.1_node­4

1 1

1.1.2.1_node­9

2 1

1.1.2.2._node_10

1 1

1.1.3_node­6

1 1

1.2.1_node­7

1 1

1.2.2_node­8

1 8

1._node­1

2 4

1.1_node­2

1 1

1.1.1_node­4

2 2

1.2_node­3

1 1

1.2.1_node­7

________0

1 8

1._node­1

2 4

1.1_node­2

2 2

1.1.2._node_5

1 1

1.1.2.1_node­9

2 2

1.2_node­3

1 1

1.2.1_node­7

________1

1 8

1._node­1

2 4

1.1_node­2

2 2

1.1.2._node_5

2 1

1.1.2.2._node_10

2 2

1.2_node­3

1 1

1.2.1_node­7

________2

1 8

1._node­1

2 4

1.1_node­2

1 1

1.1.3_node­6

2 2

1.2_node­3

1 1

1.2.1_node­7

________3

1 8

1._node­1

2 4

1.1_node­2

1 1

1.1.1_node­4