Toplogical Sort 拓扑排序

来源:互联网 发布:诲女知之乎悔 编辑:程序博客网 时间:2024/05/23 01:15

Toplogical Sort


      拓扑排序是对有向图的顶点的一种排序,它使得如果存在一条从Vm到Vn的路径,那么在排序中Vn出现在Vm后面。

 

      如果图含有圈,或者初始入度没有为0的节点,那么拓扑排序是不可能完成的。


理论介绍去看<DSAA>或者《算法导论》,老话,这里还是介绍如何实现。


tls.h

/************************************************************code file: tls.hcode writer: EOFcode date: 2014.11.22e-mail: jasonleaster@gmail.comcode description:Header file for toplogistic sort.************************************************************/#ifndef _TLS_H_#define _TLS_H_#include <stdio.h>#include <stdlib.h>#define CONNECTED    1#define DISCONNECTED 0#define SUCCESS  0#define FAILED  -1#define EMPTY_QUEUE   -1#define UNEMPTY_QUEUE  0 /***We use these macro as index for struct table*/#define KNOW_OFFSET 0 //vertex that have been found#define DIST_OFFSET 1 //distance of vertex#define PATH_OFFSET 2 //parent vertex of current vertex#define FOUND    1#define NOT_FOUND   0#define ENTRY_POINT 3#define INFINITE -1struct node{struct node* previous;struct node* next;int data;};struct vertex{int value;int indegree;struct vertex* next;struct vertex* end;};struct graph{int num_vertex;int num_edge;struct vertex adjacent[0];};struct table{int height;int width;int msg[0];//we store message of table in this array.};/***API for ADT--graph*/struct graph* init_graph(int vertex,int edge);void   release_graph(struct graph* p_graph);int add_edge(struct graph* p_graph,char from_v,char to_v);int print_graph(struct graph* p_graph);/***API for ADT--table*/struct table* init_table(int row,int col);void release_table(struct table* p_table);/***I implement some API to use ADT-Queue*/int queue_destory(struct node* p_queue_tail);int queue_enter(struct node** pp_queue_header,struct node** pp_queue_tail,int number);int queue_init(struct node** pp_queue_header,        struct node** pp_queue_tail);int queue_out(struct node** pp_queue_header,      struct node** pp_queue_tail);void queue_print(struct node* p_queue_tail);#endif

测试主程序test_graph.c

/****************************************************************code file: test_graph.ccode writer: EOFcode date: 2014.11.22e-mail: jasonleaster@gmail.comcode description:This test program is used for testing toplogistic sort.*****************************************************************/#include "tls.h"int main(){struct graph* p_graph = NULL;FILE* fp = fopen("./text.txt","r+");if(!fp){printf("fopen() failed!\n");return 0;}int ret    = 0;int vertex = 0;int edge   = 0;int from_v = 0;int to_v   = 0;fscanf(fp,"%d",&vertex);fscanf(fp,"%d",&edge);p_graph = init_graph(vertex,edge);int temp = 0;for(temp;temp < edge;temp++){/***I think it's necessary to check the returned value** of scanf() family.*/ret = fscanf(fp,"%d %d",&from_v,&to_v);if(ret != 2){break;}add_edge(p_graph,from_v,to_v);}struct table* p_table =  init_table(vertex,3);print_graph(p_graph);//----------------------topsort(p_graph);//---------------------release_table(p_table);release_graph(p_graph);fclose(fp);return 0;}



init_graph.c

/************************************************************code file: init_graph.ccode writer: EOFcode date: 2014.11.22e-mail: jasonleaster@gmail.comcode description:This function is used for initializing the graphwith inputed parameter @vertex and @edge.************************************************************/#include "tls.h"struct graph* init_graph(int num_vertex,int num_edge){if(num_vertex <= 0 || num_edge <= 0){return NULL;}struct graph* p_graph = NULL;        p_graph = (struct graph*)malloc(sizeof(struct graph) +\  num_vertex*sizeof(struct vertex));if(!p_graph){printf("malloc failed in function %s()\n",__FUNCTION__);return NULL;}p_graph->num_vertex = num_vertex;p_graph->num_edge   = num_edge;int temp = 0;//initialize the adjacent relationshipfor(temp = 0;temp < num_vertex;temp++){p_graph->adjacent[temp].value = temp;p_graph->adjacent[temp].next  = NULL;p_graph->adjacent[temp].end   = NULL;p_graph->adjacent[temp].indegree   = 0;}return p_graph;}


init_table.c

/************************************************************code file: init_table.ccode writer: EOFcode date: 2014.11.23e-mail: jasonleaster@gmail.comcode description:This function will help us to create a table which'ssize is @row multiply @col. And the size of each unit intthis table is sizeof(int).************************************************************/#include "tls.h"struct table* init_table(int row,int col){if(row <= 0 || col <= 0){return NULL;}struct table* p_table = (struct table*)malloc(sizeof(struct table) + row*col*sizeof(int));if(!p_table){return NULL;}p_table->height = row;p_table->width  = col;int num_row = row;int num_col = col;//We must initialize the table !for(row = 0;row < num_row;row++){*((int*)(p_table->msg) + row*num_col + KNOW_OFFSET) = NOT_FOUND;if(row != ENTRY_POINT){*((int*)(p_table->msg) + row*num_col + DIST_OFFSET) = INFINITE;}else{*((int*)(p_table->msg) + row*num_col + DIST_OFFSET) = 0;}*((int*)(p_table->msg) + row*num_col + PATH_OFFSET) = 0;}return p_table;}


