русс | укр

Языки программирования

ПаскальСиАссемблерJavaMatlabPhpHtmlJavaScriptCSSC#DelphiТурбо Пролог

Компьютерные сетиСистемное программное обеспечениеИнформационные технологииПрограммирование

Все о программировании


Linux Unix Алгоритмические языки Аналоговые и гибридные вычислительные устройства Архитектура микроконтроллеров Введение в разработку распределенных информационных систем Введение в численные методы Дискретная математика Информационное обслуживание пользователей Информация и моделирование в управлении производством Компьютерная графика Математическое и компьютерное моделирование Моделирование Нейрокомпьютеры Проектирование программ диагностики компьютерных систем и сетей Проектирование системных программ Системы счисления Теория статистики Теория оптимизации Уроки AutoCAD 3D Уроки базы данных Access Уроки Orcad Цифровые автоматы Шпаргалки по компьютеру Шпаргалки по программированию Экспертные системы Элементы теории информации

Int count; // счетчик числа элементов, предшествующих


Дата добавления: 2015-01-16; просмотров: 578; Нарушение авторских прав


//данному

char name[40]; // имя элемента

MAINS *llink; // связи двусвязного списка

MAINS *rlink;

struct POD *pod; // указатель на подсписок

};

struct POD { // структура узла подсписка

POD *next;// следующий узел подсписка

MAINS *m; // указатель на узел основного списка

};

 

Алгоритм имеет три фазы:

Первая фаза – первоначальное построение списочной структуры. Проходим массив пар, и для каждого элемента множества, который ещё не включен в список, создаем узел и помещаем его в хвост основного списка. Для каждой пары first, second в подсписок узла firstпомещаем узел, в поле m которого помещаем ссылку на узел основного списка second. Счетчик count узла second увеличиваем на единицу. После завершения первой фазы узел каждого элемента содержит число элементов, предшествующих данному. На рис.19 изображено состояние основного списка после завершения первой фазы для массива пар

 
 

предшество­вания

Рис 19. Топологическая сортировка. 1 фаза.

 

Вторая фаза – создание списка ведущих элементов. Список ведущих имеет такую же структуру, что и основной список. Проходя основной список слева направо, узлы, имеющие поле счетчика, равное нулю, пере­носим в список ведущих элементов. Этим элементам ничто не предшест­вует, и они первыми будут выведены в выходную последовательность.

Третья фаза – построение выходной последовательности. Проходим список ведущих и его элементы помещаем в выходную последователь­ность и удаляем из списка ведущих. Проходя подсписок выводимого в результат элемента, уменьшаем на единицу поле счетчика того элемента основного списка, на который ссылается поле m подсписка. Действительно, после вывода элемента списка ведущих в результирующую последовательность, он уже не предшествует оставшимся в основном списке элементам. Если поле счетчика окажется равным нулю, переносим его в хвост списка ведущих.



Если отношение предшествования было задано корректно, то все элементы будут выведены и основной список опустеет. Если же основной список по завершении третьей фазы не пуст, то это говорит о противоречивом задании частичного порядка. Например, частичный порядок

a í b; b í c; c í a

противоречив.

Ниже приведен текст функции, реализующей топологическую сортировку:

