1、什么是拓扑排序
条 有向边<u,v>,在拓扑排序中u节点位于v节点的前面(如果图G包含回路,则不可能排出一个线性次序)。可以将图的拓扑排序看做是将图的所有节点排在一条水平线上,有向图中的所有有向边都从左指向右。对于有向无环图G=(V,E),G的拓扑排序是G中所有节点的一种线性次序,该次序满足如下条件:对于图中的一
2、拓扑排序解决的实际问题
然 后再去穿另外一些衣服,有些衣服则可以以任意顺序穿上,在下图中有向边<u,v >表明服装u必须在服装v之前穿上。我们该如何解决穿衣问题呢?我在这里介绍使用拓扑排序解决现实生活中的一个起床穿衣的问题。在起床的过程中,我们必须先穿某些衣服,
3、拓扑排序算法
法的步骤为:①初始化集合A、B为空;②将入度为0的节点加入集合A;③从集合A中取元素,将取出的元素加入集合B,并将此元素所指向的所有节点的入度减1,如果有节点的入度减为0,则将其加入到集合A中;④重复步骤③直到结合A为空为止,此时集合B中即为拓扑排序结果。我们需要两个队列集合A、B,其中集合A用来存放入度为0的节点,集合B用来存放排好序的节点。拓扑排序算
#include <iostream> /*拓扑排序: 给定一个有向无环图,把图G中的所有顶点排成一个线性序列, 使得图中任意边<u,v>,在线性序列中顶点u在顶点v的前面。 基本思想: ①从图中选取入度为0的顶点,并将这些顶点加入队列集合A中; ②依次从队列集合A中取元素,将该元素加入到队列集合B中,同时将该元素所连接的顶点的入度减1, 如果顶点的入度减为0,则将该顶点加入到集合A中。 ③重复②,直到集合A为空。 */ typedef char ElemType; const int WHITE = 0; const int BLACK = 1; const int MAX_VERTEX = 30; const int MAX_ARC = 900; /*边的数据结构*/ typedef struct arc_node { int position;//存储边的另一个顶点下标 int weight;//边的权重 struct arc_node *next;//指向下一条边 }ANode, *pArc; /*顶点的数据结构*/ typedef struct vertex_node { ElemType data; pArc first_arc;//指向第一条弧 }VNode, *pVNode; /*图的数据结构*/ typedef struct graphic_node { int vertex_num;//顶点数量 int arc_num;//边的数量 pVNode vertex[MAX_VERTEX];//用来存放顶点的数组 }Graphic, *pGNode; /*辅助数据结构:队列*/ typedef struct queue_node { int data; struct queue_node *next; }QNode,*pQNode; typedef struct queue { pQNode front; pQNode tail; }Queue; void topologic_sort(Graphic g); void create_graphic(pGNode g, int direction); /*要想修改内容必须传指针,要想修改内容指向的值可以不传指针*/ void init_queue(Queue *q); bool isempty_queue(Queue q); void insert_queue(Queue *q, int e); bool delete_queue(Queue *q, int *e);//当删除最后一个元素的时候一定要修改尾部指针 using namespace std; int main() { Graphic g; create_graphic(&g,1); topologic_sort(g); return 0; } void create_graphic(pGNode g, int direction)//direction = 0表示创建的是无向图,非0值是有向图 { cout << "输入顶点数" << endl; cin >> g->vertex_num; cout << "输入边数" << endl; cin >> g->arc_num; int i; cout << "输入" << g->vertex_num << "个顶点" << endl; for (i = 0; i < g->vertex_num; i++) { g->vertex[i] = (pVNode)malloc(sizeof(VNode)); cin >> (g->vertex[i]->data); g->vertex[i]->first_arc = NULL; } cout << "输入" << g->arc_num << "个边和边的权重(例如:输入0 1 20表示下标为0和下标为1的顶点有一条边且权重为20)" << endl; for (i = 0; i < g->arc_num; i++) { int x, y, w; cin >> x >> y >> w; pArc temp1 = (pArc)malloc(sizeof(ANode)); temp1->position = y; temp1->weight = w; /*将边加入到链接链表中*/ temp1->next = g->vertex[x]->first_arc; g->vertex[x]->first_arc = temp1; if (direction == 0)//说明是无向图 { pArc temp2 = (pArc)malloc(sizeof(ANode)); temp2->position = x; temp2->weight = w; temp2->next = g->vertex[y]->first_arc; g->vertex[y]->first_arc = temp2; } } } void init_queue(Queue *q) { /*构造哨兵节点*/ pQNode x = (pQNode)malloc(sizeof(QNode)); x->next = NULL; q->front = q->tail = x; } bool isempty_queue(Queue q) { if (q.front->next == NULL) return true; return false; } void insert_queue(Queue *q, int e) { pQNode x = (pQNode)malloc(sizeof(QNode)); x->next = NULL; x->data = e; q->tail->next = x; q->tail = x; } bool delete_queue(Queue *q, int *e) { if (isempty_queue(*q)) return false; pQNode x = q->front->next; *e = x->data; q->front->next = x->next; if (x->next == NULL)//如果删除的是最后一个元素 q->tail = q->front; free(x); return true; } void topologic_sort(Graphic g) { int in[MAX_VERTEX] = { 0 };//用来记录每个顶点的入度 /*统计每个顶点的入度*/ for (int i = 0; i < g.vertex_num;i++) { pArc x = g.vertex[i]->first_arc; while (x != NULL) { in[x->position] += 1; x = x->next; } } Queue A, B; init_queue(&A); init_queue(&B); /*将入度为0的顶点加入A队列*/ for (int i = 0; i < g.vertex_num; i++) { if (in[i] == 0) insert_queue(&A, i); } while ( !isempty_queue(A)) { int position; delete_queue(&A, &position); insert_queue(&B, position); /*将所有以顶点A为起点的边的其它顶点的入度减1*/ pArc y = g.vertex[position]->first_arc; while (y != NULL) { in[y->position] -= 1; if (in[y->position] == 0) insert_queue(&A, y->position); y = y->next; } } /*输出拓扑排序的结果*/ while ( !isempty_queue(B) ) { int position; delete_queue(&B, &position); cout << g.vertex[position]->data << " "; } }