G(V,E)
,G
表示一个图,V
是图G
的顶点集合,E
为图G
的边的集合图的逻辑结构:多对多
图的存储结构:邻接矩阵
邻接表
十字链表
邻接多重表
(i,j)
深度优先遍历(DFS)
广度优先遍历(BFS)
邻接表创建并遍历图代码(粘贴即可运行):
#include
#include
using namespace std;
#define maxSize 100
int visit[maxSize];
typedef struct EdgeNode{//边结点(其实就是尾顶点)
int adjvex;//当前顶点下标
int weight;//边的权值
struct EdgeNode *next;//指向下一个边结点的指针
}EdgeNode;
typedef struct VNode{//顶点结点
int data;//数据域
EdgeNode *firstEdg;//指向与之相邻接的边结点
}VNode;
typedef struct AGraph{//图结点
VNode adjList[maxSize];//顶点数组
int numVNode,numEdge;//顶点数和边数
}AGraph;
void createGraph(AGraph &G){//创建无向图 (因为要真正改变G,所以要传引用&)
int numVNode,numEdge,i,j,k;
EdgeNode *s,*p;
printf("请输入顶点个数和边数\n");
scanf("%d %d",&numVNode,&numEdge);
G.numEdge=numEdge;
G.numVNode=numVNode;
printf("请输入顶点\n");
for(i=0;i//输入顶点
scanf("%d",&G.adjList[i].data);
G.adjList[i].firstEdg=NULL;
}
printf("请输入边(vi,vj)的顶点的下标,格式为:i j\n");
for(k=0;kscanf("%d %d",&i,&j);
s=(EdgeNode *)malloc(sizeof(EdgeNode));
s->adjvex=j;
s->next=G.adjList[i].firstEdg;
G.adjList[i].firstEdg=s;
p=(EdgeNode *)malloc(sizeof(EdgeNode));
p->adjvex=i;
p->next=G.adjList[j].firstEdg;
G.adjList[j].firstEdg=p;
}
}
void dfs(AGraph G,int i){//深度优先遍历顶点i(类似二叉树的前序遍历)
printf("%d ",G.adjList[i].data);//先访问顶点
visit[i]=1;//然后标记被访问顶点
EdgeNode *p;
p=G.adjList[i].firstEdg;
while(p!=NULL){//接着遍历被访问顶点的边表
if(visit[p->adjvex]!=1){//若顶点未访问
dfs(G,p->adjvex);//则递归调用
}
p=p->next;
}
}
void dfsTravering(AGraph G){//dfs方法中只能遍历连通图的所有顶点,而此方法则能遍历有独立顶点的图的所有顶点
for(int i=0;i0;//标记数组初始化
}
printf("深度优先遍历的结果为:\n");
for(int i=0;i//遍历所有顶点
if(visit[i]!=1){//未访问的顶点
dfs(G,i);//从下标为0的开始访问
}
}
printf("\n");
}
void bfs(AGraph G,int v){//广度优先遍历下标为v的顶点及和其相邻接的顶点(类似二叉树的广度遍历)
int que[maxSize];//注:队列存放的都是顶点下标
int front,rear;front=rear;//初始化队头队尾指针
int i,j;
EdgeNode *p;//边结点
printf("%d ",G.adjList[v].data);//先访问结点,再标记,接着入队
visit[v]=1;
rear=(rear+1)%maxSize;//注:循环队列进出队都是先移指针再改数据
que[rear]=v;//顶点下标v入队
while(rear!=front){//循环条件:队不为空
front=(front+1)%maxSize;
i=que[front];//出队
p=G.adjList[i].firstEdg;//出队顶点指向的边结点
while(p!=NULL){//遍历出队顶点的边表
if(visit[p->adjvex]!=1){//顶点未曾访问过
printf("%d ",G.adjList[p->adjvex].data);//访问顶点
visit[p->adjvex]=1;//标记
rear=(rear+1)%maxSize;//入队
que[rear]=p->adjvex;
}
p=p->next;//边结点往下走
}
}
}
void bfsTravering(AGraph G){//广度优先遍历(当图不是连通图时需要这个方法)
for(int i=0;i0;//初始化标记数组
}
printf("广度优先遍历结果:\n");
for(int i=0;iif(visit[i]!=1){//不为1说明顶点未曾访问
bfs(G,i);
}
}
printf("\n");
}
int main(int argc, char** argv) {
AGraph G;
createGraph(G);
dfsTravering(G);
bfsTravering(G);
return 0;
}
/*
示例输入:
顶点数:10 边数:13
顶点:0 1 2 3 4 5 6 7 8 9
边下标:
0 2
0 1
1 4
1 3
2 5
2 3
3 4
4 7
4 6
5 7
6 9
7 8
8 9
*/
邻接矩阵创建并遍历图代码(粘贴即可运行):
#include
#define maxSize 100
#define infinity 65535
using namespace std;
bool visit[100]={false};
typedef struct {//图结点
int vertext[maxSize];//顶点数组
int edge[maxSize][maxSize]; //邻接矩阵(matrix)
int n,e;//图的顶点数和边数
}MGraph;
void createGraph(MGraph &G){//用邻接矩阵创建无向图
int i,j,k,weight;
printf("请输入顶点数和边数\n");
scanf("%d %d",&G.n,&G.e);
printf("请输入顶点:\n");
for(i=0;iscanf("%d",&G.vertext[i]);//输入顶点
}
for(i=0;ifor(j=0;j//初始化数组
G.edge[i][j]=infinity;
}
}
printf("请输入边的顶点下标i j及边的权重w\n");
for(k=0;kscanf("%d %d %d",&i,&j,&weight);
G.edge[i][j]=weight;
G.edge[j][i]=G.edge[i][j];//无向图的邻接矩阵是对称的
}
}
void dfs(MGraph G,int v){//深度优先遍历算法 (类似前序遍历)
int i;
printf("%d ",G.vertext[v]);//先访问
visit[v]=true;//再标记
for(i=0;i//最后遍历所有没访问过且与下标为v的顶点相邻的顶点,递归dfs
if(!visit[i]&&G.edge[v][i]!=infinity){
dfs(G,i);
}
}
}
void dfsTravering(MGraph G){//若不是连通图,则需要一个个检查顶点是否遍历过(连通图不需要,直接调用dfs方法即可)
for(int i=0;ifalse;
}
for(int i=0;iif(!visit[i]){
dfs(G,i);
}
}
}
void bfs(MGraph G,int v){//广度优先搜索遍历
int i,j;
int que[maxSize];
int front,rear;
front=rear=0;
printf("%d ",G.vertext[v]);
visit[v]=true;
rear=(rear+1)%maxSize;
que[rear]=v;
while(front!=rear){
front=(front+1)%maxSize;
i=que[front];
for(j=0;jif(!visit[j]&&G.edge[i][j]!=infinity){//没有被访问且顶点之间相邻接
printf("%d ",G.vertext[j]);
visit[j]=true;
rear=(rear+1)%maxSize;
que[rear]=j;
}
}
}
}
int main(int argc, char** argv) {
MGraph G;
createGraph(G);
dfs(G,8);
dfsTravering(G);
bfs(G,5);
return 0;
}
/*
实例输入:
顶点数:10,边数:13
顶点:0 1 2 3 4 5 6 7 8 9
边顶点下标及权值:
0 2 4
0 1 3
1 4 6
1 3 5
2 5 7
2 3 8
3 4 3
4 7 4
4 6 9
5 7 6
6 9 2
7 8 5
8 9 3
*/
深度优先遍历4部曲(dfs):
广度优先遍历6部曲(bfs) :