上一篇博客實現了圖的基本操做(使用鄰接表),包括圖的建立、輸出、遍歷等,此次來實現一下拓撲排序。拓撲排序基本原理能夠參考之前轉載的一篇博客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 }
測試用的有向圖:數組
輸出結果:測試