Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
ПособиеСтруктДанн.doc
Скачиваний:
1
Добавлен:
01.03.2025
Размер:
1.51 Mб
Скачать

Void TopSort(pair *p, int n_pair, file *result){

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

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

// что s1s2

// 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;

}

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