void TopSort(PAIR *p, int n_pair, FILE *result){

// p - массив пар указателей на имена элементов

// Наличие пары s1,s2 означает,

// что s1ís2

// n_pair - число таких пар

// result - файл, в который помещаются результаты

MAINS *mhead; // голова основного списка

MAINS *vhead; // голова списка ведущих элементов

MAINS *u1,*u2,*v,*w;

int i;

POD *x,*y;

// создание основного списка

mhead=new MAINS;

mhead->llink=mhead;

mhead->rlink=mhead;

// проход по всем парам

for(i=0; i<n_pair; i++){

// найдем или создадим элемент по имени p[i].first

u1=FindU(mhead,p[i].first);

// найдем или создадим элемент по имени p[i].second

u2=FindU(mhead,p[i].second);

// u1 предшествует u2, поэтому к счетчику u2 прибавим 1

u2->count++;

// в подсписок u1 добавим узел, указывающий на u2

x=new POD;

x->next=u1->pod;

u1->pod=x;

x->m=u2;

}

// создание списка ведущих

vhead=new MAINS; // голова

vhead->llink=vhead->rlink=vhead;

// проходим по основному списку и узлы с полем счетчика ==0

// переносим в список ведущих

for(v=mhead->rlink; v!=mhead; v=w){

w=v->rlink;

if(v->count==0){

// переносим в хвост списка ведущих

AddToTail(vhead,v);

}

}

// проход по списку ведущих

for(v=vhead->rlink; v!=vhead; v=v->rlink){

// имя элемента печатаем в файл результата

fprintf(result," \"%s\",\n",v->name);

// проходим по подсписку и уменьшаем на 1 поле счетчика

// в узлах основного списка, на которые ссылаются узлы

// подсписка

for(x=v->pod,y=x->next; x!=NULL; x=y){

y=x->next;

x->m->count--;

if(x->m->count==0){

// если счетчик==0, то переносим узел из основного

// списка в конец списка ведущих

AddToTail(vhead,x->m);

}

// узлы подсписка больше не понадобятся

delete x;

}

// узлы списка ведущих тоже больше не нужны

delete v;

}

delete vhead;

// осталось ли что-нибудь в основном списке ?

// если осталось, то это говорит о противоречивом

// задании предшествования и список содержит кольца

// элементов множества

// в любом случае надо все освободить

if(mhead->rlink!=mhead){

fprintf(result,"Список функций, образующих рекурсивные цепи\n");

for(v=mhead->rlink; v!=mhead; v=v->rlink){

fprintf(result,"%3d %s\n",v->count, v->name);

for(x=v->pod,y=x->next; x!=NULL; x=y){

y=x->next;

delete x;

}

delete v;

}

}

delete mhead;

}

 

Рассмотренный алгоритм использует две вспомогательные функции:

 

MAINS *FindU(MAINS *head, char *WhatToFind){

MAINS *v;

// Функция либо находит в основном списке с головой head

// узел с элементом по имени WhatToFind, либо создает его

// В любом случае возвращается указатель на узел с

// элементом по имени WhatToFind

// ищем, и если найдем, вернем указатель

for(v=head->rlink; v!=head; v=v->rlink){

if(strcmp(WhatToFind,v->name)==0){

return v;

}

}

// не нашли - создаем

v=new MAINS;

strcpy(v->name,WhatToFind);

v->count=0;

v->pod=NULL;

v->rlink=head;

v->llink=head->llink;

head->llink->rlink=v;

head->llink=v;

return v;

}

//-------------------------------------

void AddToTail(MAINS *head, MAINS *v){

// изъять узел v из основного списка и вставить

// в хвост списка ведущих с головой head

// удаляем из того списка, в котором он сейчас находится

v->llink->rlink=v->rlink;

v->rlink->llink=v->llink;

// помещаем слева от head

v->rlink=head;

v->llink=head->llink;

head->llink->rlink=v;

head->llink=v;

}

 



<== предыдущая лекция | следующая лекция ==>
Списки общего вида | Стек свободного пространства


Карта сайта Карта сайта укр


Уроки php mysql Программирование

Онлайн система счисления Калькулятор онлайн обычный Инженерный калькулятор онлайн Замена русских букв на английские для вебмастеров Замена русских букв на английские

Аппаратное и программное обеспечение Графика и компьютерная сфера Интегрированная геоинформационная система Интернет Компьютер Комплектующие компьютера Лекции Методы и средства измерений неэлектрических величин Обслуживание компьютерных и периферийных устройств Операционные системы Параллельное программирование Проектирование электронных средств Периферийные устройства Полезные ресурсы для программистов Программы для программистов Статьи для программистов Cтруктура и организация данных


 


Не нашли то, что искали? Google вам в помощь!

 
 

© life-prog.ru При использовании материалов прямая ссылка на сайт обязательна.

Генерация страницы за: 0.008 сек.