Toplogical Sort 拓扑排序
Toplogical Sort
拓扑排序是对有向图的顶点的一种排序,它使得如果存在一条从Vm到Vn的路径,那么在排序中Vn出现在Vm后面。
如果图含有圈,或者初始入度没有为0的节点,那么拓扑排序是不可能完成的。
理论介绍去看<DSAA>或者《算法导论》,老话,这里还是介绍如何实现。
tls.h
/************************************************************ code file : tls.h code writer : EOF code date : 2014.11.22 e-mail : [email protected] code 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 -1 struct 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.c code writer : EOF code date : 2014.11.22 e-mail : [email protected] code 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.c code writer : EOF code date : 2014.11.22 e-mail : [email protected] code description: This function is used for initializing the graph with 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 relationship for(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.c code writer : EOF code date : 2014.11.23 e-mail : [email protected] code description: This function will help us to create a table which's size is @row multiply @col. And the size of each unit int this 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.c code writer : EOF code date : 2014.11.22 e-mail : [email protected] code description: This function will print out the connection of graph which @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.c code writer : EOF code date : 2014.11.22 e-mail : [email protected] code description: It's easy and convenient for us to call this API once and 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); }
#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"); }
/************************************************************ code file : add_edge.c code writer : EOF code date : 2014.11.22 e-mail : [email protected] code description: This function will help us to add a new connection between 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.c code writer : EOF code date : 2014.11.22 e-mail : [email protected] code 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 = 0 for(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
8 12 3 6 1 4 1 2 1 3 4 3 4 6 4 7 7 6 2 4 2 5 5 7 5 4
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。