拓扑排序之变量序列代码
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;
}
轉載于:https://www.cnblogs.com/liguangsunls/p/7257150.html
總結
以上是生活随笔為你收集整理的拓扑排序之变量序列代码的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 物联网网络编程和web编程
- 下一篇: bzoj4196:[Noi2015]软件