对于图的邻接表存储以及遍历,搞清思路是十分必要的。
1、首先搞清结构体。不同的处理问题的思路,对应着不同的结构体封装。下面 以我的处理方式为例为大家展示:
#define max_vertex_num 100 //该图可以为维护最大的结点个数。
typedef struct Arcnode
{
int adjvex;//该弧所指向的顶点的位置
struct Arcnode *nextarc;
char *info;
}Arcnode;
typedef struct Vnode
{
char data;
Arcnode *firstrac;//对于每一个邻接链表,这相当于是链表的头指针。
}Vnode,Adjlist[max_vertex_num];
typedef struct
{
Adjlist vertices;
int vexnum,arcnum;
int kind;//1为有向图,0为无向图。
}Algrap;
看过我封装的结构体,相信大家已经很清楚的了解到,图、结点、弧之间存在一定的联系。也清楚了结构体中所具有的属性。 2、先引入几个函数以及实现。 int creatgrap(Algrap *map1); 创建图。对于每个节点的临接点所形成的链表采用头插法初始化,链表中储存的数据保存节点位置。
void DFSTraverse(Algrap *G); 保证每个节点都会被遍历到,尽管该图不是连通图。遍历的顺序默认为从最大连通图中下表最小的开始。
void DFS(Algrap *G,int i); 图的递归遍历。
void printf(Algrap G);
把图的逻辑存储关系打印出来。
下面给出函数的实现:
//图的创建。
int creatgrap(Algrap *map1)
{
int i,j;
cout<<"请输入图的结点数以及弧的条数:";
cin>>map1->vexnum>>map1->arcnum;
cout<<" 请选择图的类型: "<<endl;
cout<<" 1 有向图 "<<endl;
cout<<" 2 无向图 "<<endl;
cout<<" 请输入选择的数字: "<<endl;
cin>>map1->kind;
while(map1->kind!=1&&map1->kind!=2)
{
cout<<"请重新输入选择数字,你输入的数字不合法!"<<endl;
cin>>map1->kind;
}
for(i=0;i<map1->vexnum;i++)
{
cout<<"请输入节点数据:";
cin>>map1->vertices[i].data;
map1->vertices[i].firstrac=NULL;
}
for(i=0;i<map1->arcnum;i++)
{
char a,b;
int temp1=0,temp2=0;
cout<<"请输入两个有关系的节点:";
cin>>a>>b;
for(j=0;j<map1->vexnum;j++)
{
if(map1->vertices[j].data==a)
temp1=j;
if(map1->vertices[j].data==b)
temp2=j;
}
Arcnode *p,*q;
p=(Arcnode*)malloc(sizeof(Arcnode));
p->adjvex=temp2;
p->nextarc=map1->vertices[temp1].firstrac;//插入表头.采用头插法,先进的弧、遍历后出。后进的弧、遍历先出。
map1->vertices[temp1].firstrac=p;
if(map1->kind==2)
{
q=(Arcnode*)malloc(sizeof(Arcnode));
q->adjvex=temp1;
q->nextarc=map1->vertices[temp2].firstrac;
map1->vertices[temp2].firstrac=q;
}
}
return 0;
}
void DFSTraverse(Algrap *G)//保证每个节点都会被遍历到,尽管该图不是连通图。遍历的顺序默认为从最大连通图中下标最小的开始。
{
int i;
for(i=0;i<G->vexnum;i++)
visited[i]=false;
for(i=0;i<G->vexnum;i++)
if(!visited[i])
DFS(G,i);
}
void DFS(Algrap *G,int i)
{
Arcnode *p=NULL;
printf("访问顶点;%c\n",G->vertices[i].data);
visited[i]=true;
p=G->vertices[i].firstrac;
while(p)
{
if(!visited[p->adjvex])
DFS(G,p->adjvex);
p=p->nextarc;
}
}
void printf(Algrap G)
{
int i;
Arcnode *p;
cout<<"下面把图的逻辑存储打印出来:"<<endl;
for(i=0;i<G.vexnum;i++)
{
cout<<G.vertices[i].data;
p=G.vertices[i].firstrac;
while(p)
{
cout<<"->"<<p->adjvex;
p=p->nextarc;
}
cout<<endl;
}
}
下面给出完整的程序:
// 邻接表图的建立与遍历.cpp : 定义控制台应用程序的入口点。
#include "stdafx.h"
#include<cstdlib>
#include<cstdio>
#include<iostream>
using namespace std;
bool visited[100];
#define max_vertex_num 100 //该图可以为维护最大的结点个数。
typedef struct Arcnode
{
int adjvex;//该弧所指向的顶点的位置
struct Arcnode *nextarc;
char *info;
}Arcnode;
typedef struct Vnode
{
char data;
Arcnode *firstrac;//对于每一个邻接链表,这相当于是链表的头指针。
}Vnode,Adjlist[max_vertex_num];
typedef struct
{
Adjlist vertices;
int vexnum,arcnum;
int kind;//1为有向图,2为无向图。
}Algrap;
int creatgrap(Algrap *map1);
void DFSTraverse(Algrap *G);
void DFS(Algrap *G,int i);
void printf(Algrap G);
int main()
{
Algrap *map=(Algrap* )malloc(sizeof(Algrap));
creatgrap(map);
printf(*map);
DFSTraverse(map);
return 0;
}
//图的创建。
int creatgrap(Algrap *map1)
{
int i,j;
cout<<"请输入图的结点数以及弧的条数:";
cin>>map1->vexnum>>map1->arcnum;
cout<<" 请选择图的类型: "<<endl;
cout<<" 1 有向图 "<<endl;
cout<<" 2 无向图 "<<endl;
cout<<" 请输入选择的数字: "<<endl;
cin>>map1->kind;
while(map1->kind!=1&&map1->kind!=2)
{
cout<<"请重新输入选择数字,你输入的数字不合法!"<<endl;
cin>>map1->kind;
}
for(i=0;i<map1->vexnum;i++)
{
cout<<"请输入节点数据:";
cin>>map1->vertices[i].data;
map1->vertices[i].firstrac=NULL;
}
for(i=0;i<map1->arcnum;i++)
{
char a,b;
int temp1=0,temp2=0;
cout<<"请输入两个有关系的节点:";
cin>>a>>b;
for(j=0;j<map1->vexnum;j++)
{
if(map1->vertices[j].data==a)
temp1=j;
if(map1->vertices[j].data==b)
temp2=j;
}
Arcnode *p,*q;
p=(Arcnode*)malloc(sizeof(Arcnode));
p->adjvex=temp2;
p->nextarc=map1->vertices[temp1].firstrac;//插入表头.采用头插法,先进的弧、遍历后出。后进的弧、遍历先出。
map1->vertices[temp1].firstrac=p;
if(map1->kind==2)
{
q=(Arcnode*)malloc(sizeof(Arcnode));
q->adjvex=temp1;
q->nextarc=map1->vertices[temp2].firstrac;
map1->vertices[temp2].firstrac=q;
}
}
return 0;
}
void DFSTraverse(Algrap *G)//保证每个节点都会被遍历到,尽管该图不是连通图。遍历的顺序默认为从最大连通图中下表最小的开始。
{
int i;
for(i=0;i<G->vexnum;i++)
visited[i]=false;
for(i=0;i<G->vexnum;i++)
if(!visited[i])
DFS(G,i);
}
void DFS(Algrap *G,int i)
{
Arcnode *p=NULL;
printf("访问顶点;%c\n",G->vertices[i].data);
visited[i]=true;
p=G->vertices[i].firstrac;
while(p)
{
if(!visited[p->adjvex])
DFS(G,p->adjvex);
p=p->nextarc;
}
}
void printf(Algrap G)
{
int i;
Arcnode *p;
cout<<"下面把图的逻辑存储打印出来:"<<endl;
for(i=0;i<G.vexnum;i++)
{
cout<<G.vertices[i].data;
p=G.vertices[i].firstrac;
while(p)
{
cout<<"->"<<p->adjvex;
p=p->nextarc;
}
cout<<endl;
}
}