十字链表:整合了邻接表和逆邻接表,即容易找到v1的头,也能找到v1的尾,因而容易求得顶点的出度和入度。
边集数组:由两个一维数组构成,一个存储顶点信息,一个存储边的信息。这个边数组每个数据元素由一条边的起点下标,终点下标和权组成。
图的遍历:从图中一个顶点开始访遍图中其余的顶点,且使每个顶点仅访问一次,这一过程叫做图的遍历。
typedef int Boolean;
Boolean visited[MAX];
//邻接矩阵的深度优先递归算法
void DFS(MGraph G,int i)
{
int j;
visited[i] = TRUE;
printf("%c",G.vexs[i]);
for(j = 0;j < G.numVertexes;j++)
{
if(G.arc[i][j] == 1 &&!visited[j])
DFS(G,j);
}
}
//邻接矩阵的深度遍历操作
void DFSTraverse(MGraph G)
{
int i;
for(i = 0;i < G.numVertexes;i++)
visited[i] = FALSE; //初始所以顶点状态都是未访问过状态
for(i = 0;i <G.numVertexes;i++)
if(!visited[i]) //对未访问过的顶点调用DFS,若是连通图,只会执行一次
DFS(G,i);
}
//邻接表的深度优先递归遍历算法
void DFS(GraphAdjList GL,int i)
{
EdgeNode *p;
visited[i] = TRUE;
printf("%c",GL->adjList[i].data);
p = GL->adjList.firstedge;
while(p)
{
if(!visited[p->adjvex])
DFS(GL,p->adjvex);
p = p->next;
}
}
//邻接表的深度遍历操作
void DFSTraverse(GraphAdjList GL)
{
int i;
for(i = 0;i < GL->numVertexes;i++)
visited = FALSE;
for(i = 0;i < GL->numVertexes;i++)
if(!visited[i])
DFS(GL,i);
}
//邻接矩阵的广度遍历算法
void BFSTraverse(MGraph G)
{
int i,j;
Queue Q;
for(i = 0;i < G.numVertexes;i++)
visited[i] = FALSE;
InitQueue(&Q); //初始化辅助队列
for(i = 0;i < G.numVertexes;i++)
{
if(!visited[i])
{
visited[i] = TRUE;
printf("%c",G.vexs[i]);
EnQueue(&Q,i); //将顶点入队列
while(!QueueEmpty(Q))
{
DeQueue(&Q,&i); //将队中元素出队列,赋值给i
for(j = 0;j < G.numVertexes;j++)
{
//判断其他顶点若与当前顶点存在边且未访问过
if(G.arc[i][j] == 1 && !visited[j])
{
visited[j] = TRUE;
printf("%c",G.vex[j]);
EnQueue(&Q,j);
}
}
}
}
}
}
//邻接表广度遍历算法
void BFSTraverse(GraphAdjList GL)
{
int i;
EdgeNode *p;
Queue Q;
for(i = 0;i < GL->numVertexes;i++)
visited[i] = FALSE;
InitQueue(&Q);
for(i = 0;i < GL->numVertexes;i++)
{
if(!visited[i])
{
visited[i] = TRUE;
printf("%c",GL->adjList[i].data);
EnQueue(&Q,i);
while(!QueueEmpty(Q))
{
DeQueue(&Q,&i);
p = GL->adjList[i].firstedge; //找到当前顶点边表链表头指针
while(p)
{
if(!visited[p->adjvex])
{
visited[p->adjvex] == TRUE;
printf("%c",GL->adjList[p->adjvex].data);
EnQueue(&Q,p->adjvex); //将此顶点入队列
}
p = p->next; //指向下一个邻接点
}
}
}
}
}
构造连通网的最小代价生成树称为最小生成树。
//prim算法最小生成树
void MiniSpanTree_Prim(MGraph G)
{
int min,i,j,k;
int adjvex[MAXVEX]; //保存相关顶点下标
int lowcost[MAXVEX];//保存相关顶点间边的权值
lowcost[0] = 0; //初始化第一个权值为0,即v0加入生成树
adjvex[0] = 0; //初始化第一个顶点下标为0
for(i = 1;i < G.numVertexes;i++) //循环除下标为0外的全部顶点
{
lowcost[i] = G.arc[0][i];//将v0顶点与之有边的权值存入数组
adjvex[i]= 0; //初始化都为v0的下标
}
for(i = 1;;i <G.numVertexes;i++)
{
min = INFINITY; //初始化最小权值为无穷
j = 1;k = 0;
while(j < G.numVertexes)
{
if(lowcost[j]!= 0 && lowcost[j] < min)
{
//如果权值不为0,且权值小于min
min = lowcost[j]; //当前权值为最小值
k = j;
}
j++;
}
printf("(%d,%d)",adjvex[k],k);
lowcost[k] = 0;
for(j = 1;j < G.numVertexes;j++)
{
if(lowcost[j]!= 0&&G.arc[k][j] < lowcost[j])
{
lowcost[j] = G.arc[k][j];
adjvex[j] = k;
}
}
}
}
//Kruskal算法生成最小生成树
void MiniSpanTree_Kruskal(MGraph G)
{
int i,n,m;
Edge edges[MAXEDGE]; //定义边集数组
int parent[MAXVEX]; //定义数组用来判断边与边是否形成环路
for(i = 0;i <G.numVertexes;i++)
parent[i] = 0;
for(i = 0;i <G.numEdges;i++)
{
n = Find(parent,edges[i].begin);
m = Find(parent,edges[i].end);
if(n != m) //假如n与m不等,说明此边没有与现有生成树形成环路
{
parent[n] = m;
printf("(%d,%d)%d",edged[i].begin,edges[i].end,edges[i].weight);
}
}
}
int Find(int *parent,int f)//查找连线顶点的尾部下标
{
while(parent[f]>0)
f = parent[f];
return f;
}