图的基本操作,为了便于信息即可显示,在函数内部输出了数据,可后修改来实现更接近封装程序。
程序包可在次下载:http://download.youkuaiyun.com/detail/decting/4850581
GraphTestApp.c内容:
#include <stdio.h>
#include "M_AL_Graph.h"
int main()
{
int i,j,n,m,x,y,w;
Mgraph A; //定义邻接矩阵,
Graph* G=CreateGraph(); //定义图并创建图
//输入图信息,文件方式,可注释掉来手动输入
freopen("Input.txt","r",stdin);
scanf("%d%d",&n,&m); //输入节点数和边数
for(i=0; i<m; i++)
{
scanf("%d%d%d",&x,&y,&w);
AddGraphEdge(G,x,y,w); //无向图正反两遍加入边
AddGraphEdge(G,y,x,w);
}
AdjGraphMatrix(G,A); //得到邻接矩阵,以0填充无关边
//测试1、输出邻接矩阵
printf("1、\n邻接矩阵如下:\n");
for(i=1;i<=n;i++)
{
for(j=1;j<=n;j++)
printf("%2d ",A[i][j]);
printf("\n");
}
//测试2、输出邻接表
printf("2、\n邻接表如下:\n");
DisplayGraph(G);
//测试3、输出深度和宽度遍历
printf("3、\n深度遍历如下:\n");
GraphDeepthTraversal(G);
printf("\n宽度遍历如下:\n");
GraphBreadthTraversal(G);
//测试4、输出prim算法生成的最小生成树,个边和总权值
printf("\n4、\n最小生成树的各边分别为:");
printf("\n最小生成树总权值为:%d\n",GraphPrim(G));
return 0;
}
/*
--------------------------------------
测试图数据1 | 测试图数据2
6 10 | 6 10
1 6 21 | 1 2 6
1 5 19 | 1 3 1
1 2 10 | 1 4 5
2 6 11 | 2 3 5
5 6 33 | 3 4 5
4 6 14 | 2 5 3
4 5 18 | 3 5 6
3 4 6 | 3 6 4
2 4 6 | 5 6 6
2 3 5 | 4 6 2
--------------------------------------
*/
/*测试图数据1的结果:
--------------------------------------
1、
邻接矩阵如下:
0 10 0 0 19 21
10 0 5 6 0 11
0 5 0 6 0 0
0 6 6 0 18 14
19 0 0 18 0 33
21 11 0 14 33 0
2、
邻接表如下:
1: 2 5 6
2: 1 3 4 6
3: 2 4
4: 2 3 5 6
5: 1 4 6
6: 1 2 4 5
3、
深度遍历如下:
1 2 3 4 5 6
宽度遍历如下:
1 2 5 6 3 4
4、
最小生成树的各边分别为:10 5 6 11 18
最小生成树总权值为:50
Press any key to continue
--------------------------------------
*/
M_AL_Graph.h的内容:
/****
* 每个图会有一个图的头部,定义时如下
* Graph* G;
* CreateGraphHead(&G);
* 或者如下定义
* Graph* G=CreateGraph();
* Mgraph 是邻接矩阵的定义类型
* 定义时,Mgraph A;等价于WeightType A[MAXNODE][MAXNODE];
* WeightType是int型
* GraphDeepthTraversal(Graph*)和GraphBreadthTraversal(Graph*)
* 分别是深度和宽度优先遍历的调用函数,直接调用
* GraphPrim(Graph*)为prim生成最小生成树,又返回值,为生成树总权值
*******/
#ifndef _M_AL_GRAPH_H_
#define _M_AL_GRAPH_H_
#include <memory.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#define MAXWEIGHT 0x7FFFFFFF
#define MAXNODE 300 //定义最大节点数
typedef int NodeType; //节点类型
typedef int WeightType;
//定义邻接矩阵,Graph是二维数组的标示
typedef WeightType Mgraph[MAXNODE][MAXNODE];
typedef struct GNODE
{//定义图中每个节点的信息,节点信息和连接的节点
NodeType data;
WeightType weight;
struct GNODE* link;
}GraphNode;
typedef struct GRAPH
{//定义图类型
GraphNode *node;
struct GRAPH* next;
}Graph;
Graph* CreateGraph();
void CreateGraphHead(Graph**);
void CreateGraphNode(GraphNode**);
void AddGraphNode(Graph*,NodeType);
void DisplayGraphNode(Graph*);
void AddGraphEdge(Graph*,NodeType,NodeType,WeightType);
void AdjGraphMatrix(Graph*,Mgraph);
void DisplayGraph(Graph*);
GraphNode* FindGraphNode(Graph*,NodeType);
void GraphDeapth(Graph*,GraphNode*,WeightType*);
void GraphDeepthTraversal(Graph*);
void GraphBreadthTraversal(Graph*);
WeightType GraphPrim(Graph*);
#endif //_M_AL_GRAPH_H_
M_AL_Graph.c的内容:
#include "M_AL_Graph.h"
Graph* CreateGraph(void)
{//返回式创建图节点
Graph* Temp_G;
CreateGraphHead(&Temp_G);
return Temp_G;
}
void CreateGraphHead(Graph** G)
{//调用式创建图头部节点
*G=(Graph*)malloc(sizeof(Graph));
(*G)->next=NULL;
CreateGraphNode(&(*G)->node);
}
void CreateGraphNode(GraphNode** N)
{//创建节点
*N=(GraphNode*)malloc(sizeof(GraphNode));
(*N)->weight=(*N)->data=0;
(*N)->link=NULL;
}
void AddGraphNode(Graph* G,NodeType N)
{//增加节点,向图中增加节点,会按照从小到大的顺序排列
Graph* Temp_G=CreateGraph();
while(G->next!=NULL&&G->next->node->data<=N) G=G->next;
if(G->node->data==N) return;
Temp_G->next=G->next;
Temp_G->node->data=N;
G->next=Temp_G;
}
void DisplayGraphNode(Graph* G)
{//临时的图节点输出,便于调试,查看
while(G->next!=NULL)
{
G=G->next;
printf("%d ",G->node->data);
}
}
void AddGraphEdge(Graph* G,NodeType N1,NodeType N2,WeightType W)
{//加入边,N1到N2的权值为W
GraphNode *Temp_N,*N;
CreateGraphNode(&Temp_N); //先创建个节点
AddGraphNode(G,N1); //保证N1在图中
AddGraphNode(G,N2); //保证N2在图中
while(G->next->node->data!=N1) G=G->next;//寻找N1节点的位置
N=G->next->node;
Temp_N->data=N2;
Temp_N->weight=W;
while(N->link!=NULL&&N->link->data<=N2) N=N->link;//寻找N2该插入的位置
Temp_N->link=N->link;
N->link=Temp_N;
}
void AdjGraphMatrix(Graph* G,Mgraph A)
{//Adjacent Matrix, 得到图G的邻接矩阵A
GraphNode *N;
NodeType X;
//初始化A内权值为0,表示不相连接
memset(A,0,MAXNODE*MAXNODE*sizeof(WeightType));
while(G->next!=NULL)
{
G=G->next; N=G->node;
X=N->data;
while(N->link!=NULL)
{
N=N->link;
A[X][N->data]=N->weight;
}
}
}
void DisplayGraph(Graph* G)
{//以邻接矩阵的形式输出G
GraphNode *N;
while(G->next!=NULL)
{
G=G->next; N=G->node;
printf("%2d: ",N->data);
while(N->link!=NULL)
{
N=N->link;
printf("%2d ",N->data);
}
printf("\n");
}
}
GraphNode* FindGraphNode(Graph* G,NodeType N)
{//根据N节点,寻找并返回结构体节点指针
while(G->next!=NULL&&G->next->node->data!=N)
G=G->next;
return G->next->node;
}
void GraphDeapth(Graph* G,GraphNode* N,WeightType* Visited)
{//深度优先遍历Deeth First Traversal,过程函数
GraphNode *Temp_N=FindGraphNode(G,N->data);
if(Temp_N==NULL||Visited[Temp_N->data]) return;
printf("%d ",Temp_N->data);
Visited[Temp_N->data]=1;
while(Temp_N->link!=NULL)
{
Temp_N=Temp_N->link;
GraphDeapth(G,Temp_N,Visited);
}
}
void GraphDeepthTraversal(Graph* G)
{//深度优先遍历operator调用函数
int Visited[MAXNODE]={0};//访问点表示数组
if(G->next==NULL) return;
GraphDeapth(G,G->next->node,Visited);
}
void GraphBreadthTraversal(Graph* G)
{//宽度优先遍历Breadth First Traversal,使用循环队列实现
int front=0,rear=0,Visited[MAXNODE]={0};
GraphNode **GraphQueue,*N;//定义循环队列头
if(G->next==NULL) return;
GraphQueue=(GraphNode*)malloc(MAXNODE*sizeof(GraphNode));
GraphQueue[rear++]=G->next->node;//初始第一个成员为G图中的第一个
while(front!=rear)
{
N=FindGraphNode(G,GraphQueue[front++]->data);
if(Visited[N->data]) continue;
printf("%d ",N->data);
Visited[N->data]=1;
while(N->link!=NULL)
{
N=N->link;
GraphQueue[rear++]=N;
}
}
}
WeightType GraphPrim(Graph* G)
{//prim算法实现的最小生成树,各边的weight直接在函数内部
//输出,返回最小生成树的总权值
Mgraph A;
GraphNode* N;
int n=0,Visited[MAXNODE]={0};
WeightType M[MAXNODE]={MAXWEIGHT},STree=0;
if(G->next==NULL) return;
AdjGraphMatrix(G,A);
N=G->next->node;
Visited[N->data]=1;
while(G->next!=NULL)G=G->next,n++;
while(N->link!=NULL)N=N->link,M[N->data]=N->weight;
while(1)
{
int i,k=0;
for(i=1; i<=n; i++)
if(!Visited[i]&&(M[k]>M[i]&&M[i])) k=i;
if(!k) break;
printf("%d ",M[k]);
Visited[k]=1;
STree+=M[k];
for(i=1; i<=n; i++)
if(!Visited[i]&&(M[i]>A[k][i]||!M[i])&&A[k][i])
M[i]=A[k][i];
}
return STree;
}
附加文件Input.txt:
6 10
1 6 21
1 5 19
1 2 10
2 6 11
5 6 33
4 6 14
4 5 18
3 4 6
2 4 6
2 3 5