采用邻接矩阵完成无向图的“建立、深度遍历、广度遍历”操作
数据结构中图的建立与深度优先、广度优先遍历
数据结构中图的建立与深度优先、广度优先遍历《数据结构》实验报告实验内容:图的建立(邻接矩阵)及其深度优先、广度优先遍历学号:姓名:一、上机实验的问题和要求(需求分析):[ 题目]二、程序设计的基本思想,原理和算法描述:设计一个程序,建立图的邻接矩阵,并且进行图的广度优先遍历。
三、调试和运行程序过程中产生的问题及采取的措施:(略)四、源程序及注释[ 源程序] 程序名:9.cpp#include"stdio.h"#include"stdlib.h"#define INFINITY 100#define MAX_VERTEX_NUM 20#define MAX 100#define OK 1#define ERROR 0#define NULL 0typedef int VRType;typedef int VertextType;typedef int Status;typedef enum {DG,DN,UDG,UDN}GraphKind;typedef struct ArcCell{VRType adj;}ArcCell,AdjMatrix[MAX_VERTEX_NUM ][MAX_VERTEX_NUM ]; typedef struct{int vexs[MAX_VERTEX_NUM ];int arcs[4][4] ;int vexnum,arcnum;GraphKind Kind;}MGraph;int LocateVex(MGraph G,int v1){ int i;for(i=0;i<g.vexnum;i++)< p="">if(G.vexs[i]==v1)printf("%d\n",i);return i;}Status CreateUDN(MGraph &G){ int v1,v2;int i,j,k,w;printf("输入图的顶点数和弧数:");scanf("%d,%d",&G.vexnum,&G.arcnum); printf("输入顶点:");for(i=0;i<g.vexnum;i++)< p="">scanf("%d",&G.vexs[i]);for(i=0;i<g.vexnum;i++)< p="">for(j=0;j<g.vexnum;j++)< p="">G.arcs[i][j]=INFINITY ;printf("输入顶点关系:");for(k=0;k<g.arcnum;k++)< p="">{scanf("%d%d%d",&v1,&v2,&w);i=LocateVex(G,v1);j=LocateVex(G,v2);G.arcs[i][j]=w;G.arcs[j][i]=G.arcs[i][j];printf("%d\n%d\n",G.arcs[i][j],G.arcs[j][i]);}printf("图的邻接矩阵图是:\n");for(i=0;i<g.vexnum;i++)< p="">{for(j=0;j<g.vexnum;j++)< p="">printf("%d",G.arcs[i][j]);printf("\n");}return OK;}Status Visit(int e){//输出函数printf("%d\n",e);return OK;}//PrintElement//Status(*VisitFunc)(char v);int visited[MAX];void DFS(MGraph G,int v){ int j;Visit (v);visited[v]=1;for(j=1;j<g.vexnum;j++)< p="">if(!visited[j]&&G.arcs[v][j]!=INFINITY)DFS(G,j); } void DFSTraverse(MGraph G){ int v;for(v=0;v<g.vexnum;++v)< p="">visited[v]=0;for(v=0;v<g.vexnum;++v)< p="">if(!visited[v])DFS(G,v);/* 有关队列的操作*/#define MAX SIZE 100#define QElemType int#define OVERFLOW 0typedef struct{QElemType *base;int front;int rear;}SqQueue;Status InitQueue(SqQueue &Q){ Q.base=(QElemType*)malloc(MAXSIZE* sizeof(QElemType)); if(!Q.base)exit(OVERFLOW);Q.front=Q.rear=0;return 0;}Status EnQueue(SqQueue &Q,QElemType e){if(Q.rear+1==Q.front)return ERROR;Q.base[Q.rear]=e;Q.rear=Q.rear+1;return OK;}Status DeQueue(SqQueue &Q,QElemType &e){if(Q.front==Q.rear)return ERROR;e=Q.base[Q.front];Q.front=Q.front+1;return OK;}Status QueueEmpty(SqQueue Q){if(Q.front==Q.rear)return OK;else return ERROR;void BFSTraverse(MGraph &G){ int v,u,j;SqQueue Q;for(v=0;v<g.vexnum;v++)< p=""> visited[v]=0;InitQueue(Q);for(v=0;v<g.vexnum;++v)< p="">if(!visited[v]){visited[v]=1;Visit(v);EnQueue(Q,v);while(!QueueEmpty(Q)){ DeQueue(Q,u);for(j=1;j<g.vexnum;j++)< p="">if(!visited[j]&&G.arcs[v][j]!=INFINITY) { visited[j]=1;Visit(j);EnQueue(Q,j);}} }}void main(){ MGraph G;CreateUDN(G);printf("建图成功!");printf("深度优先遍历的结果:\n"); DFSTraverse(G);printf("广度优先遍历的结果:\n"); BFSTraverse(G);}五、运行结果运行结果:上一页下一页</g.vexnum;j++)<></g.vexnum;++v)<></g.vexnum;v++)<></g.vexnum;++v)<> </g.vexnum;++v)<> </g.vexnum;j++)<> </g.vexnum;j++)<> </g.vexnum;i++)<> </g.arcnum;k++)<> </g.vexnum;j++)<> </g.vexnum;i++)<> </g.vexnum;i++)<> </g.vexnum;i++)<>。
图的深度优先遍历和广度优先遍历
华北水利水电学院数据结构实验报告20 10 ~20 11 学年第一学期2008级计算机专业班级:107学号:200810702姓名:王文波实验四图的应用一、实验目的:1.掌握图的存储结构及其构造方法2.掌握图的两种遍历算法及其执行过程二、实验内容:以邻接矩阵或邻接表为存储结构,以用户指定的顶点为起始点,实现无向连通图的深度优先及广度优先搜索遍历,并输出遍历的结点序列。
提示:首先,根据用户输入的顶点总数和边数,构造无向图,然后以用户输入的顶点为起始点,进行深度优先和广度优先遍历,并输出遍历的结果。
三、实验要求:1.各班学号为单号的同学采用邻接矩阵实现,学号为双号的同学采用邻接表实现。
2.C/ C++完成算法设计和程序设计并上机调试通过。
3.撰写实验报告,提供实验结果和数据。
4.写出算法设计小结和心得。
四、程序源代码:#include<iostream.h>#define MaxVerNum 50struct edgenode{int endver;int inform;edgenode* edgenext;};struct vexnode{char vertex;edgenode* edgelink;};struct Graph{vexnode adjlists[MaxVerNum];int vexnum;int arcnum;};//队列的定义及相关函数的实现struct QueueNode{int nData;QueueNode* next;};struct QueueList{QueueNode* front;QueueNode* rear;};void EnQueue(QueueList* Q,int e) {QueueNode *q=new QueueNode;q->nData=e;q->next=NULL;if(Q==NULL)return;if(Q->rear==NULL)Q->front=Q->rear=q;else{Q->rear->next=q;Q->rear=Q->rear->next;}}void DeQueue(QueueList* Q,int* e) {if (Q==NULL)return;if (Q->front==Q->rear){*e=Q->front->nData;Q->front=Q->rear=NULL;}else{*e=Q->front->nData;Q->front=Q->front->next;}}//创建图void CreatAdjList(Graph* G){int i,j,k;edgenode* p1;edgenode* p2;cout<<"请输入顶点数和边数:"<<endl;cin>>G->vexnum>>G->arcnum;cout<<"开始输入顶点表:"<<endl;for (i=0;i<G->vexnum;i++){cin>>G->adjlists[i].vertex;G->adjlists[i].edgelink=NULL;}cout<<"开始输入边表信息:"<<endl;for (k=0;k<G->arcnum;k++){cout<<"请输入边<Vi,Vj>对应的顶点:";cin>>i>>j;p1=new edgenode;p1->endver=j;p1->edgenext=G->adjlists[i].edgelink;G->adjlists[i].edgelink=p1;p2=new edgenode;p2->endver=i;p2->edgenext=G->adjlists[j].edgelink;G->adjlists[j].edgelink=p2;//因为是无向图,所以有两次建立边表的过程}}//-------------------------------------------------------------深度优先遍历void DFS(Graph *G,int i,int visit[]){cout<<G->adjlists[i].vertex<<" ";visit[i]=1;edgenode *p=new edgenode;p=G->adjlists[i].edgelink;if(G->adjlists[i].edgelink&&!visit[p->endver]){DFS(G,p->endver,visit);}}void DFStraversal(Graph *G,char c)//深度优先遍历{cout<<"该图的深度优先遍历结果为:"<<endl;int visit[MaxVerNum];for(int i=0;i<G->vexnum;i++){visit[i]=0;//全部初始化为0,即未访问状态}int m;for (i=0;i<G->vexnum;i++){if (G->adjlists[i].vertex==c)//根据字符查找序号{m=i;DFS(G,i,visit);break;}}//继续访问未被访问的结点for(i=0;i<G->vexnum;i++){if(visit[i]==0)DFS(G,i,visit);}cout<<endl;}//-------------------------------------------------------------广度优先遍历void BFS(Graph* G,int v,int visit[]){QueueList *Q=new QueueList;Q->front=Q->rear=NULL;EnQueue(Q,v);while(Q->rear!=NULL){int e=0;DeQueue(Q,&e);cout<<G->adjlists[e].vertex<<" ";visit[e]=1;edgenode* p=new edgenode;p=G->adjlists[e].edgelink;if(p){int m=p->endver;if(m==0){EnQueue(Q,m);while(visit[m]==0){p=p->edgenext;if(p==NULL)break;m=p->endver;EnQueue(Q,m);}}}}}void BFStraversal(Graph *G,char c){cout<<"该图的广度优先遍历结果为:"<<endl;int visited[MaxVerNum];for (int i=0;i<G->vexnum;i++){visited[i]=0;}int m;for (i=0;i<G->vexnum;i++){if (G->adjlists[i].vertex==c){m=i;BFS(G,i,visited);break;}}//继续访问未被访问的结点for(i=0;i<G->vexnum;i++){if(visited[i]==0)BFS(G,i,visited);}cout<<endl;}void main(){Graph * G=new Graph;CreatAdjList(G);char ch;cout<<"请输入开始遍历的顶点:";cin>>ch;DFStraversal(G,ch);BFStraversal(G,ch);}五、程序运行情况(写出输入数据及运行结果)六、小结(包括收获、心得体会、存在的问题及解决问题的方法、建议等)注:内容一律使用宋体五号字,单倍行间距本次试验采用的是邻接表的方式实现图的深度优先遍历和广度优先遍历。
无向图深度遍历邻接矩阵报告
55.G->arcs[i][j].adj=1;
56.G->arcs[j][i].adj=1;
57.}
58.return(OK);
59.}
60.
61.
62.void DepthFirstSearch(AdjMatrix G,int v)
63.{int j;
输出邻接矩阵0 1
1 0
实际结果:
第二组测试:
输入数据:顶点:0,1,2,3,4
预测结果:输出结点数据:0,1,2,3,4
输出邻接矩阵01 1 1 0
1 0 0 1 0
1 0 0 1 1
1 1 1 0 1
0 0 1 1 0
实际结果:
第三组测试:
输入数据:顶点:0,1,2,3,4 5 6
预测结果:输出结点数据:0123456
70.}
71.void TraverseGraph(AdjMatrix G)
72.{int i;
73.for(i=0;i<G.vexnum;i++) visited[i]=FALSE;
74.for(i=0;i<G.vexnum;i++)
75.if(!visited[i]) DepthFirstSearch(G,i);
typedef struct
{
VertexData vertex[MAX_VERTEX_NUM];//为顶点的集合
ArcNode arcs[MAX_VERTEX_NUM][MAX_VERTEX_NUM];
int vexnum,arcnum;//vexnum为顶点数,arcnum为弧数
邻接矩阵图的深度广度遍历
for(int i=0;i<G.vexnum;i++)
if(G.arcs[k][i]!=INFINITY)
return i;
}
return aph G,int i,int j) //图G中顶点i的第j个邻接顶点的下一个邻接顶点
{
{
cout<<"边%d:",i;
scanf("%c-%c %d",&a,&b,&w); //输入边和权值
temp=getchar(); //接收回车
Queue Q; //辅助队列Q
Q.InitQueue();
for(int i=0;i<G.vexnum;i++)
if(!visited[i]) //i尚未访问
{
e=base[front];
front=(front+1)%QUEUE_SIZE;
}
public:
int *base;
int front;
int rear;
};
int Locate(Graph G,char c) //图G中查找元素c的位置
for(j=0;j<G.vexnum;j++)
G.arcs[i][j]=INFINITY;
cout<<"输入%d条边分别为:\n",G.arcnum; //读取边信息并初始化集合
for(i=0;i<G.arcnum;i++) //初始化边
深度遍历和广度遍历例题
深度遍历和广度遍历例题深度遍历(Depth-First Search,DFS)和广度遍历(Breadth-First Search,BFS)是图遍历算法中常用的两种方法。
下面我将为你提供一个例题,并从多个角度进行全面的回答。
例题,给定一个无向图,使用深度遍历和广度遍历两种方法遍历该图,并输出遍历的结果。
首先,我们需要明确一下图的表示方式。
常用的图表示方法有邻接矩阵和邻接表,这里我们选择使用邻接表表示图。
假设我们有如下无向图:A./ \。
B---C.\ /。
D.邻接表表示如下:A: B, C.B: A, C, D.C: A, B, D.D: B, C.接下来,我们来进行深度遍历。
深度遍历的基本思想是从起始节点开始,尽可能深地访问每个节点,直到无法继续深入为止,然后回溯到上一个节点,继续访问其他未访问的节点。
从节点A开始进行深度遍历,访问顺序为A-B-C-D。
具体步骤如下:1. 将节点A标记为已访问。
2. 访问与节点A相邻的未被访问的节点,即节点B和节点C。
3. 选择其中一个节点(这里选择节点B),将其标记为已访问,并继续深度遍历该节点。
4. 对节点B进行相同的操作,访问与节点B相邻的未被访问的节点,即节点A、节点C和节点D。
5. 选择其中一个节点(这里选择节点C),将其标记为已访问,并继续深度遍历该节点。
6. 对节点C进行相同的操作,访问与节点C相邻的未被访问的节点,即节点A、节点B和节点D。
7. 选择其中一个节点(这里选择节点D),将其标记为已访问,并继续深度遍历该节点。
8. 由于节点D没有未被访问的相邻节点,回溯到节点C。
9. 由于节点C也没有未被访问的相邻节点,回溯到节点B。
10. 由于节点B还有一个未被访问的相邻节点(节点A),将其标记为已访问,并继续深度遍历该节点。
11. 由于节点A没有未被访问的相邻节点,回溯到节点B。
12. 由于节点B没有未被访问的相邻节点,回溯到节点A。
13. 完成深度遍历。
采用邻接矩阵表示法创建图,并进行深度优先搜索遍历
东华理工大学长江学院信息工程系数据结构课题设计专业:计算机科学与技术姓名:赵进城学号:20173031308 日期:2018/05/24采用邻接矩阵表示法创建图,并进行深度优先搜索遍历1、代码运行截图2、附源代码:// data.cpp : Defines the entry point for the console application.//#include "stdafx.h"#include <iostream>using namespace std;#define MVNum 100//最大顶点数typedef char VerTexType;//假设顶点的数据类型为字符型typedef int ArcType; //假设边的权值类型为整型//------------图的邻接矩阵------------------typedef struct{VerTexType vexs[MVNum]; //顶点表ArcType arcs[MVNum][MVNum]; //邻接矩阵int vexnum,arcnum; //图的当前点数和边数}Graph;bool visited[MVNum]; //访问标志数组,其初值为"false"int FirstAdjVex(Graph G , int v);//返回v的第一个邻接点int NextAdjVex(Graph G , int v , int w);//返回v相对于w的下一个邻接点int LocateVex(Graph G , VerTexType v){//确定点v在G中的位置for(int i = 0; i <G.vexnum; ++i)if(G.vexs[i] == v)return i;return -1;}//LocateVexvoid CreateUDN(Graph&G){//采用邻接矩阵表示法,创建无向网Gint i , j , k;cout<<"请输入总顶点数,总边数,以空格隔开:";cin>>G.vexnum>>G.arcnum;//输入总顶点数,总边数cout<<endl;cout<< "输入点的名称,如a" <<endl;for(i = 0; i <G.vexnum; ++i){cout<< "请输入第" << (i+1) << "个点的名称:";cin>>G.vexs[i]; //依次输入点的信息}cout<<endl;for(i = 0; i <G.vexnum; ++i) //初始化邻接矩阵,边的权值均置为极大值MaxIntfor(j = 0; j <G.vexnum; ++j)G.arcs[i][j] = 0;cout<< "输入边依附的顶点,如a b" <<endl;for(k = 0; k <G.arcnum;++k){//构造邻接矩阵VerTexType v1 , v2;cout<< "请输入第" << (k + 1) << "条边依附的顶点:";cin>> v1 >> v2;//输入一条边依附的顶点及权值i = LocateVex(G, v1); j = LocateVex(G, v2);//确定v1和v2在G中数组的下标G.arcs[j][i] = G.arcs[i][j] = 1;//置<v1, v2>的对称边<v2, v1>的权值为w}//for}//CreateUDNvoid DFS(Graph G, int v){//图G为邻接矩阵类型int w;cout<<G.vexs[v]<<" ";visited[v]=true;for (w=0;w<G.vexnum;w++)if((G.arcs[v][w]!=0)&&(!visited[w]))DFS(G,w);}//DFSint FirstAdjVex(Graph G , int v){//返回v的第一个邻接点int i;for(i = 0 ; i <G.vexnum ; ++i){if(G.arcs[v][i] == 1 && visited[i] == false) return i;}return -1;}//FirstAdjVexint NextAdjVex(Graph G , int v , int w){//返回v相对于w的下一个邻接点int i;for(i = w ; i <G.vexnum ; ++i){if(G.arcs[v][i] == 1 && visited[i] == false)return i;}return -1;}//NextAdjVexint main(){cout<< "******采用邻接矩阵表示图的深度优先搜索遍历********" <<endl<<endl;Graph G;CreateUDN(G);cout<<endl;cout<< "无向图G创建完成!" <<endl<<endl;cout<< "请输入遍历无向图G的起始点:"; VerTexType c;cin>> c;int i;for(i = 0 ; i <G.vexnum ; ++i){if(c == G.vexs[i])break;}cout<<endl;while(i >= G.vexnum){cout<< "该点不存在,请重新输入!" <<endl;cout<< "请输入遍历连通图的起始点:";cin>> c;for(i = 0 ; i <G.vexnum ; ++i){if(c == G.vexs[i])break;}}cout<< "深度优先搜索遍历无向图G结果:" <<endl;DFS(G , i);cout<<endl;return 0;}//main。
数据结构(visualc++)用邻接矩阵表示给定无向图并进行深度遍历
1.给定无向图,请用邻接矩阵表示法表示该图#include<iostream>#include<string>using namespace std;#define MAX 20typedef int Adj[MAX][MAX];typedef struct{string vexs[MAX]; //顶点表Adj arcs; //邻接矩阵int vexnum,arcnum; //图的顶点和弧数}MGraph;int LocateVex(MGraph &G,string u);int CreateUDN(MGraph &G){int i,k,j;string v1,v2;cout<<"请输入顶点数、弧数:";cin>>G.vexnum>>G.arcnum;cout<<"输入顶点:";for(i=0;i<G.vexnum;i++){cin>>G.vexs[i]; //构造顶点数}for(i=0;i<G.vexnum;i++){ //构造邻接矩阵for(j=0;j<G.vexnum;j++){G.arcs[i][j]=0;}}for(k=0;k<G.arcnum;k++){cout<<"输入第"<<k+1<<"边依附的两个顶点:";cin>>v1>>v2;i=LocateVex(G,v1); j=LocateVex(G,v2);G.arcs[i][j]=1;G.arcs[j][i]=1; //置<v1,v2>的对称弧<v2,v1>}return 0;v 4 v 5 v 3v 2 v 1}int LocateVex(MGraph &G,string u){ //确定u在G中序号int i;for (i=0;i<G.vexnum;i++){if (u==G.vexs[i])return i;}if (i==G.vexnum){cout<<"Error u!"<<endl;exit(1);}return 0;}void ShowG(MGraph &G){int i,j;for(i=0;i<G.vexnum;i++){cout<<G.vexs[i]<<" ";}cout<<endl;for(i=0;i<G.vexnum;i++){for(j=0;j<G.vexnum;j++){cout<<G.arcs[i][j]<<" ";}cout<<endl;}}main(){MGraph A;int a;a=CreateUDN(A);ShowG(A);}2.分别使用邻接矩阵表示法和邻接表表示法,用深度优先搜索法遍历该图。
基于邻接矩阵存储的图的深度优先遍历和广度优先遍历
基于邻接矩阵存储的图的深度优先遍历和⼴度优先遍历图的存储结构相⽐较线性表与树来说就复杂很多,对于线性表来说,是⼀对⼀的关系,所以⽤数组或者链表均可简单存放。
树结构是⼀对多的关系,所以我们要将数组和链表的特性结合在⼀起才能更好的存放。
那么我们的图,是多对多的情况,另外图上的任何⼀个顶点都可以被看作是第⼀个顶点,任⼀顶点的邻接点之间也不存在次序关系。
仔细观察以下⼏张图,然后深刻领悟⼀下:因为任意两个顶点之间都可能存在联系,因此⽆法以数据元素在内存中的物理位置来表⽰元素之间的关系(内存物理位置是线性的,图的元素关系是平⾯的)。
如果⽤多重链表来描述倒是可以做到,但在⼏节课前的树章节我们已经讨论过,纯粹⽤多重链表导致的浪费是⽆法想像的(如果各个顶点的度数相差太⼤,就会造成巨⼤的浪费)。
邻接矩阵(⽆向图)考虑到图是由顶点和边或弧两部分组成,合在⼀起⽐较困难,那就很⾃然地考虑到分为两个结构来分别存储。
顶点因为不区分⼤⼩、主次,所以⽤⼀个⼀维数组来存储是狠不错的选择。
⽽边或弧由于是顶点与顶点之间的关系,⼀维数组肯定就搞不定了,那我们不妨考虑⽤⼀个⼆维数组来存储。
图的邻接矩阵(Adjacency Matrix)存储⽅式是⽤两个数组来表⽰图。
⼀个⼀维数组存储图中顶点信息,⼀个⼆维数组(称为邻接矩阵)存储图中的边或弧的信息。
我们可以设置两个数组,顶点数组为vertex[4]={V0,V1,V2,V3},边数组arc[4][4]为对称矩阵(0表⽰不存在顶点间的边,1表⽰顶点间存在边)。
对称矩阵:所谓对称矩阵就是n阶矩阵的元满⾜a[i][j]=a[j][i](0<=i,j<=n)。
即从矩阵的左上⾓到右下⾓的主对⾓线为轴,右上⾓的元与左下⾓相对应的元全都是相等的。
有了这个⼆维数组组成的对称矩阵,我们就可以很容易地知道图中的信息:1. 要判定任意两顶点是否有边⽆边就⾮常容易了;2. 要知道某个顶点的度,其实就是这个顶点Vi在邻接矩阵中第i⾏(或第i列)的元素之和;3. 求顶点Vi的所有邻接点就是将矩阵中第i⾏元素扫描⼀遍,arc[i][j]为1就是邻接点咯。
数据结构(visualc++)用邻接矩阵表示给定无向图并进行深度遍历
1.给定无向图,请用邻接矩阵表示法表示该图#include<iostream>#include<string>using namespace std;#define MAX 20typedef int Adj[MAX][MAX];typedef struct{string vexs[MAX]; //顶点表Adj arcs; //邻接矩阵int vexnum,arcnum; //图的顶点和弧数}MGraph;int LocateVex(MGraph &G ,string u);int CreateUDN(MGraph &G){int i,k,j;string v1,v2;cout<<"请输入顶点数、弧数:";cin>>G .vexnum>>G .arcnum;cout<<"输入顶点:";for(i=0;i<G .vexnum;i++){cin>>G .vexs[i]; //构造顶点数}for(i=0;i<G .vexnum;i++){ //构造邻接矩阵for(j=0;j<G .vexnum;j++){G .arcs[i][j]=0;}}for(k=0;k<G .arcnum;k++){cout<<"输入第"<<k+1<<"边依附的两个顶点:";cin>>v1>>v2;i=LocateVex(G ,v1); j=LocateVex(G ,v2);G .arcs[i][j]=1;G .arcs[j][i]=1; //置<v1,v2>的对称弧<v2,v1>}return 0;v 4 v 5 v 3v 2 v 1}int LocateVex(MGraph &G,string u){ //确定u在G中序号int i;for (i=0;i<G.vexnum;i++){if (u==G.vexs[i])return i;}if (i==G.vexnum){cout<<"Error u!"<<endl;exit(1);}return 0;}void ShowG(MGraph &G){int i,j;for(i=0;i<G.vexnum;i++){cout<<G.vexs[i]<<" ";}cout<<endl;for(i=0;i<G.vexnum;i++){for(j=0;j<G.vexnum;j++){cout<<G.arcs[i][j]<<" ";}cout<<endl;}}main(){MGraph A;int a;a=CreateUDN(A);ShowG(A);}2.分别使用邻接矩阵表示法和邻接表表示法,用深度优先搜索法遍历该图。
基于java数据结构实验 基于邻接矩阵和邻接表的深度广度优先遍历图
基于邻接表:基于基于邻接矩阵:实验总结(结论或问题分析):通过这次实验,我掌握了无向图的建立,一种基于邻接表,一种基于邻接矩阵,然后分别实现深度广度优先遍历。
广度优先遍历类似于数的层序遍历,它的思想是从一个顶点V0开始,辐射状地优先遍历其周围较广的区域。
深度优先遍历是从图的某个顶点出发,访问这个顶点,然后从v的没访问过的邻接点出发深度优先遍历图,直到图中所有和v有路径相通的顶点都被访问到。
实验成绩任课教师签名附:源程序:参考:基于邻接表的深度广度遍历package graph;import java.util.*;public class ALgraph{static class Vertex<T> {private T date;private Edge frist;public T getDate() {return date;}public void setDate(T date) {this.date = date;}public Edge getFrist() {return frist;}public void setFrist(Edge frist) {this.frist = frist;}}static class Edge {private int vertexIndex;private Edge next;public int getVertexIndex() {return vertexIndex;}public void setVertexIndex(int vertexIndex) {this.vertexIndex = vertexIndex;}public Edge getNext() {//System.out.println(next);if(next==null){return null;}return next;}public void setNext(Edge next) {this.next = next;}}public static Vertex[] set(int x,int y){//参考输入数据 1 2 3 4 5//1 3 1 2 1 4 1 5 2 5 2 4Scanner sc=new Scanner(System.in);Vertex[]arr=new Vertex[x];Vertex<String> v=null;System.out.println("请依次输入顶点的信息空格分开");for(int i=0;i<x;i++){String str=sc.next();v=new Vertex<String>();v.setDate(str);v.setFrist(null);arr[i]=v;}System.out.println("请依次输入边的信息空格分开 (根据你输入的顶点信息来)");Edge e=null;int str1,str2;//System.out.println(y);for(int j=0;j<y;j++){str1=sc.nextInt();str2=sc.nextInt();//System.out.println("str1:"+str1+"str2:"+str2);e=new Edge();e.setVertexIndex(str2-1);if(arr[str1-1].getFrist()==null){arr[str1-1].setFrist(e);}else{Edge e2=arr[str1-1].getFrist();while(e2.getNext()!=null){e2=e2.getNext();}//System.out.println(e.getVertexIndex());e2.setNext(e);}}return arr;}public static void dfs(Vertex[] arr) {boolean[] b = new boolean[arr.length];System.out.println();for (int j = 0, len = arr.length; j < len; j++) { //如果这个顶点没有被访问过;if (!b[j]) {fun(arr, j, b);}}System.out.println();}private static void fun(Vertex[] arr,int i,boolean[] b){ b[i]=true;//System.out.println(i);System.out.print(arr[i].getDate()+"\t");Edge e=arr[i].getFrist();while(e!=null){//对i的第一条边的顶点进行访问if(!b[e.getVertexIndex()]){fun(arr, e.getVertexIndex(), b);}e=arr[e.getVertexIndex()].getFrist();// if(b[e.getVertexIndex()]){// break;// }}e=arr[i].getFrist();if(e!=null&&e.getNext()!=null){ //对i坐标的顶点剩下的顶点进行访问e=e.getNext();}//1 2 1 3 2 4 3 5 5 4 4 6 6 7 7 5while(e!=null){if(!b[e.getVertexIndex()]){fun(arr, e.getVertexIndex(), b);}e=e.getNext();if(e==null||b[e.getVertexIndex()]){break;}}return;}public static void bfs(Vertex[] arr) {Queue<Vertex<String>> q = new LinkedList<Vertex<String>>();boolean[] b = new boolean[arr.length];for (int i = 0, len = arr.length; i < len; i++) {//如果该顶点没被访问过if (!b[i]) {System.out.print(arr[i].getDate()+"\t");b[i] = true;//将该顶点入队列q.add(arr[i]);//如果队列不是空while (!q.isEmpty()) {//v等于出队的顶点Vertex<String>v= q.poll();//e等于v的第一条连接的边Edge e = v.getFrist();//如果e不是空while (e != null) {//如果e所连接的顶点没被访问过if(!b[e.getVertexIndex()]){//该顶点入队q.add(arr[e.getVertexIndex()]);//输出该顶点的值System.out.print(arr[e.getVertexIndex()].getDate()+"\t");b[e.getVertexIndex()]=true;}//寻找改顶点的下一条边e=e.getNext();}}}}System.out.println();}public static void main(String[] args) {Vertex<Integer>[]arr=set(6, 6);System.out.println();System.out.println("深度优先遍历");dfs(arr);System.out.println("宽度优先遍历");bfs(arr);}}基于邻接矩阵:package graph;import java.util.*;public class Matrixgraph {private int[][] edges;private int num;//图的结点数量private boolean[] visited ;//结点是否被访问过private Vertex[] vertex ;private int pre;//用来记录前一个public void createGraph(){Scanner in = new Scanner(System.in);System.out.print("please input the info:");String str = in.next();String[] temp = str.split(",");System.out.print(temp.length);this.num = temp.length;System.out.print(num);visited = new boolean[num];vertex = new Vertex[num];for(int i=0;i<num;i++){Vertex v = new Vertex(i,temp[i]);vertex[i]=v;visit(vertex[i]);System.out.println();}edges = new int[num][num];for(int i=0;i<num;i++){for(int j=0;j<num;j++){Scanner in1 = new Scanner(System.in);System.out.print("input the value:");int k = in1.nextInt();/* System.out.print(k);*/edges[i][j] =k;}}}public void visit(Vertex v){if(v!=null){System.out.print( v.no+" "+);System.out.println();}}public void dFS(int i){visit(vertex[i]);visited[i]=true;for(int j=i+1;j<num;j++){if(!visited[j]&&edges[i][j]!=0){dFS(j);} } }public void dFSTrave(){//深度遍历是在邻接矩阵的基础上进行的for(int i=0;i<num;i++){visited[i]=false;//默认情况下所有顶点是没有被访问过的}for(int i=0;i<num;i++){if(!visited[i]){//还需要考虑一个条件就是必须可达dFS(i);}}}public void bFSTrave(){for(int i=0;i<num;i++){visited[i]=false;//默认情况下所有顶点是没有被访问过的}Vertex v=null;Queue queue = new LinkedList();for(int i=0;i<num;i++){if(!visited[i]){visit(vertex[i]);visited[i]=true;//访问完成后入队queue.add( vertex[i]);while(!queue.isEmpty()){v = (Vertex) queue.poll();if(v!=null){int k = v.no;for(int j=k+1;j<num;j++){if(!visited[j]&&edges[k][j]!=0){visit(vertex[j]);visited[j]=true;queue.add( vertex[j]);}}}}}}}public static void main(String[] args) {Matrixgraph graph = new Matrixgraph();graph.createGraph();graph.dFSTrave();// graph.bFSTrave();}class Vertex {//图的顶点信息public int no;//顶点的标号public String info;//顶点的信息public Vertex(int i,String info){this.no = i; = info;}}}参考程序1:public class Graph {private int[] vertexs;private int vertexsize;private int[][] matrix;private boolean[] isvisited;private static final int MAX_WEIGHT=1000;public Graph(int vertexsize){this.vertexsize=vertexsize;matrix=new int[vertexsize][vertexsize];vertexs=new int[vertexsize];for(int i=0;i<vertexsize;i++){vertexs[i]=i;}isvisited=new boolean[vertexsize];}public int[] getVertexs() {return vertexs;}public void setVertexs(int[] vertexs) {this.vertexs = vertexs;}public int getweight(int v1,int v2){return matrix[v1][v2]==0?0:(matrix[v1][v2]==MAX_WEIGHT?-1:matrix[v1][v2]); }public int getdegree(int index){int degree=0;for(int j=0;j<matrix[index].length;j++){int weight=matrix[index][j];if(weight!=0&&weight!=MAX_WEIGHT){degree++;}}return degree;}//找某个顶点的第一个邻接点public int getfirstadj(int index){for(int j=0;j<vertexsize;j++){if(matrix[index][j]>0&&matrix[index][j]<MAX_WEIGHT){return j;}}return -1;}public int getnextadj(int v,int index){for(int j=index+1;j<vertexsize;j++){if(matrix[v][j]>0&&matrix[v][j]<MAX_WEIGHT){return j;}}return -1;}public void depthfirstsearch(int i){isvisited[i]=true;int w=getfirstadj(i);while(w!=-1){if(!isvisited[w]){System.out.println("访问"+w+"顶点");depthfirstsearch(w);}w=getnextadj(i,w);}}public void depthfirstsearch(){}public static void main(String[] args) {Graph graph=new Graph(5);int [] a1=new int[]{0,45,28,10,MAX_WEIGHT};int [] a2=new int[]{45,0,12,MAX_WEIGHT,21};int [] a3=new int[]{28,12,0,17,26};int [] a4=new int[]{10,MAX_WEIGHT,17,0,15};int [] a5=new int[]{MAX_WEIGHT,21,26,15,0};graph.matrix[0]=a1;graph.matrix[1]=a2;graph.matrix[2]=a3;graph.matrix[3]=a4;graph.matrix[4]=a5;//System.out.println("权值"+graph.getweight(0, 3));//System.out.println("v0的度:"+graph.getdegree(2));graph.depthfirstsearch();}}。
图的深度优先遍历和广度优先遍历
华北水利水电学院数据结构实验报告20 10 ~20 11 学年第一学期2008级计算机专业班级:107学号:200810702姓名:王文波实验四图的应用一、实验目的:1.掌握图的存储结构及其构造方法2.掌握图的两种遍历算法及其执行过程二、实验内容:以邻接矩阵或邻接表为存储结构,以用户指定的顶点为起始点,实现无向连通图的深度优先及广度优先搜索遍历,并输出遍历的结点序列。
提示:首先,根据用户输入的顶点总数和边数,构造无向图,然后以用户输入的顶点为起始点,进行深度优先和广度优先遍历,并输出遍历的结果。
三、实验要求:1.各班学号为单号的同学采用邻接矩阵实现,学号为双号的同学采用邻接表实现。
2.C/ C++完成算法设计和程序设计并上机调试通过。
3.撰写实验报告,提供实验结果和数据。
4.写出算法设计小结和心得。
四、程序源代码:#include<iostream.h>#define MaxVerNum 50struct edgenode{int endver;int inform;edgenode* edgenext;};struct vexnode{char vertex;edgenode* edgelink;};struct Graph{vexnode adjlists[MaxVerNum];int vexnum;int arcnum;};//队列的定义及相关函数的实现struct QueueNode{int nData;QueueNode* next;};struct QueueList{QueueNode* front;QueueNode* rear;};void EnQueue(QueueList* Q,int e) {QueueNode *q=new QueueNode;q->nData=e;q->next=NULL;if(Q==NULL)return;if(Q->rear==NULL)Q->front=Q->rear=q;else{Q->rear->next=q;Q->rear=Q->rear->next;}}void DeQueue(QueueList* Q,int* e) {if (Q==NULL)return;if (Q->front==Q->rear){*e=Q->front->nData;Q->front=Q->rear=NULL;}else{*e=Q->front->nData;Q->front=Q->front->next;}}//创建图void CreatAdjList(Graph* G){int i,j,k;edgenode* p1;edgenode* p2;cout<<"请输入顶点数和边数:"<<endl;cin>>G->vexnum>>G->arcnum;cout<<"开始输入顶点表:"<<endl;for (i=0;i<G->vexnum;i++){cin>>G->adjlists[i].vertex;G->adjlists[i].edgelink=NULL;}cout<<"开始输入边表信息:"<<endl;for (k=0;k<G->arcnum;k++){cout<<"请输入边<Vi,Vj>对应的顶点:";cin>>i>>j;p1=new edgenode;p1->endver=j;p1->edgenext=G->adjlists[i].edgelink;G->adjlists[i].edgelink=p1;p2=new edgenode;p2->endver=i;p2->edgenext=G->adjlists[j].edgelink;G->adjlists[j].edgelink=p2;//因为是无向图,所以有两次建立边表的过程}}//-------------------------------------------------------------深度优先遍历void DFS(Graph *G,int i,int visit[]){cout<<G->adjlists[i].vertex<<" ";visit[i]=1;edgenode *p=new edgenode;p=G->adjlists[i].edgelink;if(G->adjlists[i].edgelink&&!visit[p->endver]){DFS(G,p->endver,visit);}}void DFStraversal(Graph *G,char c)//深度优先遍历{cout<<"该图的深度优先遍历结果为:"<<endl;int visit[MaxVerNum];for(int i=0;i<G->vexnum;i++){visit[i]=0;//全部初始化为0,即未访问状态}int m;for (i=0;i<G->vexnum;i++){if (G->adjlists[i].vertex==c)//根据字符查找序号{m=i;DFS(G,i,visit);break;}}//继续访问未被访问的结点for(i=0;i<G->vexnum;i++){if(visit[i]==0)DFS(G,i,visit);}cout<<endl;}//-------------------------------------------------------------广度优先遍历void BFS(Graph* G,int v,int visit[]){QueueList *Q=new QueueList;Q->front=Q->rear=NULL;EnQueue(Q,v);while(Q->rear!=NULL){int e=0;DeQueue(Q,&e);cout<<G->adjlists[e].vertex<<" ";visit[e]=1;edgenode* p=new edgenode;p=G->adjlists[e].edgelink;if(p){int m=p->endver;if(m==0){EnQueue(Q,m);while(visit[m]==0){p=p->edgenext;if(p==NULL)break;m=p->endver;EnQueue(Q,m);}}}}}void BFStraversal(Graph *G,char c){cout<<"该图的广度优先遍历结果为:"<<endl;int visited[MaxVerNum];for (int i=0;i<G->vexnum;i++){visited[i]=0;}int m;for (i=0;i<G->vexnum;i++){if (G->adjlists[i].vertex==c){m=i;BFS(G,i,visited);break;}}//继续访问未被访问的结点for(i=0;i<G->vexnum;i++){if(visited[i]==0)BFS(G,i,visited);}cout<<endl;}void main(){Graph * G=new Graph;CreatAdjList(G);char ch;cout<<"请输入开始遍历的顶点:";cin>>ch;DFStraversal(G,ch);BFStraversal(G,ch);}五、程序运行情况(写出输入数据及运行结果)六、小结(包括收获、心得体会、存在的问题及解决问题的方法、建议等)注:内容一律使用宋体五号字,单倍行间距本次试验采用的是邻接表的方式实现图的深度优先遍历和广度优先遍历。
图的遍历和生成树求解实现(邻接矩阵、邻接表―图的深度广度遍历
图的遍历和生成树求解实现(邻接矩阵、邻接表―图的深度广度遍历算法的实现和最小生成树PRIM和KRUSCAL算法的实现)图的遍历和生成树求解实现(邻接矩阵、邻接表―图的深度广度遍历算法的实现和最小生成树PRIM和KRUSCAL算法的实现)#inc lude <iostream>#inc lude <malloc.h>using namespace std;#define int_max 10000#define inf 9999#define max 20//…………………………………………邻接矩阵定义……………………typedef struct ArcCell{int adj;char *info;}ArcCell,AdjMatrix[20][20];typedef struct{char vexs[20];AdjMatr ix arcs;int vexnum,arcnum;}MGraph_L;//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^int localvex(MGraph_L G,char v)//返回V的位置{int i=0;w hile(G.vexs[i]!=v){++i;}return i;}int creatMGr aph_L(MGraph_L &G)//创建图用邻接矩阵表示{char v1,v2;int i,j,w;cout<<"…………创建无向图…………"<<endl<<"请输入图G顶点和弧的个数:(4 6)不包括“()”"<<endl; cin>>G.vexnum>>G.arcnum;for(i=0;i!=G.vexnum;++i){cout<<"输入顶点"<<i<<endl;cin>>G.vexs[i];}for(i=0;i!=G.vexnum;++i)for(j=0;j!=G.vexnum;++j){G.arcs[i][j].adj=int_max;G.arcs[i][j].info=NULL;}for(int k=0;k!=G.arcnum;++k){cout<<"输入一条边依附的顶点和权:(a b 3)不包括“()”"<<endl;cin>>v1>>v2>>w;//输入一条边依附的两点及权值i=localvex(G,v1);//确定顶点V1和V2在图中的位置j=localvex(G,v2);G.arcs[i][j].adj=w;G.arcs[j][i].adj=w;}cout<<"图G邻接矩阵创建成功!"<<endl;return G.vexnum;}void ljjzprint(MGraph_L G){int i,j;for(i=0;i!=G.vexnum;++i){for(j=0;j!=G.vexnum;++j)cout<<G.arcs[i][j].adj<<" ";cout<<endl;}}int vis ited[max];//访问标记int w e;typedef struct arcnode//弧结点{int adjvex;//该弧指向的顶点的位置struct arcnode *nextarc;//弧尾相同的下一条弧char *info;//该弧信息}arcnode;typedef struct vnode//邻接链表顶点头接点{char data;//结点信息arcnode *firstarc;//指向第一条依附该结点的弧的指针}vnode,adjlist;typedef struct//图的定义{adjlist vertices[max];int vexnum,arcnum;int kind;}algraph;//…………………………………………队列定义……………………typedef struct qnode{int data;struct qnode *next;}qnode,*queueptr;typedef struct{queueptr front;queueptr rear;}linkqueue;//………………………………………………………………………typedef struct acr{int pre;//弧的一结点int bak;//弧另一结点int w eight;//弧的权}edg;int creatadj(algraph &gra,MGr aph_L G)//用邻接表存储图{int i=0,j=0;arcnode *arc,*tem,*p;for(i=0;i!=G.vexnum;++i){gra.vertices[i].data=G.vexs[i];gra.vertices[i].firstarc=NULL;}for(i=0;i!=G.vexnum;++i){for(j=0;j!=G.vexnum;++j){if(gra.vertices[i].firstarc==NULL){if(G.arcs[i][j].adj!=int_max&&j!=G.vexnum){arc=(arcnode *)malloc(sizeof(arcnode));arc->adjvex=j;gra.vertices[i].firstarc=arc;arc->nextarc=NULL;p=arc;++j;w hile(G.arcs[i][j].adj!=int_max&&j!=G.vexnum) {tem=(arcnode *)malloc(sizeof(arcnode));tem->adjvex=j;gra.vertices[i].firstarc=tem;tem->nextarc=arc;arc=tem;++j;}--j;}}else{if(G.arcs[i][j].adj!=int_max&&j!=G.vexnum){arc=(arcnode *)malloc(sizeof(arcnode));arc->adjvex=j;p->nextarc=arc;arc->nextarc=NULL;p=arc;}}}}gra.vexnum=G.vexnum;gra.arcnum=G.arcnum;/*for(i=0;i!=gra.vexnum;++i){arcnode *p;cout<<i<<" ";p=gra.vertices[i].firstarc;w hile(p!=NULL){cout<<p->adjvex;p=p->nextarc;}cout<<endl;}*/cout<<"图G邻接表创建成功!"<<endl;return 1;}void adjpr int(algraph gra){int i;for(i=0;i!=gra.vexnum;++i){arcnode *p;cout<<i<<" ";p=gra.vertices[i].firstarc;w hile(p!=NULL){cout<<p->adjvex;p=p->nextarc;}cout<<endl;}}int firstadjvex(algraph gra,vnode v)//返回依附顶点V的第一个点 //即以V为尾的第一个结点{if(v.firstarc!=NULL)return v.firstarc->adjvex;int nextadjvex(algraph gra,vnode v,int w)//返回依附顶点V的相对于W的下一个顶点{arcnode *p;p=v.firstarc;w hile(p!=NULL&&p->adjvex!=w){p=p->nextarc;}if(p->adjvex==w&&p->nextarc!=NULL){p=p->nextarc;return p->adjvex;}if(p->adjvex==w&&p->nextarc==NULL)return -10;}int initqueue(linkqueue &q)//初始化队列{q.rear=(queueptr)malloc(sizeof(qnode));q.front=q.rear;if(!q.front)return 0;q.front->next=NULL;return 1;}int enqueue(linkqueue &q,int e)//入队{queueptr p;p=(queueptr)malloc(sizeof(qnode));if(!p)return 0;p->data=e;p->next=NULL;q.rear->next=p;q.rear=p;return 1;}int dequeue(linkqueue &q,int &e)//出队{queueptr p;if(q.front==q.r ear)return 0;p=q.front->next;e=p->data;q.front->next=p->next;if(q.rear==p)q.rear=q.front;free(p);return 1;}int queueempty(linkqueue q)//判断队为空{if(q.front==q.r ear)return 1;return 0;}void bfstra(algraph gra)//广度优先遍历{int i,e;linkqueue q;for(i=0;i!=gra.vexnum;++i)visited[i]=0;initqueue(q);for(i=0;i!=gra.vexnum;++i)if(!visited[i]){ visited[i]=1;cout<<gr a.vertices[i].data;enqueue(q,i);w hile(!queueempty(q)){dequeue(q,e);// cout<<" "<<e<<" ";for(w e=firstadjvex(gra,gra.vertices[e]);w e>=0;w e=nextadjvex(gra,gra.vertices[e],w e)) {if(!v isited[w e]){visited[w e]=1;cout<<gra.vertices[w e].data;enqueue(q,w e);}}}}}int dfs(algraph gra,int i);//声明DFSint dfstra(algraph gra){int i,j;for(i=0;i!=gra.vexnum;++i){visited[i]=0;}for(j=0;j!=gra.vexnum;++j){if(visited[j]==0)dfs(gra,j);}return 0;}int dfs(algraph gra,int i){visited[i]=1;int w e1;// cout<<i<<visited[i]<<endl;cout<<gra.vertices[i].data;// cout<<endl;for(w e=firstadjvex(gra,gra.vertices[i]);w e>=0;w e=nextadjvex(gra,gra.vertices[i],w e)) {// cout<<w e<<visited[w e]<<endl;w e1=w e;// cout<<nextadjvex(gra,gra.vertices[i],w e)<<endl;if(visited[w e]==0)// cout<<dfs(gra,w e);//<<endl;// cout<<i<<w e1<<endl;w e=w e1;// cout<<nextadjvex(gra,gra.vertices[i],w e)<<endl;}return 12;}int bfstra_fen(algr aph gra)//求连通分量{int i,j;for(i=0;i!=gra.vexnum;++i){visited[i]=0;}for(j=0;j!=gra.vexnum;++j){if(visited[j]==0){dfs(gra,j);cout<<endl;}}return 0;}typedef struct{int adjvex;int low cost;}closedge;/*int minimum(c losedge *p);int minispantree(MGraph_L G,char u){int k,j,i;closedge closedge_a[20];k=localvex(G,u);// cout<<k<<endl;for(j=0;j!=G.vexnum;++j){if(j!=k){closedge_a[j].adjvex=u;closedge_a[j].low cost=G.arcs[k][j].adj;}for(i=1;i!=G.vexnum;++i){k=minimum(closedge_a);cout<<k;cout<<closedge_a[k].adjvex<<" "<<G.vexs[k]<<endl; closedge_a[k].low cost=0;for(j=0;j!=G.vexnum;++j)if(G.arcs[k][j].adj<closedge_a[j].low cost){closedge_a[j].adjvex=G.vexs[k];closedge_a[j].low cost=G.arcs[k][j].adj;}}}return 0;}int minimum(closedge *p){int s=10000;for(;p!=NULL;++p){if(s>p->lowcost)s=p->low cost;}return s;}*/int pr im(int g[][max],int n) //最小生成树PRIM算法{int low cost[max],prevex[max]; //LOWCOST[]存储当前集合U分别到剩余结点的最短路径 //prevex[]存储最短路径在U中的结点int i,j,k,min;for(i=2;i<=n;i++) //n个顶点,n-1条边{low cost[i]=g[1][i]; //初始化prevex[i]=1; //顶点未加入到最小生成树中}low cost[1]=0; //标志顶点1加入U集合for(i=2;i<=n;i++) //形成n-1条边的生成树{min=inf;k=0;for(j=2;j<=n;j++) //寻找满足边的一个顶点在U,另一个顶点在V的最小边if((lowcost[j]<min)&&(low cost[j]!=0)){min=low cost[j];k=j;}printf("(%d,%d)%d\t",prevex[k]-1,k-1,min);low cost[k]=0; //顶点k加入Ufor(j=2;j<=n;j++) //修改由顶点k到其他顶点边的权值if(g[k][j]<low cost[j]){low cost[j]=g[k][j];prevex[j]=k;}printf("\n");}return 0;}int acrvisited[100];//kruscal弧标记数组int find(int acrvisited[],int f){w hile(acrvisited[f]>0)f=acrvisited[f];return f;}void kruscal_arc(MGraph_L G,algraph gra) {edg edgs[20];int i,j,k=0;for(i=0;i!=G.vexnum;++i)for(j=i;j!=G.vexnum;++j){if(G.arcs[i][j].adj!=10000){edgs[k].pre=i;edgs[k].bak=j;edgs[k].w eight=G.arcs[i][j].adj;++k;}}int x,y,m,n;int buf,edf;for(i=0;i!=gra.arcnum;++i)acrvisited[i]=0;for(j=0;j!=G.arcnum;++j){m=10000;for(i=0;i!=G.arcnum;++i){if(edgs[i].w eight<m){m=edgs[i].w eight;x=edgs[i].pre;y=edgs[i].bak;n=i;}}// cout<<x<<y<<m;// cout<<endl;buf=find(acrvisited,x);edf=find(acrvisited,y);// cout<<buf<<" "<<edf<<endl;edgs[n].w eight=10000;if(buf!=edf){acrvisited[buf]=edf;cout<<"("<<x<<","<<y<<")"<<m;cout<<endl;}}}void main(){algraph gr a;MGraph_L G;int i,d,g[20][20];char a='a';d=creatMGr aph_L(G);creatadj(gra,G);vnode v;cout<<endl<<"……####注意:若该图为非强连通图(含有多个连通分量)时"<<endl <<" 最小生成树不存在,则显示为非法值。
邻接矩阵表示的图的基本操作的实现
邻接矩阵表示的图的基本操作的实现//采用邻接矩阵完成无权无向及有向图的"建立、输出、深度遍历、广度遍历"操作#include <stdio.h>#include <stdlib.h>#define OK 1#define ERROR -1typedef int Status;typedef int ElemType; //此例中设元素为单值元素,类型为整型#define MAX_VERTEX_NUM 20 //最大顶点个数typedef int ElemType; //图顶点数据类型typedef int QueueElemType;//队列结点数据类型//链表结点类型定义typedef struct Qnode{QueueElemType data;struct Qnode *next;}QNode;//队列类型定义:typedef struct Linkqueue{QNode *front,*rear;}LinkQueue;//图的数据类型定义typedef struct Mgraph{ElemType vector[MAX_VERTEX_NUM]; //顶点向量int adj[MAX_VERTEX_NUM][MAX_VERTEX_NUM];//邻接矩阵int vexnum; //图中当前顶点数int arcnum; //图中当前边数} MGraph;//队列初始化Status InitLinkQueue(LinkQueue *Q){QNode *p;p=(QNode*)malloc(sizeof(QNode));//开辟头结点空间if(p!=NULL){p->next=NULL;Q->front=Q->rear=p;return OK;}elsereturn ERROR;}//链式队列的入队操作,在已知队列的队尾插入一个元素e,修改队尾指针rear。
建立图地邻接矩阵或邻接表存储并在此基础上实现图地深度优先遍历和广度优先遍历
#include "stdafx.h"#include "conio.h"#include "stdio.h"#include "stdlib.h"typedef enum {FALSE, TRUE} BOOLEAN;#define OVERFLOW -1#define OK 1#define ERROR 0#define INFINITY INT_MAX /* 最大值∞ *//* 根据图的权值类型,分别定义为最大整数或实数 */ #define MAX_VERTEX_NUM 20 /* 最大顶点数目 */ typedef enum {DG, DN, UDG,UDN} GraphKind ;/* {有向图,有向网,无向图,无向网} */BOOLEAN Visited[MAX_VERTEX_NUM];BOOLEAN visited[MAX_VERTEX_NUM];#define VEX_NUM 20#define MAXSIZE 50typedef char Vextype;typedef int ElemType;typedef int Status;////////////////////////////// 邻接矩阵结构定义typedef struct {Vextype vexs[VEX_NUM];int adj[VEX_NUM][VEX_NUM]; /*邻接矩阵*/ int n,e; /*顶点数和边数*/}Mgraph;////////////////////////////// 邻接表结构定义typedef struct node { /*边结点*/int adjvex; /*邻接点域*/struct node * nextarc; /*指向下一个边结点的指针域*/} EdgeNode;typedef struct vnode { //顶点结构,2个域,结点信息和第一个邻接点Vextype vertex;EdgeNode *firstedge;}VertexNode;typedef struct { //图结构VertexNode adjlist[MAXSIZE];int n,e;} ALGraph;////int FirstAdjVex(ALGraph G,int v){//在图G中寻找第v个顶点的第一个邻接顶点if(!G.adjlist[v].firstedge) return -1;else return(G.adjlist[v].firstedge->adjvex);}int NextAdjVex(ALGraph G,int v,int w){//在图G中寻找第v个顶点的相对于w的下一个邻接顶点EdgeNode *p;int vi;p=G.adjlist[v].firstedge;if(!p) return -1;while(p->adjvex!=w) p=p->nextarc; //在顶点v的弧链中找到顶点w p=p->nextarc;if(!p) return -1; //若已是最后一个顶点,返回-1else {vi=p->adjvex;return vi; //返回下一个邻接顶点的序号}}////void CreateMGraph(Mgraph *G) {int i,j,k; // char ch;printf("请输入顶点数和边数:\n");scanf("%d,%d",&(G->n),&(G->e)); /*输入*/printf("请输入顶点信息:\n");for (i=0;i<G->n;i++)scanf("%s",&(G->vexs[i]));for (i=0;i<G->n;i++)for (j=0;j<G->n;j++)G->adj[i][j]=0; /*初始化邻接矩阵*/printf("输入每条边对应的两个顶点的序号:\n");for (k=0;k<G->e;k++) {scanf("%d,%d",&i,&j); /*输入e条边*/G->adj[i][j]=1;G->adj[j][i]=1; /*对称加入,无向图的邻接矩阵存储建立*/ }}/*CreateMGraph*/void CreateALGraph(ALGraph *G){ /*建立无向图的邻接表存储*/int i,j,k;char vi;EdgeNode *s;printf("请输入顶点数和边数:\n");scanf("%d,%d",&(G->n),&(G->e));printf("请输入顶点信息Vi\n例如a,每输入一个顶点后回车:\n");for (i=0;i<G->n;i++) {scanf("%s",&vi);G->adjlist[i].vertex=vi;G->adjlist[i].firstedge=NULL;}printf("顶点:");for (i=0;i<G->n;i++)printf("%c(%d)-",G->adjlist[i].vertex,i+1);printf("\n请输入边的信息(vi,vj)\n例如:1,2:\n");for (k=0;k<G->e;k++) { /*建立边表*/scanf("%d,%d",&i,&j); //在头结点和边结点之间插入新的边结点s=(EdgeNode*)malloc(sizeof(EdgeNode));s->adjvex=j-1;s->nextarc=G->adjlist[i-1].firstedge;G->adjlist[i-1].firstedge=s;s=(EdgeNode*)malloc(sizeof(EdgeNode));s->adjvex=i-1;s->nextarc=G->adjlist[j-1].firstedge;G->adjlist[j-1].firstedge=s;}////输出邻接表...}/*CreateALGraph*/void DFS(ALGraph *G, int v) {EdgeNode *p ;Visited[v]=TRUE ;printf("%c->",G->adjlist[v].vertex); /* 置访问标志,访问顶点v */p=G->adjlist[v].firstedge; /* 链表的第一个结点 */while (p!=NULL){if(!Visited[p->adjvex])DFS(G, p->adjvex);/* 从v的未访问过的邻接顶点出发深度优先搜索 */p=p->nextarc ;}}void DFS_traverse (ALGraph *G){int v ;EdgeNode *p ;printf("深度度优先搜索输出结点信息:");for (v=0; v<G->n; v++) Visited[v]=FALSE ; /* 访问标志初始化 */ p=G->adjlist[v].firstedge ;for (v=0; v<G->n; v++)if (!Visited[v]) DFS(G,v);}///////////////队列 ///////////////////////typedef struct Node{ElemType data; // 元素数据struct Node *next; // 链式队列中结点元素的指针} QNode, *QueuePtr;typedef struct{QueuePtr front; // 队列头指针QueuePtr rear; // 队列尾指针} LinkQueue;Status InitQueue(LinkQueue &Q) {//构造一个空队列QQ.front = Q.rear = (QueuePtr)malloc(sizeof(QNode)); if(Q.front == NULL) exit(OVERFLOW); //存储失败Q.front ->next = NULL;return OK;}Status DestoryQueue(LinkQueue &Q) {//销毁队列Qwhile(Q.front){Q.rear = Q.front->next; //利用尾指针移动保存队头指针free(Q.front); //依次释放头结点Q.front = Q.rear;}return OK;}Status QueueEmpty(LinkQueue Q){//assert(Q.front != NULL && Q.rear != NULL);if(Q.front == Q.rear)return TRUE;elsereturn FALSE;}Status EnQueue(LinkQueue &Q, ElemType e)//插入元素e为Q新的队尾元素{QueuePtr p = (QueuePtr )malloc(sizeof(QNode));if(!p) exit(OVERFLOW); //存储失败p ->data = e; p ->next = NULL;Q.rear ->next = p; //当前队尾指针指向新的结点Q.rear = p; //移动队尾知道到新的结点,当前结点成为队尾结点 return OK;}Status DeQueue(LinkQueue &Q, ElemType *e)//若队列不空,则删除Q的队头元素,用e返回值,并返回OK。
利用邻接表存储无向图,并深度遍历和广度遍历图
利用邻接表存储无向图,并深度遍历和广度遍历图#include <stdio.h>#include <iostream.h>#include <malloc.h>#define max 20int visited[max];int w;char *info;//该弧信息typedef struct vnode{char data;//结点信息}vnode,adjlist;typedef struct{adjlist vertices[max];int kind;}algraph;typedef struct qnode{int data;struct qnode *next;}qnode,*queptr;typedef struct{queptr front;queptr rear;}linkque;void dfs(algraph gra,int i);int creatadj(algraph &gra)//用邻接表存储图{int i,n,m;char cha;cout<<"输如结点个数:";cin>>n;cout<<"输如弧个数:";for(i=0;i<n;i++){cout<<"输如结点信息:";cin>>gra.vertices[i].data;gra.vertices[i].firstarc=NULL;}for(i=0;i<n;i++){cout<<"结点"<<i<<"是否有出度:";cin>>cha;cin>>arc->adjvex;gra.vertices[i].firstarc=arc;cout<<"是否还有出度:";cin>>cha;cin>>tem->adjvex;arc->nextarc=tem;arc=tem;cout<<"是否还有出度:";cin>>cha;}arc->nextarc=NULL;}if(cha=='n')continue;}gra.vexnum=n;p=v.firstarc;while(p!=NULL){if(p->adjvex!=w)p=p->nextarc;if(p->adjvex==w&&p->nextarc!=NULL)return p->nextarc->adjvex;else return 0;}}int initque(linkque &q)//初始化队列{q.rear=(queptr)malloc(sizeof(qnode)); q.front=q.rear;if(!q.front)return 0;q.front->next=NULL;return 1;}int enque(linkque &q,int e)//入队{queptr p;p=(queptr)malloc(sizeof(qnode));if(!p)return 0;p->data=e;p->next=NULL;q.rear->next=p;q.rear=p;return 1;}int deque(linkque &q,int &e)//出队{queptr p;if(q.front==q.rear)return 0;p=q.front->next;e=p->data;q.front->next=p->next;if(q.rear==p)q.rear=q.front;free(p);return 1;}int queempty(linkque q)//判断队为空{if(q.front==q.rear) return 1;return 0;}void bfstra(algraph gra,vnode v)//广度优先遍历{int i,e; linkque q;for(i=0;i<gra.vexnum;i++)visited[i]=0;initque(q);for(i=0;i<gra.vexnum;i++)if(!visited[i]){visited[i]=1;cout<<gra.vertices[i].data;enque(q,i);while(!queempty(q))deque(q,e);for(w=firstadjvex(gra,gra.vertices[e]);w>0;w=nextadjvex(gra,gra.vertices[e],w)) if(!visited[w]){visited[w]=1;cout<<gra.vertices[w].data;enque(q,w);}}}int dfstra(algraph gra,vnode v)//深度优先遍历{int i;for(i=0;i<gra.vexnum;i++)visited[i]=0;for(i=0;i<gra.vexnum;i++)if(!visited[i])dfs(gra,i);return 1;}void dfs(algraph gra,int i){visited[i]=1;cout<<gra.vertices[i].data;for(w=firstadjvex(gra,gra.vertices[i]);w>0;w=nextadjvex(gra,gra.vertices[i],w)) if(!visited[w])dfs(gra,w);}void main(){algraph gra;vnode v;creatadj(gra);cout<<"广度优先遍历:";bfstra(gra,v);cout<<endl;cout<<"深度优先遍历:";dfstra(gra,v);cout<<endl;}。
c语言邻接矩阵的广度优先遍历
C语言邻接矩阵的广度优先遍历1.引言在计算机科学和图论中,图是一种用来表示对象间的关系的数据结构。
图的广度优先遍历是一种用于遍历图中所有节点的算法,它从一个起始节点开始,依次访问该节点的所有邻居节点,然后再逐步向外层节点扩展,直到遍历完整个图的所有节点。
C语言是一种广泛应用的编程语言,本文将重点介绍如何利用C语言来实现邻接矩阵的广度优先遍历。
2.邻接矩阵邻接矩阵是一种常见的图的表示方法,它使用一个二维数组来表示图中节点之间的连接关系。
在邻接矩阵中,矩阵的行和列分别表示图中的节点,矩阵中的元素表示相应节点之间的连接关系。
如果节点i和节点j之间有连接,则矩阵中第i行第j列的元素为1;否则为0。
邻接矩阵的优点是可以方便地表示节点之间的连接关系,但缺点是当图中节点较多时,矩阵会占用较大的空间。
3.广度优先遍历算法广度优先遍历算法是一种用于遍历图中所有节点的算法,它通过逐层访问节点的方式来遍历整个图。
广度优先遍历算法使用一个队列来保存要访问的节点,首先将起始节点加入队列,然后逐个访问该节点的邻居节点,并将邻居节点加入队列。
接着从队列中取出下一个节点,继续访问其邻居节点,并将新的邻居节点加入队列。
直到队列为空为止,遍历结束。
4.C语言实现邻接矩阵的广度优先遍历下面将通过一个简单的例子来介绍如何利用C语言来实现邻接矩阵的广度优先遍历。
假设有如下的邻接矩阵表示的图:```1 2 3 4 51 0 1 1 0 02 1 0 0 1 13 1 0 0 1 04 0 1 1 0 15 0 1 0 1 0```其中矩阵的行和列分别表示节点,元素为1表示两个节点间有连接,为0表示没有连接。
现在要从节点1开始进行广度优先遍历。
首先需要定义一个队列来保存要访问的节点,以及一个数组来记录节点是否被访问过。
然后将起始节点加入队列,并标记为已访问。
接着从队列中取出节点1,并访问其邻居节点2和3,并将2和3加入队列。
然后从队列中取出节点2,并访问其邻居节点1、4和5,并将4和5加入队列。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
/* 采用邻接矩阵完成无向图的“建立、深度遍历、广度遍历”操作 */#include "stdio.h"#include "string.h"#define TRUE 1#define FALSE 0#define OVERFLOW -2#define OK 1#define ERROR 0typedef int Status;#define INFINITY INT_MAX /*最大值“无穷”*/#define MAX_VERTEX_NUM 20 /*最大顶点个数*/typedef int Boolean;typedef char VertexType[20];typedef int VRType;/**************以下为队列的操作************//****队列的类型定义****/typedef int QElemType;typedef struct QNode{QElemType data;struct QNode *next;} QNode, *QueuePtr;typedef struct{QueuePtr front;QueuePtr rear;} LinkQueue;/****初始化队列****/Status InitQueue(LinkQueue *Q){ (*Q).front=(*Q).rear=(QueuePtr)malloc(sizeof(QNode));if (!(*Q).front) exit(OVERFLOW);(*Q).front->next=NULL;return OK; }/****判断队列是否为空****/Status QueueEmpty (LinkQueue Q){ if (Q.front==Q.rear)return TRUE;elsereturn FALSE; }/****入队列****/Status EnQueue(LinkQueue *Q, QElemType e){ QueuePtr p;p=(QueuePtr)malloc(sizeof(QNode));if (!p) exit(OVERFLOW);p->data=e; p->next=NULL;(*Q).rear->next=p;(*Q).rear=p;return OK; }/****出队列****/Status DeQueue(LinkQueue *Q, QElemType *e){ QueuePtr p;if ((*Q).front==(*Q).rear) return ERROR;p=(*Q).front->next;*e=p->data;(*Q).front->next=p->next;if ((*Q).rear==p) (*Q).rear=(*Q).front;free(p);return OK; }/**************以下为图的操作************//*图的类型定义*/typedef struct ArcCell{ VRType adj; /*图中有1/0表示是否有边,网中表示边上的权值*/ /* InfoType *info; 与边相关的信息*/} ArcCell, AdjMatrix[MAX_VERTEX_NUM][MAX_VERTEX_NUM];typedef struct{ VertexType vexs[MAX_VERTEX_NUM]; /*顶点向量*/AdjMatrix arcs; /*邻接矩阵*/int vexnum,arcnum; /*图中当前顶点数和边数*/} MGraph;/*建立无向图的邻接矩阵*/void CreateGraph(MGraph *G){ int i,j,k; VertexType v1,v2;printf("\nInput MG vexnum,arcnum:");scanf("%d,%d",&(*G).vexnum,&(*G).arcnum);printf("Input %d vexs:",(*G).vexnum);for(i=0;i<(*G).vexnum;i++) /*输入顶点向量*/ { scanf("%s",(*G).vexs[i]); }printf("vexs list\n");for(i=0;i<G->vexnum;i++) /*输出顶点向量*/puts(G->vexs[i]);for(i=0;i<(*G).vexnum;i++) /*邻接矩阵初始化*/ for(j=0;j<(*G).vexnum;j++)(*G).arcs[i][j].adj=0;printf("\nInput %d arcs(vi vj):\n",(*G).arcnum); for(k=0;k<(*G).arcnum;k++) /*输入无权图的边*/ { scanf("%s%s",v1,v2);i=LocateVex(*G,v1); j=LocateVex(*G,v2);(*G).arcs[i][j].adj=1;(*G).arcs[j][i]=(*G).arcs[i][j];}}/* 顶点在顶点向量中的定位*/int LocateVex(MGraph G,VertexType v){ int i;for(i=0;i<G.vexnum;i++)if (strcmp(v,G.vexs[i])==0) break;return i;}/* 查找第1个邻接点 */int FirstAdjVex(MGraph G,int v){ int j,p=-1;for(j=0;j<G.vexnum;j++)if (G.arcs[v][j].adj==1) {p=j; break;}return p;}/* 查找下一个邻接点 */int NextAdjVex(MGraph G,int v,int w){ int j,p=-1;for(j=w+1;j<G.vexnum;j++)if (G.arcs[v][j].adj==1) {p=j; break;}return p;}/*按邻接矩阵方式输出无向图*/void PrintGraph(MGraph G){ int i,j;printf("\nMGraph:\n");for(i=0; i<G.vexnum; i++){ printf("%10s",G.vexs[i]);for(j=0; j<G.vexnum; j++)printf("%4d",G.arcs[i][j].adj);printf("\n");}}/*深度遍历*/Boolean visited[MAX_VERTEX_NUM]; /* 设置全局的访问标志数组 */void Dfs(MGraph G, int v){ int w;visited[v]=TRUE;printf("%s",G.vexs[v]);for(w=FirstAdjVex(G,v); w>=0; w=NextAdjVex(G,v,w))if(!visited[w]) Dfs(G,w);}void DfsTraverse(MGraph G){ int v;for (v=0; v<G.vexnum; v++)visited[v]=FALSE;for(v=0; v<G.vexnum; v++)if (!visited[v]) Dfs(G,v);}/* 广度遍历 */void BfsTraverse(MGraph G){ int v,u,w; LinkQueue Q;for(v=0; v<G.vexnum; v++) visited[v]=FALSE;InitQueue(&Q);for(v=0; v<G.vexnum; v++)if (!visited[v]){ visited[v]=TRUE;printf("%s",G.vexs[v]);EnQueue(&Q,v);while(!QueueEmpty(Q)){ DeQueue(&Q,&u);for(w=FirstAdjVex(G,u); w>=0; w=NextAdjVex(G,u,w))if (!visited[w]){ visited[w]=TRUE;printf("%s",G.vexs[w]);EnQueue(&Q,w);}}}}/*主函数*/main(){ int w;MGraph G;CreateGraph(&G);PrintGraph(G);printf("\nDfs:"); DfsTraverse(G); /* 深度遍历 */ printf("\nBfs:"); BfsTraverse(G); /* 广度遍历 */ }。