基於鄰接表的拓撲排序實現

  上一篇博客實現了圖的基本操做(使用鄰接表),包括圖的建立、輸出、遍歷等,此次來實現一下拓撲排序。拓撲排序基本原理能夠參考之前轉載的一篇博客html

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

  因爲代碼比較簡單,就直接貼出來了ios

  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 }

 

  測試用的有向圖:數組

  輸出結果:測試

相關文章
相關標籤/搜索