參考資料:
//http://blog.csdn.net/cxllyg/article/details/7606184
//http://2728green-rock.blog.163.com/blog/static/43636790200901211848284/
//http://blog.csdn.net/qiuyoungster/article/details/7846169
//main.c
//http://blog.csdn.net/cxllyg/article/details/7606184
//http://2728green-rock.blog.163.com/blog/static/43636790200901211848284/
//http://blog.csdn.net/qiuyoungster/article/details/7846169
#include<stdio.h>
#include"GraphAdjacencyMatrix.h"
//注意程序運行時,選擇1,其他的圖沒有去實現。否則會出現段錯誤。
int main()
{
pGraph G=CreateGraph(G);
PrintGraph(G);
char vertex='d';
char v1='b';
char v2='c';
//int w=10;
/*
Degree(G , v);
Isadjacency(G, v1, v2);
InsertVertex( G ,v);
InsertArc( G,v1, v2, w);
*/
PrintGraph(G);
printf("******DFSTraverseInitial******:\n\n");
DFSTraverseInitial(G);
printf("input a char: %c ,以該字符爲起始節點的深度廣度優先遍歷\n",vertex);
//scanf("%c",&v);
printf("******DFSTraverse******:");
DFSTraverse(G,vertex);
printf("******BFSTraverse******:");
BFSTraverse(G,vertex);
printf("******MiniSpanTree_Prim******:\n") ;
MiniSpanTree_Prim(G ,'a');
printf("\n\n");
printf("******MiniSpanTree_Kruskal******:\n") ;
MiniSpanTree_Kruskal(G );
printf("\n\n");
printf("******Dijkstra 求單源最短路徑*******:\n\n");
int D1[G->vertexnum];
int Path1[G->vertexnum][G->vertexnum];
vertex='e';
ShortestPath_DIJ(G,vertex,D1,Path1);
int v,w,u;
for( v=0 ;v<G->vertexnum ;v++)
{
if(G->vexs[v]!=vertex) //自己到自己的頂點可以不用輸出。
{
if(D1[v]<INFINITY)
{
printf("源點%c到頂點 %c的最短距離 D[%d]= %d\n",vertex,G->vexs[v],v,D1[v]);
printf("經過的頂點爲:" );
for(w=0 ;w<G->vertexnum ;w++)
{
if(Path1[v][w]!=-1)
{
printf("%c ",G->vexs[ Path1[v][w] ]) ;
}
else
break;
}
}
else
printf("源點%c到頂點 %c是不可達的!" ,vertex,G->vexs[v]);
printf("\n\n");
}
}
printf("*****Floyd 求任意頂點對之間的最短路徑******:\n\n");
int D2[G->vertexnum][G->vertexnum];
int Path2[G->vertexnum][G->vertexnum][G->vertexnum];
ShortestPath_FLOYD(G,D2,Path2);
for( v=0 ;v<G->vertexnum ;v++)
for( w=0 ;w<G->vertexnum ;w++)
{
if(v!=w)
{
if(D2[v][w]<INFINITY )
{
printf("頂點%c到頂點 %c的最短距離 D[%d][%d]= %d\n",G->vexs[v],G->vexs[w],v,w,D2[v][w]);
printf("經過的頂點爲:" );
for(u=0 ;u<G->vertexnum ;u++)
{
if(Path2[v][w][u]!=-1)
{
printf("%c ",G->vexs[ Path2[v][w][u] ]) ;
}
else
break;
}
}
else
printf("頂點%c到頂點 %c是不可達的!" ,G->vexs[v],G->vexs[w]);
printf("\n\n");
}
}
printf("*****TopSort******:\n\n" );
int result[G->vertexnum];
if( TopSort(G,result) ) //需要判斷以下,否則由於result[i]未初始化,對於TopSort存在環的情況下,result數組的值是未知的,
//當調用G->vexs[ result[v] ]會出現越界或者段錯誤。
{
for (v=0 ;v<G->vertexnum; v++)
printf("%c ",G->vexs[ result[v] ]);
printf("\n\n");
}
Destroy(G);
return 1;
}
//GraphAdjacencyMatrix.h
#ifndef _GRAPHADJACENCYMATRIX_H_
#define _GRAPHADJACENCYMATRIX_H_
#define MAX_VERTEX_NUM 50 //最大頂點數
#define INFINITY 65535 //65535代表無窮大
#define true 1
#define false 0
#define DEBUG
extern numTree;
extern int parent[MAX_VERTEX_NUM];
typedef int bool;
typedef int EdgeType ;
typedef char VertexType;
typedef int InfoType ;
typedef int VRType;
//DG是有向圖,DN是有向網,UDG是無向圖,UDN是無向網
//網和圖的區別在於弧有沒有權值
typedef enum {DG,DN,UDG,UDN}GraphKind ;
//弧的定義
typedef struct Arcs
{
EdgeType adj; //EdgeType是邊關係類型
//對於無權圖,用1,0表示是否相鄰
//對於帶全圖,則爲權值類型
InfoType *info;//弧相關信息的指針
}ArcCell, AdjMatrix[MAX_VERTEX_NUM][MAX_VERTEX_NUM] ;
//圖的鄰接矩陣存儲結構
typedef struct GraphAdjacencyMatrix
{
VertexType vexs[MAX_VERTEX_NUM];
AdjMatrix arcs;
int vertexnum;
int arcsnum;
GraphKind kind;
}Graph,*pGraph;
bool visited[MAX_VERTEX_NUM] ;
struct closedge //Prim算法的輔助數組
{
VertexType adjvex;
VRType lowcost;
} closedge[MAX_VERTEX_NUM];
typedef struct Edge //Kruskal算法的輔助數組
{
int begin;
int end;
int weight;
}Edge[MAX_VERTEX_NUM] ;
pGraph CreateGraph();
pGraph CreateDN();
pGraph CreateDG();
pGraph CreateUDG();
pGraph CreateUDN();
pGraph CreateAOE();
int Degree(pGraph G ,VertexType v);
int Isadjacency(pGraph G, VertexType v1, VertexType v2);
bool InsertVertex(pGraph G ,VertexType v);
bool InsertArc(pGraph G,VertexType v1, VertexType v2, int w);
int Locate(pGraph G , char ch);
void PrintGraph(pGraph G);
void DFSTraverse(pGraph G, char v);
void DFSTraverseInitial(pGraph G);
void DFS(pGraph G ,int i);
void BFS(pGraph G ,int location);
void BFSTraverse(pGraph G ,char v);
void MiniSpanTree_Prim(pGraph G ,VertexType v);
int minimum(pGraph G,struct closedge closedge[]);
void MiniSpanTree_Kruskal(pGraph G);
int cmpstruct(const void * a, const void *b);
bool IsConnected( Edge edge, int k);
void MiniSpanTree_Sollin(pGraph G );
void Visit(char ch);
bool TopSort(pGraph G, int result[]) ;
void ShortestPath_DIJ(pGraph G,char vertexs,int D[],bool Path[][G->vertexnum]);
void ShortestPath_FLOYD(pGraph G,int D[][G->vertexnum],bool Path[][G->vertexnum][G->vertexnum]);
#endif
//GraphAdjacencyMatrix.c
#include<stdio.h>
#include<malloc.h>
#include"GraphAdjacencyMatrix.h"
#include"UnionFind.h"
#include"LinkQueue.h"
int Degree(pGraph G ,VertexType v)
{
int n=Locate(G ,v) ;
if(n==-1)
{
printf("dont exist the vertexs %c\n",v);
return -1;
}
else
{
int count=0 ,i;
if(G->kind==DN) //對於其他種類的圖,暫時不寫,這樣的話,可擴展性強
{
for (i=0 ;i<G->vertexnum ;i++ )
{
if(G->arcs[n][i].adj !=0 && G->arcs[n][i].adj !=INFINITY)
count++;
}
for (i=0 ;i<G->vertexnum ;i++)
{
if(G->arcs[i][n].adj !=0 && G->arcs[i][n].adj !=INFINITY )
count++;
}
return count ;
}
}
}
/*
*判斷兩個頂點是否相鄰,如果沒有該頂點返回-1;
*否則,如果是帶權的網返回,權值,通過判斷返回值來判斷是否相鄰,例如權值爲INFINITY,0則爲不相鄰;
* 如果是無權的圖,則,返回值爲1,爲相鄰;爲0爲不相鄰
* */
int Isadjacency(pGraph G, VertexType v1, VertexType v2)
{
int m=Locate(G,v1);
int n=Locate(G,v2);
if(m==-1 || n==-1)
return -1;
return G->arcs[m][n].adj;
}
/*
*
*插入一個頂點
* */
bool InsertVertex(pGraph G ,VertexType v)
{
int m=Locate(G,v);
if( m!=-1)
{
printf("the same vertex %c exist\n",v);
return false;
}
else
{
if(G->kind==DN)
{
int i;
G->vexs[G->vertexnum] =v;
for(i=0; i<G->vertexnum ; i++)
G->arcs[G->vertexnum][i].adj =INFINITY;
for(i=0; i< G->vertexnum ; i++)
G->arcs[i][G->vertexnum].adj=INFINITY;
G->arcs[G->vertexnum][G->vertexnum].adj=0;
G->vertexnum++;
return true;
}
}
}
/*
*從輸入的頂點開始遍歷
* */
void DFSTraverse(pGraph G, char v)
{
int i;
int m=Locate(G,v);
if(m==-1)
printf("Graph doesn't have the vertexs %c\n",v);
for (i =0;i<G->vertexnum ;i++)
visited[i]=false;
DFS(G,m);
for(i=0 ; i< G->vertexnum ; i++ )
{
if( !visited[i])
{
DFS(G,i);
}
}
printf("\n");
}
/*
* 每次從第一個頂點開始遍歷
* */
void DFSTraverseInitial(pGraph G) //每次對第一個第一個節點進行遍歷
{
int i;
for( i=0 ;i< G->vertexnum ;i++)
visited[i]=false;
for( i=0 ;i <G->vertexnum ; i++) //對未訪問的頂點遞歸調用DFS,如果是連通圖則只執行一次
{
if(! visited[i])
DFS(G ,i);
}
printf("\n");
}
void DFS(pGraph G ,int i)
{
visited[i]=true;
Visit(G->vexs[i]);
int j;
for( j=0 ;j< G->vertexnum ;j++)
{
if(G->arcs[i][j].adj !=INFINITY && G->arcs[i][j].adj !=0 && !visited[j])
DFS(G, j);
}
}
void BFSTraverse(pGraph G ,char v)
{
int i;
int m=Locate(G,v);
if(m==-1)
printf("Graph doesn't have the vertexs %c\n",v);
for ( i=0 ;i<G->vertexnum ;i++)
visited[i]=false;
BFS(G,m);
for( i=0 ;i< G->vertexnum ;i++)
{
if(!visited[i])
BFS(G, i);
}
printf("\n");
}
void BFS(pGraph G ,int location)
{
pLinkQueue q=InitLinkQueue();
EnLinkQueue(q,location);
visited[location]=true;
while(!IsLinkQueueEmpty(q) )
{
int i;
DeLinkQueue(q, &i);
Visit(G->vexs[i]);
//visited[i]=true; //如果是每次出隊時,表示遍歷過,會使有些元素重複入隊,
//從而遍歷的結果使有些結點重複輸出,所以應該時每次入隊時,表示遍歷過
int j;
for( j=0;j< G->vertexnum ;j++)
{
if(G->arcs[i][j].adj !=INFINITY && G->arcs[i][j].adj !=0 && !visited[j])
{
EnLinkQueue(q,j);
visited[j]=true;
}
}
}
DestroyLinkQueue(q);
}
/*
*無向圖的最小生成樹Prim算法
* */
void MiniSpanTree_Prim(pGraph G ,VertexType v)
{
//int lowcost[G->vertexnum];
int m=Locate(G,v);
if(m==-1)
{
printf(" Graph doesn't have the vertexs %c\n" ,v);
return ;
}
int i;
for( i=0 ; i< G->vertexnum ;i++)
{
if(i != m)
{
closedge[i].adjvex=G->vexs[m];
closedge[i].lowcost=G->arcs[i][m].adj;
}
}
int totalWeight=0;//表示最小生成樹的權值大小
closedge[m].lowcost=0 ;//初始化,U={u}
for(i=1; i<=G->vertexnum-1 ;i++)
{
int k=minimum(G, closedge);
printf("%c %d %c\n",closedge[k].adjvex,closedge[k].lowcost ,G->vexs[k]);
totalWeight+=closedge[k].lowcost;//
closedge[k].lowcost=0 ; //第k頂點併入U集
int j;
for( j=0 ;j<G->vertexnum ;j++)
{
if(G->arcs[k][j].adj < closedge[j].lowcost)
{
closedge[j].adjvex=G->vexs[k];
closedge[j].lowcost=G->arcs[k][j].adj ;
}
}
}
printf("MiniSpanTree_Prim 求得的最小權值是%d\n",totalWeight);
}
int minimum(pGraph G,struct closedge closedge[])
{
int i=0;
int temp=INFINITY;
int index;
for( i=0 ;i <G->vertexnum ;i++)
{
if( closedge[i].lowcost>0 && closedge[i].lowcost !=INFINITY && closedge[i].lowcost <temp)
{
temp=closedge[i].lowcost;
index=i;
}
}
return index; //很可能這裏出錯,即上面的循環沒有找到滿足的條件
}
/*
*無向圖的最小生成樹的Kruskal算法
* */
int cmpstruct(const void * a, const void *b)
{
return ( *( struct Edge *)a).weight > (* ( struct Edge *)b).weight ? 1:-1;
}
int GetEdgeInformation(pGraph G, Edge edge)
{
int i,j;
int undirectedEdgeNum=0;
for(i=0 ; i< G->vertexnum ;i++) //獲取每條無向邊的信息
for(j=i+1; j<G->vertexnum ;j++)
{
if(G->arcs[i][j].adj!=INFINITY)
{
edge[undirectedEdgeNum].begin=i;
edge[undirectedEdgeNum].end=j;
edge[undirectedEdgeNum].weight=G->arcs[i][j].adj;
undirectedEdgeNum++;
}
}
return undirectedEdgeNum;
}
void MiniSpanTree_Kruskal(pGraph G)
{
Edge edge;
int undirectedEdgeNum=GetEdgeInformation(G, edge); //無向邊的數目(如兩個頂點a-b存在一條有向邊,只記錄一個a-b而b-a不記錄)
//對無向圖的所有邊按權值排序
qsort(edge,undirectedEdgeNum ,sizeof(edge[0]),cmpstruct);
int k=0; //k表示選擇哪一條邊,進行Kruskal
int totalWeight=0; //表示最小生成樹的權值大小
int edgenum=0; //表示通過Kruskal算法已經加入邊的數目
int flag=0;
MakeSet(G->vertexnum) ; //集合的初始化,每個結點剛開始時,獨立的屬於一個集合
int i;
for(i=1;i<undirectedEdgeNum ; i++)
{
if( ! IsConnected(edge ,k) ) //判斷把第k條邊加入會不會形成迴路,這個是通過並查集實現的,也可以採用DFS
{
printf("%c %d %c\n",G->vexs[ edge[k].begin ] ,edge[k].weight, G->vexs[ edge[k].end ]);
totalWeight+=edge[k].weight;
edgenum++;
}
else
{
//表示加入該邊,會形成迴路
}
k++;
if(edgenum == G->vertexnum-1) //最小生成樹條件:邊數=頂點數-1
{
flag = 1;
break;
}
}
if(flag)
printf("MiniSpanTree_Kruskal 求得的最小權值是%d\n",totalWeight);
else
printf("生成最小生成樹失敗!該網非連通!\n");
}
bool IsConnected( Edge edge, int k)
{
if( Find(edge[k].begin) == Find(edge[k].end) )
return true;
else
{
Union(edge[k].begin, edge[k].end );
return false;
}
}
/*
* Dijkstra 算法求單源最短路徑,即某個頂點到圖中任意頂點的最短距離
* */
// v0(vertexs) 表示源點
// D[i]表示源點v0到頂點i的最短路徑長度
// Path[v][]表示源點v0到達頂點v的路徑,若Path[v][w]=true,表示頂點w是從v0到v的最短路徑上的頂點
// final[v]=true表示求得了從v0到v的最短路徑,即把v加入了集合S中
void ShortestPath_DIJ(pGraph G,char vertexs,int D[],int Path[][G->vertexnum])
{
bool final[G->vertexnum];
int v0=Locate(G,vertexs);
if(v0==-1)
{
printf("the Graph don't have the vertexs %c",v0);
return;
}
//初始化工作
int v,w;
for(v=0 ; v<G->vertexnum ;v++)
{
final[v]=false;
D[v]=G->arcs[v0][v].adj;
for(w=0 ; w<G->vertexnum ;w++)
{
Path[v][w]=-1;
}
if(D[v] <INFINITY) //有可能無法到達
{
Path[v][0]=v0; //到任意頂點的最短路徑,源點必包含在裏面
Path[v][1]=v; //到任意頂點的最短路徑,你所要到的頂點最終一定包含在裏面
}
}
// 剛開始運轉時,集合S中只有源點v0,
final[v0]=true;
D[v0]=0;
int i;
//每次循環,求得到一個頂點的最短路徑,加入到集合S中
for( i=1; i<G->vertexnum; i++)
{
int min=INFINITY;
for(w=0 ; w<G->vertexnum ;w++)
{
if( !final[w])
{
if(D[w] <min)
{
v=w;
min=D[w];
}
}
}
final[v]=true; //離源點v0最近的的頂點v加入到S中
for( w=0 ;w< G->vertexnum ;w++)
{
if( !final[w] && min+G->arcs[v][w].adj <D[w])//更新最短路徑和距離
{
D[w]=min+G->arcs[v][w].adj;
int j;
for(j=0 ; j< G->vertexnum ;j++)
{
if(Path[v][j]!=-1)
Path[w][j]=Path[v][j];
else
break;
}
Path[w][j++]=w; //P[w]=P[v]+P[w]
}
}
}
}
//弗洛伊德算法求每一對頂點間的最短路徑
void ShortestPath_FLOYD(pGraph G,int D[][G->vertexnum],int Path[][G->vertexnum][G->vertexnum])
{
//p[v][w][i]表示當前求得的頂點v到頂點w的最短路徑中的第i+1個頂點,因爲下標從0開始
//D[v][w]表示頂點v到頂點w的最短路徑長度。
//初始化工作
int v,w,u;
for(v=0 ;v<G->vertexnum ;v++)
for(w=0 ;w<G->vertexnum ;w++)
{
D[v][w]=G->arcs[v][w].adj;
for(u=0; u<G->vertexnum ;u++)
Path[v][w][u]=-1;
if( D[v][w]<INFINITY )
{
Path[v][w][0]=v;
Path[v][w][1]=w;
}
}
//採用動態規劃的方法
for(u=0; u<G->vertexnum ;u++)
for(v=0 ;v<G->vertexnum ;v++)
for(w=0 ;w<G->vertexnum ;w++)
{
if(D[v][u] < INFINITY && D[u][w] < INFINITY && D[v][u]+D[u][w] < D[v][w])
{
//更新D
D[v][w]=D[v][u]+D[u][w];
int i;
//更新Path
for(i=0 ;i<G->vertexnum ;i++)
{
if(Path[v][u][i]!=-1)
Path[v][w][i]=Path[v][u][i];
else
break;
}
int j;
for(j=1; j<G->vertexnum ;j++ )
{
if(Path[u][w][j]!=-1)
Path[v][w][i++]=Path[u][w][j];
else
break;
}
}
}
}
/*
*TopSort思想:
*(1) 判斷頂點是否有前驅
*(2) 刪除頂點和關聯與該頂點的所有邊 注:該方法沒有采用刪除的策略,而是通過visit數組來實現,
* 即把visit[i]置爲true,此時不對它相關聯的邊訪問即可
* 注:要對於是否存在TopSort即有沒有環進行判斷
* */
bool TopSort(pGraph G, int result[]) //result[] :把TopSort結果依次存入
{
int v,w;
int i;
bool visit[G->vertexnum];//頂點是否已經已經遍歷過
for(i=0 ;i<G->vertexnum ;i++)
visit[i]=false;
int count=0; //如果AOE網頂點爲n,每個頂點到Vk都不存在有向邊的時候,則表示該頂點無前驅。
//count表示每一頂點到Vk無有向邊的個數,此時count=n-1即無前驅
int number=G->vertexnum; //待遍歷頂點的個數
i=0;
for(v=0 ; v<G->vertexnum ;v++)
{
if( !visit[v])
{
count=0;
for( w=0 ;w<G->vertexnum ;w++)//判斷頂點是否有前驅
{
if(!visit[w])
{
if(w==v)
continue;
else if( G->arcs[w][v].adj==INFINITY )
count++;
else
break;
}
}
if(count==number-1)//此時該頂點沒有前驅,可以輸出
{
visit[v]=true;
number--;
result[i++]=v;
v=0; //每次加入一個頂點,得重新開始
}
}
}
if(i<G->vertexnum)
{
printf("該AOE網存在環,不存在TopSort\n");
return false;
}
return true;
}
void Visit(char ch)
{
printf("%c ",ch);
}
/*
*
*在頂點v1和v2之間插入一個權值爲w的弧
* */
bool InsertArc(pGraph G,VertexType v1, VertexType v2, int w)
{
int m=Locate(G,v1);
int n=Locate(G,v2);
if(m==-1 || n==-1)
{
printf("don't exist the vertexs %c or %c",v1,v2);
return false;
}
if(G->arcs[m][n].adj==INFINITY || G->arcs[m][n].adj==0)
{
G->arcs[m][n].adj=w;
G->arcsnum++;
return true;
}
else
{
printf("the arcs exist\n");
return false;
}
}
/*
*創建一個圖,然後選擇創建什麼樣的圖
* */
pGraph CreateGraph()
{
printf("0:DG 1:DN 2:UDG 3:UDN 4:AOE\n");
printf("please input the Graph's kind:");
int kind;
scanf(" %d",&kind);
switch(kind)
{
case 0: return CreateDG();
case 1: return CreateDN();
case 2: return CreateUDG();
case 3: return CreateUDN();
case 4: return CreateAOE(); //其實主要爲了測試,添加上去的數據
default:
printf("the input is error\n");
CreateGraph();
}
}
/*
*創建一個有向網
* */
#if 0
pGraph CreateDN( )
{
char buf[1024]; //程序的魯壯性較好,當輸入輸入出現錯誤時,把行緩衝中的數據按照要求讀入。
//fflush在linux下主要指定輸出流,在windows下可以,那是因爲winwods下VC做了封裝
pGraph G=(pGraph) malloc(sizeof(Graph)) ;
G->kind=1;
printf("please input the vertexnum and arcsnum:");
scanf("%d %d",& G->vertexnum,& G->arcsnum) ;
fgets(buf,1024,stdin);
printf("input the vertexs:");
int i,j;
for(i=0 ; i<G->vertexnum ;i++ )
scanf("%c",& G->vexs[i]) ;
fgets(buf,1024,stdin);
//setbuf(stdin,NULL); 用這個替換上面的不行,好像有一個%*c忘了,查查
char v1 ,v2;
int w;
//弧權值的初始化
for(i=0;i<G->vertexnum ;i++)
for(j=0;j<G->vertexnum ;j++)
{
if(i!=j)
{
G->arcs[i][j].adj=INFINITY;
G->arcs[i][j].info=NULL;
}
else
{
G->arcs[i][j].adj=0;
G->arcs[i][j].info=NULL;
}
}
for(i=0 ; i<G->arcsnum ;i++)
{
printf("input the DN的每個頂點i,頂點j和權值\n" );
scanf("%c %c %d",&v1,&v2,& w);
fgets(buf,1024,stdin);
int m=Locate(G,v1);
int n=Locate(G,v2);
if(m==-1 || n==-1)
{
printf("input is error\n");
}
G->arcs[m][n].adj=w;
}
return G;
}
#endif
//測試用例
pGraph CreateDN( )
{
pGraph G=(pGraph) malloc(sizeof(Graph)) ;
G->kind=1;
G->vertexnum=6; //6
G->arcsnum=20; //20
int i,j;
for(i=0 ; i<G->vertexnum ;i++ )
G->vexs[i]='a'+i ;
char v1 ,v2;
int w;
//弧權值的初始化
for(i=0;i<G->vertexnum ;i++)
for(j=0;j<G->vertexnum ;j++)
{
if(i!=j)
{
G->arcs[i][j].adj=INFINITY;
G->arcs[i][j].info=NULL;
}
else
{
G->arcs[i][j].adj=0;
G->arcs[i][j].info=NULL;
}
}
// 20條邊
/*
a b 6
b a 6
a d 5
d a 5
a c 1
c a 1
b c 5
c b 5
d c 5
c d 5
b e 3
e b 3
c e 6
e c 6
c f 4
f c 4
d f 2
f d 2
e f 6
f e 6
*/
G->arcs[0][1].adj=6 ;
G->arcs[1][0].adj=6 ;
G->arcs[0][3].adj=5 ;
G->arcs[3][0].adj=5 ;
G->arcs[0][2].adj=1 ;
G->arcs[2][0].adj=1 ;
G->arcs[1][2].adj=5 ;
G->arcs[2][1].adj=5 ;
G->arcs[2][3].adj=5 ;
G->arcs[3][2].adj=5 ;
G->arcs[1][4].adj=3 ;
G->arcs[4][1].adj=3 ;
G->arcs[2][4].adj=6 ;
G->arcs[4][2].adj=6 ;
G->arcs[2][5].adj=4 ;
G->arcs[5][2].adj=4 ;
G->arcs[3][5].adj=2 ;
G->arcs[5][3].adj=2 ;
G->arcs[4][5].adj=6 ;
G->arcs[5][4].adj=6 ;
return G;
}
//測試用例
pGraph CreateAOE( )
{
pGraph G=(pGraph) malloc(sizeof(Graph)) ;
G->kind=1;
G->vertexnum=6; //6
G->arcsnum=20; //20
int i,j;
for(i=0 ; i<G->vertexnum ;i++ )
G->vexs[i]='a'+i ;
char v1 ,v2;
int w;
//弧權值的初始化
for(i=0;i<G->vertexnum ;i++)
for(j=0;j<G->vertexnum ;j++)
{
if(i!=j)
{
G->arcs[i][j].adj=INFINITY;
G->arcs[i][j].info=NULL;
}
else
{
G->arcs[i][j].adj=0;
G->arcs[i][j].info=NULL;
}
}
//8條邊,用於AOE網TopSort的測試
/*
a d 5
d c 5
d f 2
b c 5
b e 3
c e 6
c f 4
e f 6
*/
G->arcs[0][3].adj=5 ;
G->arcs[3][2].adj=5 ;
G->arcs[3][5].adj=2 ;
G->arcs[1][2].adj=5 ;
G->arcs[1][4].adj=3 ;
G->arcs[2][4].adj=6 ;
G->arcs[2][5].adj=4 ;
G->arcs[4][5].adj=6 ;
return G;
}
pGraph CreateDG()
{
}
pGraph CreateUDG()
{
}
pGraph CreateUDN()
{
}
/*
*定位頂點ch在頂點數組的位置
* */
int Locate(pGraph G , char ch)
{
int i;
for( i=0 ;i<G->vertexnum ;i++)
{
if( G->vexs[i]==ch)
return i;
}
return -1;
}
/*
*銷燬圖,釋放圖的空間
* */
void Destroy(pGraph G)
{
free(G);
}
/*
*圖的鄰接矩陣的輸出
* */
void PrintGraph(pGraph G)
{
int i,j;
for(i=0;i< G->vertexnum ;i++)
{
for( j=0 ;j< G->vertexnum ;j++)
{
printf(" %d ", G->arcs[i][j].adj);
}
printf("\n");
}
}
//LinkQueue.h
#ifndef _LINKQUEUE_H_
#define _LINKQUEUE_H_
//隊列的鏈式存儲結構
//當CHAR定義時,用字符的處理模式
//當CHAR沒有被定義時,採用整數處理模式
#define INT
#ifdef INT
//數據類型的定義
typedef int DataType;
#else
typedef char Datatype;
#endif
//隊列節點存儲結構
typedef struct Node
{
DataType data;
struct Node *next;
} Node, *pNode;
//隊列存儲結構
typedef struct Queue
{
pNode front;
pNode rear;
int queuesize;
} LinkQueue, *pLinkQueue;
pLinkQueue InitLinkQueue();
int IsLinkQueueEmpty(pLinkQueue q);
int GetLinkQueueLength(pLinkQueue q);
void EnLinkQueue(pLinkQueue q, DataType x);
void DeLinkQueue(pLinkQueue q,DataType *x);
int GetHead(pLinkQueue q,DataType *x);
void print(DataType data);
void LinkQueueTraverse(pLinkQueue q, void (*Visit) (DataType data) );
void ClearLinkQueue(pLinkQueue q);
void DestroyLinkQueue(pLinkQueue q);
#endif
LinkQueue.c
#include<stdio.h>
#include<malloc.h>
#include<stdlib.h>
#include"LinkQueue.h"
pLinkQueue InitLinkQueue()
{
pLinkQueue q=(pLinkQueue ) malloc(sizeof(LinkQueue)) ;
if(!q)
{
q->front=NULL;
q->rear=NULL;
q->queuesize=0;
}
return q;
}
int IsLinkQueueEmpty(pLinkQueue q)
{
if(q->queuesize ==0)
return 1;
else
return 0;
}
int GetLinkQueueLength(pLinkQueue q)
{
return q->queuesize;
}
void EnLinkQueue(pLinkQueue q, DataType x)
{
if( q )
{
pNode p=(pNode ) malloc(sizeof(Node) ) ;
p->data=x;
p->next=NULL;
if(q->queuesize==0) //剛開始時隊列爲空時,對隊頭指針進行賦值
{
q->front=p;
q->rear=p;
}
else
{
q->rear->next=p;
q->rear=p;
}
q->queuesize++;
}
}
void DeLinkQueue(pLinkQueue q,DataType *x)
{
if(q->queuesize==0)
{
printf("the queue is null,can't get anything\n");
}
else
{
if(q->front==q->rear) //只有一個節點時,無節點的情況上面已經考慮了
{
*x=q->front->data;
free(q->front);
q->front=NULL;
q->rear=NULL;
}
else
{
pNode p=q->front;
*x=p->data;
q->front=q->front->next;
free(p);
}
q->queuesize--;
}
}
int GetHead(pLinkQueue q,DataType *x)
{
if(q->queuesize==0)
return 0 ;
else
{
*x= q->front->data;
return 1 ;
}
}
void print(DataType data)
{
printf("%d ",data);
}
void LinkQueueTraverse(pLinkQueue q, void (*Visit) (DataType data) )
{
if(!q)
exit(-1);
pNode p=q->front ;
if(!p)
{
printf("the LinkQueue is null\n");
return ;
}
while(p)
{
Visit(p->data);
p=p->next ;
}
}
void ClearLinkQueue(pLinkQueue q)
{
DataType data;
while(q->queuesize)
{
DeLinkQueue(q,&data);
}
}
void DestroyLinkQueue(pLinkQueue q)
{
if(q->queuesize!=0)
ClearLinkQueue(q) ;
free(q);
}
//UnionFind.h
#ifndef _UNIONFIND_H_
#define _UNIONFIND_H_
void MakeSet(int n);
int Find(int i);
void Union(int i ,int j);
#endif
//UnionFind.c
//並查集數據結構主要用於求連通子圖,最小生成樹的kruskal算法和最近公共祖先(Least Common Ancestors,LCA,等價類問題)
//前提條件:任意兩個集合不能相交.
// (1) 不相交集合的並
// (2) 查找某個集合元素所屬的集合
#include"UnionFind.h"
#define MAX_VERTEX_NUM 50 //最大頂點數
int parent[MAX_VERTEX_NUM] ;
int numTree;
/*
*創建集合,並對集合初始化
* */
void MakeSet(int n)
{
int i;
for( i=0 ;i<n ;i++)
parent[i]=-1; //從而表示初始化時每個結點都是根節點
}
int Find(int i)
{
int p=i;
while( parent[i]>=0 )
i=parent[i]; //此時退出循環找到了根節點i
while(parent[p]>=0) //使路徑上的結點都指向根節點
{
int t=parent[p];
parent[p]=i;
p=t;
}
return i;
}
void Union(int i ,int j)
{
int pID=Find(i);
int qID=Find(j);
if(pID==qID)
return ;
else
{
if(parent[pID] < parent[qID]) //如 -9 ,-5
{
parent[pID]=parent[pID]+parent[qID];
parent[qID]=pID;
}
else
{
parent[qID]=parent[pID]+parent[qID];
parent[pID]=qID;
}
numTree--;
}
}