图的存储常见的两种方式: 邻接矩阵、邻接表
邻接矩阵的定义:
//邻接矩阵
typedef struct
{
char vertex[MAXVEX];//顶点表
int arc[MAXVEX][MAXVEX];//邻接矩阵
int numVertexes, numEdges;//图中当前顶点数和边数
}MGraph;
基于邻接矩阵创建一个图:
//建立无向网的邻接矩阵
void CreateGraph(MGraph *G)
{
int i, j,k,w;
//设置顶点个数
printf("请输入图的顶点数,边数:\n");
scanf("%d %d", &G->numVertexes, &G->numEdges);
//getchar();//清空缓冲区(主要是回车)
setbuf(stdin, NULL);//设置输入缓冲区 为空缓冲区
//设置结点存储值
for (i = 0; i < G->numVertexes; i++)
{
printf("\n请输入第%d个顶点存储的值:",i);
scanf("%c", &G->vertex[i]);
setbuf(stdin, NULL);//设置输入缓冲区 为空缓冲区(每次输入一个回车,这里会造成 \n字符存在缓冲区)
}
for (i = 0; i < G->numVertexes; i++)
{
for (j = 0; j < G->numVertexes; j++)
{
G->arc[i][j] = INFINITY;//初始化邻接矩阵(权为INFINITY无穷大表示没有弧)
}
}
for (k = 0; k < G->numEdges; k++)
{
printf("请输入边(vi,vj)的下标i,下标j对应的权w:");
scanf("%d %d %d", &i, &j, &w);
G->arc[i][j] = w;//设置对应的权
G->arc[j][i] = G->arc[i][j];//无向网,对称矩阵
}
}
邻接表的定义:
typedef struct EdgeNode /* 边表结点 */
{
int adjvex; /* 邻接点域,存储该顶点对应的下标 */
// EdgeType info; /* 用于存储权值,对于非网图可以不需要 */
struct EdgeNode *next; /* 链域,指向下一个邻接点 */
}EdgeNode;
typedef struct VertexNode /* 顶点表结点 */
{
char data; /* 顶点域,存储顶点信息 */
EdgeNode *firstedge;/* 边表头指针 */
}VertexNode, AdjList[MAXVEX];
基于邻接表创建一个图:
void CreateALGraph(GraphAdjList *G)
{
int i,j,k;
EdgeNode *e;
printf("输入顶点数和边数:\n");
scanf("%d %d",&G->numNodes,&G->numEdges); /* 输入顶点数和边数 */
for(i = 0;i < G->numNodes;i++) /* 读入顶点信息,建立顶点表 */
{
printf("请输入顶点信息\n");
scanf("%s",&G->adjList[i].data); /* 输入顶点信息 */
G->adjList[i].firstedge=NULL; /* 将边表置为空表 */
}
for(k = 0;k < G->numEdges;k++)/* 建立边表 */
{
printf("输入边(vi,vj)上的顶点序号:\n");
scanf("%d %d",&i,&j); /* 输入边(vi,vj)上的顶点序号 */
e=(EdgeNode *)malloc(sizeof(EdgeNode)); /* 向内存申请空间,生成边表结点 */
e->adjvex=j; /* 邻接序号为j */
e->next=G->adjList[i].firstedge; /* 将e的指针指向当前顶点上指向的结点 */
G->adjList[i].firstedge=e; /* 将当前顶点的指针指向e */
e=(EdgeNode *)malloc(sizeof(EdgeNode)); /* 向内存申请空间,生成边表结点 */
e->adjvex=i; /* 邻接序号为i */
e->next=G->adjList[j].firstedge; /* 将e的指针指向当前顶点上指向的结点 */
G->adjList[j].firstedge=e; /* 将当前顶点的指针指向e */
}
}
基于邻接矩阵的广度优先遍历(BFS):
void BFS(MGraph *G,int i){
int j;
int Q[MAXVEX];int front=0;int rear=0;//定义一个队列,并初始化
Q[rear++]=i;
printf("%c",G->vertex[i]);
visited[i]=true;//设置标记数组
while(rear!=front){//队列不为空
i=Q[front++];//出队
for(j=0;j<G->numVertexes;j++)
if(G->arc[i][j]!=0&&G->arc[i][j]!=INFINITY&&!visited[j]){
Q[rear++]=j;//入队
printf("%c",G->vertex[j]);//访问
visited[j]=true;//修改标志
}
}
}
void BFSTraver(MGraph *G){
int i;
for(i=0;i<G->numVertexes;i++)
visited[i]=false;//初始化
for(i=0;i<G->numVertexes;i++)
if(!visited[i])
BFS(G,i);
}
深度优先遍历(DFS):
void DFS(MGraph *G,int i){
int j;
printf("%c",G->vertex[i]);
visited[i]=true;
for(j=0;j<G->numVertexes;j++){
if(G->arc[i][j]!=0&&G->arc[i][j]!=INFINITY&&!visited[i])
DFS(G,j);
}
}
void DFSTraver(MGraph *G){
int i;
for(int i;i<G->numVertexes;i++)
visited[i]=false; //初始化
for(i=0;i<G->numVertexes;i++){
if(!visited[i])
DFS(G,i);
}
}
基于邻接表的广度优先遍历(BFS):
void BFS(GraphAdjList *G,int v0){
int Q[MAXVEX];int front=0;int rear=0;
Q[rear++]=v0; //入队
visit(G,v0);
visited[v0]=true;
while(front!=rear){
int v=Q[front++]; //入队
EdgeNode *p=G->adjList[v].firstedge;
while(p!=NULL){
if(!visited[p->adjvex]){
visit(G,p->adjvex);
visited[p->adjvex]=true;
Q[rear++]=p->adjvex;
}
p=p->next; //
}
}
}
void BFSTraver(GraphAdjList *G){
int i;
for(i=0;i<G->numNodes;i++){
visited[i]=false;
}
for(i=0;i<G->numNodes;i++){
if(!visited[i])
BFS(G,i);
}
}
深度优先遍历(DFS):
void DFS(GraphAdjList *G,int v0){
visit(G,v0);
visited[v0]=true;
EdgeNode *p=G->adjList[v0].firstedge;
while(p!=NULL){
if(!visited[p->adjvex]){
DFS(G,p->adjvex);
}
p=p->next;
}
}
void DFSTraver(GraphAdjList *G){
int i;
for(i=0;i<G->numNodes;i++)
visited[i]=false;//初始化
for(i=0;i<G->numNodes;i++)
if(!visited[i])
DFS(G,i);
}