圖論所有的算法實現。DFS,BFS,Dijkstra,Floyd,Topsort,Kruskal,Prim,

參考資料:

//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--;
	}
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章