1. 程式人生 > >拓撲排序之變量序列代碼

拓撲排序之變量序列代碼

關系 拓撲序列 als space lib malloc 系列 -a 如果

/*
Name:
Copyright:
Author:
Date: 17-11-14 21:02
Description: 拓撲排序之變量序列
如果有n個變量(1<=n<=26,變量名用單個小寫字母表示)。還有m個二元組(u,v),分別表示變量u小於v。

那麽,全部變量從小到大排列起來應該是什麽樣子的呢?
比如有4個變量a,b,c,d,若以知a<b,c<b,d<c,則這4個變量的排序可能是a<d<c<b。

雖然還有可能其它的可能,你僅僅需找出當中的一個就可以。
Input
輸入為一個字符串data,當中包括N+N個字符。表示N個關系式(1<=N<=100000),比如序列"abcbdc"表示a<b,c<b,d<c.
Output
給出一個字符串,當中存儲了一個符合要求的變量序列,比如,字符串"adcb"表示a<d<c<b。


*/
#include<stdio.h>
#include<stdlib.h>


#define true 1
#define false 0
#define MAXM 26 //最大變量(頂點)數量
#define MAXN 100000 //最大關系式數量


typedef char VertexType; //頂點類型由用戶自己定義
typedef int EdgeType; //邊上的權值類型由用戶自己定義


typedef struct EdgeNode{ //邊表結點
int adjvex; //鄰接點域,存儲該頂點相應的下標
//
EdgeType weight; //權值。對於非網圖能夠不須要
struct EdgeNode *next; //鏈域,指向下一個鄰接點
} EdgeNode;


typedef struct VertexNode{ //頂點表結點
VertexType data; //頂點域,存儲頂點信息
int in; //存儲頂點入度的數量
EdgeNode *firstEdge; //邊表頭指針
} VertexNode;


typedef struct Edge{ //邊集數組
int u, v; //弧尾和弧頭
int next; //指向同一個弧尾的下一條邊
// EdgeType weight; //權值,對於非網圖能夠不須要
} EdgeLib;


int book[MAXM] = {0}; //標記某字母是否出現


int IsTopoSeq(char *data, char *topo);//依據關系列表data,推斷topo字符串是否為拓撲序列
int CreateGraph(char *data, VertexNode *GL);//創建一個圖
void PrintGraph(VertexNode *GL);//輸出圖
int TopoLogicalSort_DFS(char *topo, VertexNode *GL, int n);//拓撲排序,獲取拓撲序列,若存在環則返回假
int TopoLogicalSort_BFS(char *topo, VertexNode *GL, int n);//拓撲排序,獲取拓撲序列。若存在環則返回假
int CreateGraph_2(char *data, int In[], int first[], EdgeLib edge[]);//創建一個圖
void PrintGraph_2(int first[], EdgeLib edge[]);//輸出圖
int TopoLogicalSort(char *topo, EdgeLib edge[], int In[], int first[], int n);//拓撲排序。獲取拓撲序列,若存在環則返回假,使用隊列存儲拓撲序列


