参考资料:
//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
#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 ;vvertexnum ;v++)
{
if(G->vexs[v]!=vertex) //自己到自己的顶点可以不用输出。
{
if(D1[v]vexs[v],v,D1[v]);
printf("经过的顶点为:" );
for(w=0 ;wvertexnum ;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 ;vvertexnum ;v++)
for( w=0 ;wvertexnum ;w++)
{
if(v!=w)
{
if(D2[v][w]vexs[v],G->vexs[w],v,w,D2[v][w]);
printf("经过的顶点为:" );
for(u=0 ;uvertexnum ;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 ;vvertexnum; v++)
printf("%c ",G->vexs[ result[v] ]);
printf("\n\n");
}
Destroy(G);
return 1;
}
#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
#include
#include
#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 ;ivertexnum ;i++ )
{
if(G->arcs[n][i].adj !=0 && G->arcs[n][i].adj !=INFINITY)
count++;
}
for (i=0 ;ivertexnum ;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; ivertexnum ; 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;ivertexnum ;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 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 ;ivertexnum ;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 ;jvertexnum ;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 vertexnum ;i++)
{
if( closedge[i].lowcost>0 && closedge[i].lowcost !=INFINITY && closedge[i].lowcost (* ( 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; jvertexnum ;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;ivexs[ 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 ; vvertexnum ;v++)
{
final[v]=false;
D[v]=G->arcs[v0][v].adj;
for(w=0 ; wvertexnum ;w++)
{
Path[v][w]=-1;
}
if(D[v] vertexnum; i++)
{
int min=INFINITY;
for(w=0 ; wvertexnum ;w++)
{
if( !final[w])
{
if(D[w] vertexnum ;w++)
{
if( !final[w] && min+G->arcs[v][w].adj 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 ;vvertexnum ;v++)
for(w=0 ;wvertexnum ;w++)
{
D[v][w]=G->arcs[v][w].adj;
for(u=0; uvertexnum ;u++)
Path[v][w][u]=-1;
if( D[v][w]vertexnum ;u++)
for(v=0 ;vvertexnum ;v++)
for(w=0 ;wvertexnum ;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 ;ivertexnum ;i++)
{
if(Path[v][u][i]!=-1)
Path[v][w][i]=Path[v][u][i];
else
break;
}
int j;
for(j=1; jvertexnum ;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 ;ivertexnum ;i++)
visit[i]=false;
int count=0; //如果AOE网顶点为n,每个顶点到Vk都不存在有向边的时候,则表示该顶点无前驱。
//count表示每一顶点到Vk无有向边的个数,此时count=n-1即无前驱
int number=G->vertexnum; //待遍历顶点的个数
i=0;
for(v=0 ; vvertexnum ;v++)
{
if( !visit[v])
{
count=0;
for( w=0 ;wvertexnum ;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(ivertexnum)
{
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 ; ivertexnum ;i++ )
scanf("%c",& G->vexs[i]) ;
fgets(buf,1024,stdin);
//setbuf(stdin,NULL); 用这个替换上面的不行,好像有一个%*c忘了,查查
char v1 ,v2;
int w;
//弧权值的初始化
for(i=0;ivertexnum ;i++)
for(j=0;jvertexnum ;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 ; iarcsnum ;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 ; ivertexnum ;i++ )
G->vexs[i]='a'+i ;
char v1 ,v2;
int w;
//弧权值的初始化
for(i=0;ivertexnum ;i++)
for(j=0;jvertexnum ;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 ; ivertexnum ;i++ )
G->vexs[i]='a'+i ;
char v1 ,v2;
int w;
//弧权值的初始化
for(i=0;ivertexnum ;i++)
for(j=0;jvertexnum ;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 ;ivertexnum ;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");
}
}
#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
#include
#include
#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
//并查集数据结构主要用于求连通子图,最小生成树的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=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--;
}
}