O codigo deste post recebe um conjunto de tarefas com ordem parcial e imprime na tela uma ordem possivel de execucao das tarefas.Por exemplo, se temos um conjunto cujas tarefas sao vestir cada peca de roupa, a seguinte ordem parcial pode ser formulada, onde uma peca so pode ser vestida depois que as pecas sobre as quais ela se apoia (no desenho) ja foram vestidas. O desenho mostra, por exemplo, que nao podemos calcar os sapatos sem antes ter colocado as meias e a calca.Existem varias ordens lineares para se vestir que obedecem a ordem topologica acima. A saida do codigo abaixo mostra uma das ordem possiveis. Por exemplo:Meias, roupa intima, camisa, calca, sapatos, cinto, luvas, casaco e chapeu.No final do codigo, temos uma analise da complexidade do algoritmo, mostrando que este algoritmo e quadratico na entrada. O livro propoe um algoritmo linear, que, para ser alcancado, requer uma modificacao sutil no algoritmo (ver aula 3)./*** MAC 2301 - Laboratorio de Programacao** Exercicio da aula 2** Assunto: Lista ligada* Aplicacao: ordenacao topologica** O que e "ordem topologica"?* E uma ordem parcial.* Os inteiros possuem uma ordem "total", ja que todos os elementos sao* comparaveis entre si). Ja as tarefas para se construir uma casa possuem* apenas uma ordem parcial, porque nem todos os elementos vem necessariamente* um antes ou depois do outro. Assim: a fundacao deve ser feita antes de* tudo. Entao entre a fundacao e a pintura ha uma ordem: fundacao < pintura* Mas entre a pintura e a colocacao do piso, nao ha uma ordem fixa. Com isso,* ha varias ordem possiveis em que uma casa pode ser montada.** A tarefa deste* programa e, dada uma ordem parcial de tarefas, exibir uma das possiveis* sequencias para execucao das tarefas.***/#include #include #define MAX 100struct cel{ int chave; /* conteudo */ struct cel *prox; /* ponteiro para o proximo elemento */} ;/* Para nao termos que digitar struct cel toda hora... */typedef struct cel celula;/* Insercao no comeco de uma lista com cabeca */void insere (int x, celula *lista){ celula *nova; nova = malloc (sizeof (celula)); nova->chave = x; nova->prox = lista->prox; lista->prox = nova;}/* Funcao de remocao. Remove a lista inteira. */void removeLista(celula *lista){ celula *temp; if(lista != NULL) { temp = lista->prox; while(temp != NULL) { lista->prox = temp->prox; free(temp); temp = lista->prox; } free(lista); }}/* usado apenas para depuracao */void imprimeLista(celula *lista){ celula *varre = lista->prox; printf("\n Conteudo da lista: \n"); while(varre != NULL) { printf(" %d ", varre->chave); varre = varre->prox; } printf("\n-----\n\n");}void inicializaLista(celula ** ptrLista) /* com cabeca */{ *ptrLista = malloc(sizeof(celula)); (*ptrLista)->prox = NULL; (*ptrLista)->chave = -1;}/*** A ideia do algoritmo e termos dois vetores:* Um guarda em [i] a quantidade de tarefas antecessores da tarefa i que* estao ainda pendentes (i.e, que nao foram executados).* O outro guarda em [i] a lista de sucessores de da tarefa i.** Le-se os dados e monta-se essa estrutura.** Entao busca-se uma tarefa que possa ser executada de primeira (i.e, com* zero antecessores), executa-se essa tarefa (no caso, apenas imprimimos na* tela) e varre-se a lista de sucessores desta