int main()
{
int i, n;
VertexNode GL[MAXM];
char topo[MAXM+1];
char data[MAXN+MAXN+1];
int In[MAXM], first[MAXM]; //存儲頂點信息
EdgeLib edge[MAXN]; //存儲邊信息


gets(data);
n = CreateGraph_2(data, In, first, edge);//創建一個圖
PrintGraph_2(first, edge);//輸出圖

if (TopoLogicalSort(topo, edge, In, first, n))//採用拓撲排序構造拓撲序列
puts(topo);
else
puts("不存在滿足條件的序列");

if (IsTopoSeq(data, topo))//依據關系列表data。推斷topo字符串是否為拓撲序列
puts(topo);
else
puts("不存在滿足條件的序列");

gets(data);
n = CreateGraph(data, GL);//創建一個圖
PrintGraph(GL);//輸出圖
if (IsTopoSeq(data, topo))//依據關系列表data,推斷topo字符串是否為拓撲序列
puts(topo);
else
puts("不存在滿足條件的序列");

if (TopoLogicalSort_BFS(topo, GL, n))//採用拓撲排序構造拓撲序列
puts(topo);
else
puts("不存在滿足條件的序列");

gets(data);
n = CreateGraph(data, GL);//創建一個圖
PrintGraph(GL);//輸出圖

if (TopoLogicalSort_DFS(topo, GL, n))//採用拓撲排序構造拓撲序列
puts(topo);
else
puts("不存在滿足條件的序列");

if (IsTopoSeq(data, topo))//依據關系列表data,推斷topo字符串是否為拓撲序列
puts(topo);
else
puts("不存在滿足條件的序列");




return 0;
}
/*
函數名稱:CreateGraph
函數功能:把頂點和邊信息讀入到表示圖的鄰接表中
輸入變量:char *data:存儲了N個關系式的字符串
VertexNode *GL : 頂點表數組
輸出變量:表示圖的頂點表數組
返回值:int :頂點數量
*/
int CreateGraph(char *data, VertexNode *GL)
{
int i, u, v;
int count = 0;//記錄頂點數量
EdgeNode *e;

for (i=0; i<MAXM; i++)//初始化圖
{
GL[i].data = i + ‘a‘;
GL[i].in = 0;
GL[i].firstEdge = NULL;
book[i] = 0;
}

for (i=0; data[i]!=‘\0‘; i+=2)//每次讀取兩個變量
{
u = data[i] - ‘a‘; //字母轉換為數字,‘a‘相應0,‘b‘相應1。以此類推
v = data[i+1] - ‘a‘;
book[u] = book[v] = 1;

e = (EdgeNode*)malloc(sizeof(EdgeNode)); //採用頭插法插入邊表結點
if (!e)
{
puts("Error");
exit(1);
}
e->adjvex = v;
e->next = GL[u].firstEdge;
GL[u].firstEdge = e;

GL[v].in++;
}

for (i=0; i<MAXM; i++)//計算頂點數量
{
if (book[i] != 0)
count++;
}

return count;
}


void PrintGraph(VertexNode *GL)//輸出圖
{
int u, v;
EdgeNode *e;

for (u=0; u<MAXM; u++)
{
printf("G[%d] = %c: ", u, GL[u].data);
for (e=GL[u].firstEdge; e!=NULL; e=e->next)//將u的鄰接點入度減1。並將入度為0的頂點入棧
{
v = e->adjvex;
printf("<%c, %c>, ", GL[u].data, GL[v].data);
}
printf("\n");
}
printf("\n");
}


/*
函數名稱:TopoLogicalSort_DFS
函數功能:拓撲排序,採用深度優先搜索獲取拓撲序列
輸入變量:char *topo:用來存儲拓撲序列的字符串
VertexNode *GL : 頂點表數組
int n:頂點個數
輸出變量:用來存儲拓撲序列的字符串
返回值:int :拓撲排序成功返回真,若存在環則返回假
*/
int TopoLogicalSort_DFS(char *topo, VertexNode *GL, int n)
{
int i, u, v, top;
int count = 0; //用於統計輸出頂點的個數
EdgeNode *e;
int Stack[MAXM];

for (top=i=0; i<MAXM; i++)//將入度為0的頂點入棧
{
if (book[i] != 0 && GL[i].in == 0)
{
Stack[top++] = i;
}
}

while (top > 0)//採用深度優先搜索獲取拓撲序列
{
u = Stack[--top];
topo[count++] = u + ‘a‘;

for (e=GL[u].firstEdge; e!=NULL; e=e->next)//將u的鄰接點入度減1,並將入度為0的頂點入棧
{
v = e->adjvex;
if (--GL[v].in == 0)
Stack[top++] = v;
}
}
topo[count] = ‘\0‘;

return (count == n);//假設count小於頂點數,說明存在環
}


