拓扑排序
Posted gavanwanggw
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了拓扑排序相关的知识,希望对你有一定的参考价值。
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 << " "; } }
以上是关于拓扑排序的主要内容,如果未能解决你的问题,请参考以下文章