print_graph.c

/************************************************************code file: print_graph.ccode writer: EOFcode date: 2014.11.22e-mail: jasonleaster@gmail.comcode description:This function will print out the connection of graphwhich @p_graph point to.************************************************************/#include "tls.h"int print_graph(struct graph* p_graph){if(!p_graph){return FAILED;}int from_v = 0;int to_v = 0;int num_vertex = p_graph->num_vertex;struct vertex* p_vertex = NULL;for(from_v = 0;from_v < num_vertex;from_v++){p_vertex = &(p_graph->adjacent[from_v]);while(p_vertex){printf("\t%d",p_vertex->value);p_vertex = p_vertex->next;}printf("\n");}return SUCCESS;}

release_graph.c

/************************************************************code file: release_graph.ccode writer: EOFcode date: 2014.11.22e-mail: jasonleaster@gmail.comcode description:It's easy and convenient for us to call this API onceand free all the graph.*************************************************************/#include "tls.h"void release_graph(struct graph* p_graph){if(!p_graph){return ;}int temp = 0;int num_vertex = p_graph->num_vertex;struct vertex* p_temp = NULL;for(temp = 0;temp < num_vertex;temp++){if(p_graph->adjacent[temp].next){p_temp = (p_graph->adjacent[temp].next->next);while(p_temp){free(p_graph->adjacent[temp].next);p_graph->adjacent[temp].next = p_temp;p_temp = p_temp->next;}free(p_graph->adjacent[temp].next);}}free(p_graph);}


release_table.c
#include "tls.h"void release_table(struct table* p_table){if(!p_table){return;}free(p_table);}

#include "tls.h"void table_print(struct table* p_table){if(!p_table){return;}int row_num = p_table->height;int col_num = p_table->width;int row = 0;int know = 0;int dist = 0;int path = 0;printf("\tknow\tdist\tpath\n");for(row = 0;row < row_num;row++){know = p_table->msg[row*col_num + KNOW_OFFSET];switch(know){case FOUND:{printf("\tFound");break;}case NOT_FOUND:{printf("\tNFond");break;}default:printf("error value of varible @know\n");return;}dist = p_table->msg[row*col_num + DIST_OFFSET];switch(dist){case INFINITE:{printf("\tINF");break;}default:printf("\t%d",dist);}path = p_table->msg[row*col_num + PATH_OFFSET];switch(path){case 0:{printf("\t0");break;}default:printf("\tv%d",path);}printf("\n");}printf("\n\n\n");}


add_edge.c
/************************************************************code file: add_edge.ccode writer: EOFcode date: 2014.11.22e-mail: jasonleaster@gmail.comcode description:This function will help us to add a new connectionbetween different vertex which is in the graph.*************************************************************/#include "tls.h"int add_edge(struct graph* p_graph,char from_v,char to_v){if(!p_graph || from_v < 0 || to_v < 0){return FAILED;}struct vertex* p_to_v    = (struct vertex*)malloc(sizeof(struct vertex));if(!p_to_v){printf("malloc failed in function %s()\n",__FUNCTION__);return FAILED;}if(!(p_graph->adjacent[from_v].end)){p_graph->adjacent[from_v].next  = p_to_v;p_graph->adjacent[from_v].end   = p_to_v;p_to_v->next  = NULL;p_to_v->value = to_v;}else{p_graph->adjacent[from_v].end->next = p_to_v;p_graph->adjacent[from_v].end       = p_to_v;//update the new end node.p_to_v->next  = NULL;p_to_v->value = to_v;}/***Caculate the indegree of each vertex*/(p_graph->adjacent[to_v].indegree)++;return SUCCESS;}

这里实现拓扑排序的核心函数topsort.c 

/****************************************************************code file: topsort.ccode writer: EOFcode date: 2014.11.22e-mail: jasonleaster@gmail.comcode description:A implementation of topsort() which is used for toplogistic sort.***************************************************************/#include "tls.h"void topsort(struct graph* p_graph){if(!p_graph){return;}int counter = 0;struct vertex* p_vertex = NULL;struct node* p_queue_header = NULL;struct node* p_queue_tail   = NULL;queue_init(&p_queue_header,&p_queue_tail);int temp = 0;//Attention! Here we start from point 1 but not temp = 0for(temp = 1;temp < p_graph->num_vertex;temp++){if(p_graph->adjacent[temp].indegree == 0){queue_enter(&p_queue_header,        &p_queue_tail,    temp);}}int vertex_index = 0;while(!!p_queue_header){vertex_index = queue_out(&p_queue_header,&p_queue_tail);printf("\t%d",vertex_index);p_vertex = (struct vertex*)(&p_graph->adjacent[vertex_index]);p_vertex = p_vertex->next;for(;!!p_vertex;p_vertex = p_vertex->next){if(--(p_graph->adjacent[p_vertex->value].indegree) == 0){queue_enter(&p_queue_header,    &p_queue_tail,    p_vertex->value);}}}printf("\n");queue_destory(p_queue_tail);}

测试文本: text.txt

8123 61 41 21 34 34 64 77 62 42 55 75 4









0 0