/*
函數名稱:TopoLogicalSort_BFS
函數功能:拓撲排序,採用廣度優先搜索獲取拓撲序列
輸入變量:char *topo:用來存儲拓撲序列的字符串
VertexNode *GL : 頂點表數組
int n:頂點個數
輸出變量:用來存儲拓撲序列的字符串
返回值:int :拓撲排序成功返回真。若存在環則返回假
*/
int TopoLogicalSort_BFS(char *topo, VertexNode *GL, int n)
{
int i, u, v, front, rear;
EdgeNode *e;

front = rear = 0;
for (i=0; i<MAXM; i++)//將入度為0的頂點入棧
{
if (book[i] != 0 && GL[i].in == 0)
{
topo[rear++] = i + ‘a‘;
}
}

while (front < rear)//採用廣度優先搜索獲取拓撲序列
{
u = topo[front++] - ‘a‘;

for (e=GL[u].firstEdge; e!=NULL; e=e->next)//將u的鄰接點入度減1。並將入度為0的頂點入棧
{
v = e->adjvex;
if (--GL[v].in == 0)
topo[rear++] = v + ‘a‘;
}
}
topo[rear] = ‘\0‘;

return (rear == n);//假設count小於頂點數,說明存在環
}


/*
函數名稱:CreateGraph_2
函數功能:把頂點和邊信息讀入到表示圖的邊表集中
輸入變量:char *data:存儲了N個關系式的字符串
int In[]:存儲了頂點的入度信息
int first[]:指向以該頂點為弧尾的第一條邊
EdgeLib edge[]:存儲了邊信息的邊表集
輸出變量:表示圖的邊表集數組
返回值:int :頂點數量
*/
int CreateGraph_2(char *data, int In[], int first[], EdgeLib edge[])//創建一個圖
{
int i, j;
int count = 0;//記錄頂點數量

for (i=0; i<MAXM; i++)//初始化圖
{
first[i] = -1;
book[i] = 0;
In[i] = 0;
}

for (j=i=0; data[i]!=‘\0‘; i+=2,j++)//每次讀取兩個變量
{
edge[j].u = data[i] - ‘a‘; //字母轉換為數字,‘a‘相應0,‘b‘相應1,以此類推
edge[j].v = data[i+1] - ‘a‘;
book[edge[j].u] = book[edge[j].v] = 1;

edge[j].next = first[edge[j].u];
first[edge[j].u] = j;
In[edge[j].v]++;
}

for (i=0; i<MAXM; i++)//計算頂點數量
{
if (book[i] != 0)
count++;
}

return count;
}


void PrintGraph_2(int first[], EdgeLib edge[])//輸出圖
{
int i, j;

for (i=0; i<MAXM; i++)
{
printf("G[%d] = %c: ", i, i+‘a‘);
j = first[i]; //指向i的第一條邊
while (j != -1)
{
printf("<%c, %c>, ", edge[j].u+‘a‘, edge[j].v+‘a‘);
j = edge[j].next; //指向下一條邊
}
printf("\n");
}
printf("\n");
}
/*
函數名稱:TopoLogicalSort
函數功能:拓撲排序。採用廣度優先搜索獲取拓撲序列
輸入變量:char *topo:用來存儲拓撲序列的字符串
EdgeLib edge[]:存儲了邊信息的邊表集
int In[]:存儲了頂點的入度信息
int first[]:指向以該頂點為弧尾的第一條邊
int n:頂點個數
輸出變量:用來存儲拓撲序列的字符串
返回值:int :拓撲排序成功返回真。若存在環則返回假
*/
int TopoLogicalSort(char *topo, EdgeLib edge[], int In[], int first[], int n)
{
int i, u, front, rear;

front = rear = 0;
for (i=0; i<MAXM; i++)//將入度為0的頂點入棧
{
if (book[i] != 0 && In[i] == 0)
{
topo[rear++] = i + ‘a‘;
}
}

while (front < rear)//採用廣度優先搜索獲取拓撲序列
{
u = topo[front++] - ‘a‘;
for (i=first[u]; i!=-1; i=edge[i].next)
{
if (--In[edge[i].v] == 0)
topo[rear++] = edge[i].v + ‘a‘;
}
}
topo[rear] = ‘\0‘;

return (rear == n);//假設count小於頂點數。說明存在環
}


int IsTopoSeq(char *data, char *topo)//依據關系列表data。推斷topo字符串是否為拓撲序列
{
int pos[MAXM] = {0};
int i;

for (i=0; topo[i]!=‘\0‘; i++)//讀取變量下標
pos[topo[i]-‘a‘] = i;

for (i=0; data[i]!=‘\0‘; i+=2)//每次讀取兩個變量
{
if (pos[data[i]-‘a‘] > pos[data[i+1]-‘a‘])
return false;
}

return true;
}

拓撲排序之變量序列代碼