图——基本的图算法(三)拓扑排序

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/hh66__66hh/article/details/83349142

图——基本的图算法(三)拓扑排序

1. 基本概念

对于一个有向无环图G = (V, E)来说,其拓扑排序就是G中所有顶点的一种线性排序,这种排序满足如下条件:如果图G中包含边(a, b),即由顶点a指向顶点b的有向边,那么在G的拓扑排序中,顶点a一定处于顶点b前面(因此如果有向图G中包含回路,则不可能排出这样一个线性次序)。

2. 算法实现

2.1 总体思想

对一个有向无环图进行拓扑排序的基本思路是:从图中选出一个入度为0的顶点输出,然后删掉这个顶点,并且删去以这个顶点为尾的弧,然后重复上述步骤,直至全部顶点输出。

2.2 数据结构

对于拓扑排序,由于要删掉以某个入度为0的顶点为尾的弧,也就是要删掉相应的边,因此一般采用邻接表来对图进行表示,但要稍作修改:顶点表中的每个结点增加一项用来表示该顶点此时的入度值。具体如下:
(1)顶点表结点

typedef struct VertexListNode{
    int in; //入度
    int data; //该顶点的值
    EdgeListNode* firstadj; //指向该顶点的边表里的第一个结点
};

(2)边表结点

typedef struct EdgeListNode{
    int adjId; //弧头在顶点表中的下标
    int weight; //弧的权值
    EdgeListNode* next; //指向边表中的下一个结点
};

(3)邻接链表表示的图结构

typedef struct GraphAdjList{
    int vertexnumber; //顶点个数
    int edgenumber; //弧的条数
    VertexListNode vertextlist[Maximum]; //顶点表
};

(4)综上,数据结构为:

#define Maximum 1000

typedef struct EdgeListNode{
    int adjId;
    int weight;
    EdgeListNode* next;
};

typedef struct VertexListNode{
    int in;
    int data;
    EdgeListNode* firstadj;
};

typedef struct GraphAdjList{
    int vertexnumber;
    int edgenumber;
    VertexListNode vertextlist[Maximum];
};

2.3 具体实现

// 返回存储了拓扑排序的vector
vector<int> ToplogicalSort(GraphAdjList g) {
    int ans = 0;
    queue<int>q; //用来存储入度为0的待处理顶点
    vector<int> sort_queue; //用来存储拓扑排序结果
    // 清空队列
    while(!q.empty()) {
        q.pop();
    }
    int i, j, k;
    //找出所有入度为0的顶点,入队列
    for(i=1; i<=g.vertexnumber; i++) {
        if(g.vertextlist[i].in == 0) {
            q.push(i);
        }
    }
    EdgeListNode *temp;
    while(!q.empty()) {
        j = q.front();
        q.pop();
        ans++;
        sort_queue.push_back(j);
        temp = g.vertextlist[j].firstadj;

		//遍历其边表,找出于其有边相连的顶点
        while(temp != NULL) {
        	g.vertextlist[temp->adjId].in--; //该顶点入度减一
            if(g.vertextlist[temp->adjId].in == 0) {
                q.push(temp->adjId);
            }
            temp = temp->next;
        }
    }
	if(ans < g.vertexnumber) { //这是一个有环有向图
		sort_queue.clear(); //清空vector
	}
    return sort_queue; 

}

2.4 测试

完整代码:

#include<iostream>
#include<stdio.h>
#include<string.h>
#include<map>
#include<vector>
#include<sstream>
#include<list>
#include<stdlib.h>
#include<queue>
using namespace std;

#define Maximum 1000

typedef struct EdgeListNode{
    int adjId;
    int weight;
    EdgeListNode* next;
};

typedef struct VertexListNode{
    int in;
    int data;
    EdgeListNode* firstadj;
};

typedef struct GraphAdjList{
    int vertexnumber;
    int edgenumber;
    VertexListNode vertextlist[Maximum];
};

vector<int> ToplogicalSort(GraphAdjList g) {
    int ans = 0;
    queue<int>q;
    vector<int> sort_queue;
    while(!q.empty()) {
        q.pop();
    }
    int i, j, k;
    for(i=1; i<=g.vertexnumber; i++) {
        if(g.vertextlist[i].in == 0) {
            q.push(i);
        }
    }
    EdgeListNode *temp;
    while(!q.empty()) {
        j = q.front();
        q.pop();
        ans++;
        sort_queue.push_back(j);
        temp = g.vertextlist[j].firstadj;

        while(temp != NULL) {
            if(--g.vertextlist[temp->adjId].in == 0) {
                q.push(temp->adjId);
            }
            temp = temp->next;
        }
    }
    if(ans < g.vertexnumber) {
		sort_queue.clear();
	}
    return sort_queue;

}

int main() {
    GraphAdjList g;
    g.vertexnumber = 5;
    g.edgenumber = 5;
    int i;
    for(i=1; i<6; i++) {
        g.vertextlist[i].data = i;
        g.vertextlist[i].firstadj = NULL;
    }
    g.vertextlist[1].in = g.vertextlist[4].in = 0;
    g.vertextlist[5].in = g.vertextlist[3].in = 2;
    g.vertextlist[2].in = 1;
    EdgeListNode* t;
    t = (EdgeListNode*)malloc(sizeof(EdgeListNode));
    t->adjId = 3; t->next = NULL; g.vertextlist[1].firstadj = t;

    t = (EdgeListNode*)malloc(sizeof(EdgeListNode));
    t->adjId = 2; t->next = g.vertextlist[1].firstadj; g.vertextlist[1].firstadj = t;

    t = (EdgeListNode*)malloc(sizeof(EdgeListNode));
    t->adjId = 5; t->next = NULL; g.vertextlist[2].firstadj = t;

    t = (EdgeListNode*)malloc(sizeof(EdgeListNode));
    t->adjId = 5; t->next = NULL; g.vertextlist[3].firstadj = t;

    t = (EdgeListNode*)malloc(sizeof(EdgeListNode));
    t->adjId = 3; t->next = NULL; g.vertextlist[4].firstadj = t;

    vector<int>v;
    v = ToplogicalSort(g);
    
    if(v.size() == 0) {
        cout<<"This graph has ring"<<endl;
    }
    else {
        for(i=0; i<v.size(); i++) {
            cout<<v[i]<<" ";
        }
        cout<<endl;
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/hh66__66hh/article/details/83349142