数据结构之拓扑排序
拓撲排序介紹
拓撲排序(Topological Order)是指,將一個有向無環圖(Directed Acyclic Graph簡稱DAG)進行排序進而得到一個有序的線性序列。
這樣說,可能理解起來比較抽象。下面通過簡單的例子進行說明!
例如,一個項目包括A、B、C、D四個子部分來完成,并且A依賴于B和D,C依賴于D。現在要制定一個計劃,寫出A、B、C、D的執行順序。這時,就可以利用到拓撲排序,它就是用來確定事物發生的順序的。
在拓撲排序中,如果存在一條從頂點A到頂點B的路徑,那么在排序結果中B出現在A的后面。
拓撲排序算法的基本步驟
3.1 從Q中取出一個頂點n(將n從Q中刪掉),并放入T(將n加入到結果集中);
3.2 對n每一個鄰接點m(n是起點,m是終點);
3.2.1 去掉邊
(01) ListDG是鄰接表對應的結構體。 mVexNum是頂點數,mEdgNum是邊數;mVexs則是保存頂點信息的一維數組。
(02) VNode是鄰接表頂點對應的結構體。 data是頂點所包含的數據,而firstEdge是該頂點所包含鏈表的表頭指針。
(03) ENode是鄰接表頂點所包含的鏈表的節點對應的結構體。 ivex是該節點所對應的頂點在vexs中的索引,而nextEdge是指向下一個節點的。
拓撲排序
/** 拓撲排序** 返回值:* -1 -- 失敗(由于內存不足等原因導致)* 0 -- 成功排序,并輸入結果* 1 -- 失敗(該有向圖是有環的)*/ int ListDG::topologicalSort() {int i,j;int index = 0;int head = 0; // 輔助隊列的頭int rear = 0; // 輔助隊列的尾int *queue; // 輔組隊列int *ins; // 入度數組char *tops; // 拓撲排序結果數組,記錄每個節點的排序后的序號。ENode *node;ins = new int[mVexNum];queue = new int[mVexNum];tops = new char[mVexNum];memset(ins, 0, mVexNum*sizeof(int));memset(queue, 0, mVexNum*sizeof(int));memset(tops, 0, mVexNum*sizeof(char));// 統計每個頂點的入度數for(i = 0; i < mVexNum; i++){node = mVexs[i].firstEdge;while (node != NULL){ins[node->ivex]++;node = node->nextEdge;}}// 將所有入度為0的頂點入隊列for(i = 0; i < mVexNum; i ++)if(ins[i] == 0)queue[rear++] = i; // 入隊列while (head != rear) // 隊列非空{j = queue[head++]; // 出隊列。j是頂點的序號tops[index++] = mVexs[j].data; // 將該頂點添加到tops中,tops是排序結果node = mVexs[j].firstEdge; // 獲取以該頂點為起點的出邊隊列// 將與"node"關聯的節點的入度減1;// 若減1之后,該節點的入度為0;則將該節點添加到隊列中。while(node != NULL){// 將節點(序號為node->ivex)的入度減1。ins[node->ivex]--;// 若節點的入度為0,則將其"入隊列"if( ins[node->ivex] == 0)queue[rear++] = node->ivex; // 入隊列node = node->nextEdge;}}if(index != mVexNum){cout << "Graph has a cycle" << endl;delete queue;delete ins;delete tops;return 1;}// 打印拓撲排序結果cout << "== TopSort: ";for(i = 0; i < mVexNum; i ++)cout << tops[i] << " ";cout << endl;delete queue;delete ins;delete tops;return 0; }說明:
(01) queue的作用就是用來存儲沒有依賴頂點的頂點。它與前面所說的Q相對應。
(02) tops的作用就是用來存儲排序結果。它與前面所說的T相對應。
總結
- 上一篇: 一篇文章搞懂数据仓库:三范式与反范式
- 下一篇: 形态学图像处理(二)