拓撲排序
拓撲排序是對有向無圈圖的頂點的一種排序,它使得如果存在一條從到的路徑,那麼在排序中出現在的後面。如果圖含有圈,那麼拓撲排序是不可能的。此外,排序不必是唯一的;任何合理的排序都是可以的。
算法思想
第1種
先找出任意一個沒有入邊的頂點。然後顯示出該頂點,並將它和它的邊一起從圖中刪除。然後對圖的其餘部分應用同樣的方法處理。
僞代碼
void Topsort(Graph G)
{
int Counter;
Vertex V, W;
for(Counter = 0; Counter < NumVertex; Counter++)
{
V = FindNewVertexOfIndegreeZero();
if(V == NotAVertex)
{
Error("Graph has a cycle");
break;
}
TopNum[V] = Counter; // 或打印出
for each W adjancent to V
Indegree[W]--;
}
}
函數FindNewVertexOfIndegreeZero掃描Indegree數組,尋找一個尚未被分配拓撲編號的入度爲0的頂點;因爲其是對Indegree數組的一個簡單的順序掃描,所以每次對它的調用都花費的時間.由於有這樣的調用,因此該算法的運行時間爲。
第2種
首先,對每一個頂點計算它的入度(可以在輸入圖時就計算)。然後將所以入度爲0的頂點放入一個初始爲空的的隊列中。當隊列不空時,刪除一個頂點,並將鄰接的所有的頂點的入度減1.只要1個頂點的入度將爲0,就把該頂點放入隊列中。此時,拓撲排序就是頂點出隊的順序。
C語言代碼
void Topsort(ALGraph G)
{
Queue Q;
int Counter;
VertexType V;
ArcNode W;
Q = CreateQueue(MVNum);
Counter = 0;
for (V = 1; V <= G->vexnum; V++)
if (G->Indegree[V] == 0)
Enqueue(V, Q);
while (!IsEmpty(Q))
{
V = FrontAndDequeue(Q);
printf("%d->", V);
Counter++;
W = G->vertices[V].firstarc;
while (W != NULL)
{
if (--G->Indegree[W->adjvex] == 0)
Enqueue(W->adjvex, Q);
W = W->nextarc;
}
}
printf("^\n");
if (Counter != G->vexnum)
printf("Graph has a cycle\n");
DisposeQueue(Q);
}
如果使用鄰接表,那麼執行這個算法所用的時間爲。
完整C語言代碼
#include <stdio.h>
#include <stdlib.h>
#define NotAVertex (-1)
#define MVNum (10) // 最大頂點數
typedef int VertexType;
typedef int ArcType;
typedef struct ArcNode // 邊結點
{
VertexType adjvex; // 該邊所指向的頂點的位置
struct ArcNode *nextarc; // 指向下一條邊的指針
ArcType weight; // 邊的權值
} * ArcNode;
typedef struct VNode // 頂點信息
{
// VertexType data;
ArcNode firstarc; // 指向第一條依附該頂點的邊的指針
} VNode, AdjList[MVNum]; // AdjList 表示鄰接類型
typedef struct // 鄰接表
{
AdjList vertices;
int vexnum, arcnum; // 圖的當前定點數和邊數
int Indegree[MVNum]; // 每個頂點的入度
} * ALGraph;
void CreateUDG(ALGraph G)
{
int i, j;
int v1, v2;
ArcNode p1, p2;
ArcType weight;
printf("Input vexnum: ");
scanf("%d", &G->vexnum);
printf("Input arcnum: ");
scanf("%d", &G->arcnum);
// 輸入各點,構造表頭結點表
for (i = 1; i <= G->vexnum; i++)
{
G->vertices[i].firstarc = NULL;
G->Indegree[i] = 0;
}
// 輸入一條邊依附的兩個頂點
for (j = 0; j < G->arcnum; j++)
{
scanf("%d%d%d", &v1, &v2, &weight);
p1 = (ArcNode)malloc(sizeof(*p1));
if (p1 == NULL)
exit(0);
p1->adjvex = v2;
p1->weight = weight;
p1->nextarc = G->vertices[v1].firstarc;
G->vertices[v1].firstarc = p1;
G->Indegree[v2] += 1;
/*p2 = (ArcNode)malloc(sizeof(struct ArcNode));
p2->adjvex = i;
p2->nextarc = G->vertices[j].firstarc;
G->vertices[j].firstarc = p2;
G->Indegree[v1] += 1;*/
}
}
ALGraph CreateGraph(void)
{
ALGraph G;
G = (ALGraph)malloc(sizeof(*G));
if (G == NULL)
exit(0);
return G;
}
typedef VertexType ElementType;
typedef struct QueueNode *Queue;
struct QueueNode
{
ElementType Array[MVNum];
int Capacity;
int Size;
int Front;
int Rear;
};
int IsFull(Queue Q)
{
return Q->Size == Q->Capacity;
}
int IsEmpty(Queue Q)
{
return Q->Size == 0;
}
Queue CreateQueue(int Capacity)
{
Queue Q;
Q = (Queue)malloc(sizeof(struct QueueNode));
if (Q == NULL)
exit(0);
Q->Capacity = Capacity;
Q->Size = 0;
Q->Front = 1;
Q->Rear = 0;
return Q;
}
void Enqueue(ElementType X, Queue Q)
{
if (IsFull(Q))
{
printf("The queue is full\n");
system("pause");
exit(0);
}
Q->Size++;
if (++Q->Rear == Q->Capacity)
Q->Rear = 0;
Q->Array[Q->Rear] = X;
}
void Dequeue(Queue Q)
{
if (IsEmpty(Q))
{
printf("The queue is empty\n");
system("pause");
exit(0);
}
Q->Size--;
if (++Q->Front == Q->Capacity)
Q->Front = 0;
}
ElementType Front(Queue Q)
{
if (IsEmpty(Q))
{
printf("The queue is empty\n");
system("pause");
exit(0);
}
return Q->Array[Q->Front];
}
ElementType FrontAndDequeue(Queue Q)
{
if (IsEmpty(Q))
{
printf("The queue is empty\n");
system("pause");
exit(0);
}
Q->Size--;
return Q->Array[(Q->Front++) % Q->Capacity];
}
void DisposeQueue(Queue Q)
{
free(Q);
}
void Topsort(ALGraph G)
{
Queue Q;
int Counter;
VertexType V;
ArcNode W;
Q = CreateQueue(MVNum);
Counter = 0;
for (V = 1; V <= G->vexnum; V++)
if (G->Indegree[V] == 0)
Enqueue(V, Q);
while (!IsEmpty(Q))
{
V = FrontAndDequeue(Q);
printf("%d->", V);
Counter++;
W = G->vertices[V].firstarc;
while (W != NULL)
{
if (--G->Indegree[W->adjvex] == 0)
Enqueue(W->adjvex, Q);
W = W->nextarc;
}
}
printf("^\n");
if (Counter != G->vexnum)
printf("Graph has a cycle\n");
DisposeQueue(Q);
}
int main()
{
ALGraph G;
G = CreateGraph();
CreateUDG(G);
Topsort(G);
system("pause");
return 0;
}
輸入/輸出
頂點按數字編號,第3個數子爲邊上的權值。
Input vexnum: 7
Input arcnum: 12
1 2 1
1 3 1
3 6 1
7 6 1
5 7 1
2 5 1
1 4 1
2 4 1
5 4 1
4 7 1
4 6 1
4 3 1
1->2->5->4->3->7->6->^
請按任意鍵繼續. . .