基于邻接表的拓扑排序实现

Posted zhangbaochong

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了基于邻接表的拓扑排序实现相关的知识,希望对你有一定的参考价值。

  上一篇博客实现了图的基本操作(使用邻接表),包括图的创建、输出、遍历等,这次来实现一下拓扑排序。拓扑排序基本原理可以参考以前转载的一篇博客

http://www.cnblogs.com/zhangbaochong/p/5406159.html

  由于代码比较简单,就直接贴出来了

  1 #include <queue>
  2 #include <vector>
  3 #include <stack>
  4 #include <iostream>
  5 using namespace std;
  6 
  7 
  8 enum GraphType
  9 {
 10     UNDIR_UNWEIGHT_GRAPH,        //无向无权图
 11     UNDIR_WEIGHT_GRAPH,            //无向带权图
 12     DIR_UNWEIGHT_GRAPH,            //有向无权图
 13     DIR_WEIGHT_GRAPH            //有向带权图    
 14 };
 15 
 16 //结点颜色代表遍历情况
 17 enum ColorType
 18 {
 19     WHITE,    //未访问
 20     GRAY,    //正在访问,邻接点还没访问完
 21     BLACK    //访问完毕
 22 };
 23 
 24 template<typename VertexType, typename InfoType>
 25 class Graph
 26 {
 27 public:
 28     Graph(int vertexNum, GraphType type) :m_vertexNum(vertexNum), m_type(type), m_arcNum(0)
 29     {
 30         for (int i = 0; i < MAX_VERTEX_NUM; ++i)
 31         {
 32             m_vertices[i].firstArc = nullptr;
 33         }
 34     }
 35 
 36     void Create()
 37     {
 38         CreateDirUnweightGraph();
 39     }
 40 
 41 
 42     //输出图的信息
 43     void Display()
 44     {
 45         for (int i = 0; i < m_vertexNum; ++i)
 46         {
 47             cout << "" << i + 1 << "个结点为" << m_vertices[i].data << " 邻接表为:";
 48             ArcNode* node = m_vertices[i].firstArc;
 49             while (node)
 50             {
 51                 cout << "->" << m_vertices[node->vertexIndex].data << "(" << node->info << ")";
 52                 node = node->next;
 53             }
 54             cout << endl;
 55         }
 56     }
 57 
 58     //拓扑排序
 59     void TopologicalSort()
 60     {
 61         cout << "拓扑排序为:";
 62         CountInDegree();
 63         stack<Vertex> s;
 64         //把所有入度为0的结点入栈
 65         for (int i = 0; i < m_vertexNum; ++i)
 66         {
 67             if (m_inDegreeArray[i] == 0)
 68                 s.push(m_vertices[i]);
 69         }
 70         int count = 0;//输出结点计数,用于判断有没有环
 71         while (!s.empty())
 72         {
 73             Vertex v = s.top();
 74             s.pop();
 75             cout << v.data << "->";
 76             ++count;
 77             ArcNode* node = v.firstArc;
 78             while (node)
 79             {
 80                 //从图中删除结点v,v指向的结点入度-1
 81                 //结点 入度为0加入栈中
 82                 if (--m_inDegreeArray[node->vertexIndex] == 0)
 83                     s.push(m_vertices[node->vertexIndex]);
 84                 node = node->next;
 85             }
 86         }
 87         if (count < m_vertexNum)
 88             cout << "图中存在环!" << endl;
 89     }
 90 private:
 91     struct ArcNode
 92     {
 93         int vertexIndex;        //该弧指向的顶点位置
 94         struct ArcNode* next;    //指向下一个弧
 95         InfoType info;            //该弧的相关信息,如权重等
 96     };
 97 
 98     struct Vertex
 99     {
100         VertexType data;    //顶点信息
101         ArcNode* firstArc;    //指向第一条依附该节点弧的指针
102         ColorType color;    //访问情况
103     };
104 
105     //最大顶点数
106     static const int MAX_VERTEX_NUM = 20;
107     Vertex m_vertices[MAX_VERTEX_NUM];    //顶点列表
108     int m_vertexNum;    //当前顶点数量
109     int m_arcNum;        //当前弧数量
110     GraphType m_type;    //图类型:有向无权图、有向带权图、无向无权图、无向无权图
111 
112     //结点入度数组
113     int m_inDegreeArray[MAX_VERTEX_NUM];
114 private:
115     //初始化顶点列表
116     void InitVertices()
117     {
118         cout << "请输入每个顶点的关键字" << endl;
119         VertexType data;
120         for (int i = 0; i < m_vertexNum; ++i)
121         {
122             cin >> data;
123             m_vertices[i].data = data;
124         }
125     }
126     //插入一个表结点
127     void Insert(int headVertex, int tailVertex, InfoType info)
128     {
129         //构造一个邻接表结点,即创建一条弧
130         ArcNode* newNode = new ArcNode;
131         newNode->info = info;
132         newNode->next = nullptr;
133         newNode->vertexIndex = tailVertex;
134 
135         //找到邻接表的最后一个节点
136         ArcNode* lastNode = m_vertices[headVertex].firstArc;
137         if (lastNode == nullptr)
138             m_vertices[headVertex].firstArc = newNode;
139         else
140         {
141             while (lastNode->next)
142             {
143                 lastNode = lastNode->next;
144             }
145             lastNode->next = newNode;
146         }
147         ++m_arcNum;
148     }
149 
150     //创建有向无权图
151     void CreateDirUnweightGraph()
152     {
153         InitVertices();
154         cout << "请分别输入每条边的起始结点值:" << endl;
155         int head, tail;
156         while (cin >> head >> tail)
157         {
158             Insert(head, tail, 0);
159         }
160     }
161     
162     void CountInDegree()
163     {
164         for (int i = 0; i < m_vertexNum; ++i)
165         {
166             m_inDegreeArray[i] = 0;
167             for (int j = 0; j < m_vertexNum; ++j)
168             {
169                 ArcNode* node = m_vertices[j].firstArc;
170                 while (node)
171                 {
172                     if (node->vertexIndex == i)
173                     {
174                         ++m_inDegreeArray[i];
175                     }
176                     node = node->next;
177                 }
178             }
179         }
180     }
181 };
182 
183 int main()
184 {
185     Graph<char, int> g(6, DIR_UNWEIGHT_GRAPH);
186     g.Create();
187     g.Display();
188     g.TopologicalSort();
189 }

 

  测试用的有向图:

  输出结果:

以上是关于基于邻接表的拓扑排序实现的主要内容,如果未能解决你的问题,请参考以下文章

C++实现拓扑排序(邻接表存储,栈实现)

C++实现拓扑排序(vector模拟邻接表存储,栈实现)

图论基础——邻接链表存图+拓扑排序

拓扑排序算法实现

拓扑排序

拓扑排序,判断有向图中是否有环