【数据结构】树和图03——图的遍历

这篇博客介绍了图的深度优先搜索(DFS)和广度优先搜索(BFS)的实现。通过邻接矩阵和邻接表两种数据结构,分别展示了DFS和BFS的时间复杂度,并提供了C语言的代码示例。在DFS中,邻接矩阵的时间复杂度为n^2,而邻接表可以降低到n+e。在BFS中,使用邻接表进行优化。样例输入和输出展示了算法的实际应用。
摘要由CSDN通过智能技术生成

/图的深度优先搜索遍历——DFS/

采用邻接矩阵,时间复杂度为n*^2。如果采用邻接表存储,DFS的时间复杂度会变成n+e。

在BFS中我会采用邻接表的存储方法。

本程序的输入输出:

样例输入
6
0 0 0 1 0 0
0 0 1 1 0 0
0 1 0 1 0 0
1 1 1 0 0 0
0 0 0 0 0 1
0 0 0 0 1 0

样例输出
0 3 1 2 4 5

#include<stdio.h>
#define max 50
#define maxcost 10000
typedef int elemtype;
typedef struct
{
	int vertexnum;//顶点个数 
	elemtype graph[max][max];//邻接矩阵 
}graph;
void DFS(graph G,int i,int depth,bool vis[])
{
	int t;
	vis[i]=true;
	printf("%d ",i);
	for(t=0;t<G.vertexnum;t++)
		if(vis[t]==false&&G.graph[i][t]!=maxcost)
			DFS(G,t,depth+1,vis);
}
void DFStraverse(graph G,bool vis[])
{
	int i;
	for(i=0;i<G.vertexnum;i++)
	{
		if(vis[i]==false)
		DFS(G,i,1,vis);
	}
}
int main()
{
	graph G;
	scanf("%d",&G.vertexnum);
	int i,j;
	for(i=0;i<G.vertexnum;i++)
		for(j=0;j<G.vertexnum;j++)
		{
			scanf("%d",&G.graph[i][j]);
			if(G.graph[i][j]==0&&i!=j)
				G.graph[i][j]=maxcost;
		}
	bool vis[G.vertexnum]={false};
	DFStraverse(G,vis);
	return 0;
}

/树的广度优先搜索遍历——BFS/

样例输入:
5 8
1 0
0 2
2 4
4 3
3 1
1 2
0 3
3 4
样例输出:
0 2 3 4 1

#include<stdio.h>
#include<malloc.h>
#define maxnum 100
#define error 1
#define ok 0
typedef int elem;
typedef int status;
typedef int vextype;
typedef int edgetype;
typedef int weightype;
typedef struct arcnode 
{
	int adjvex;//该弧指向的顶点
	struct arcnode *nextarc;//指向下一条弧的指针 
	weightype weight;//权值 
}arcnode;//表结点
typedef struct vnode
{
	vextype data;//顶点信息 
	arcnode *firstarc;//指向下一条弧的指针 
}vnode,list[maxnum];//头结点
typedef struct 
{
	list vertices;
	int vernum,arcnum;
}graph;
typedef struct qnode
{
    elem data;//队列元素 
    struct qnode *next;//指向下一个元素的指针 
}qnode,*queueptr;//链式队列的结构 
typedef struct
{
    queueptr front;//队列的头 
    queueptr rear;//队列的尾 
}linkqueue;//还可以不放在结构体里,单独拿出来 
status linkqueue_init(linkqueue &q)
{
    q.front=q.rear=(queueptr)malloc(sizeof(qnode));
    q.rear->next=NULL;
    return ok;
}//初始化一个队列 
status linkqueue_push(linkqueue &q,elem e)
{
    q.rear->data=e;
    queueptr s;
	s=(queueptr)malloc(sizeof(qnode));
	q.rear->next=s;
	q.rear=s;
	q.rear->next=NULL;
	return ok;
}//进队一个元素 
status linkqueue_pop(linkqueue &q)
{
	queueptr t;
	t=q.front->next;
	q.front=t;
	return ok;
}//出队一个元素
elem linkqueue_getfront(linkqueue &q)
{
	return q.front->data;
}//取队头元素
status linkqueue_empty(linkqueue &q)
{
	if(q.front==q.rear)
	return ok;
	else 
	return error;
}//判断队列是否为空 
int LocateVer(graph &G,int u)  
{  
    int i;  
    for(i=0;i<G.vernum;i++)
        if(u==G.vertices[i].data)  
            return i; 
}  
void CreateG(graph &G)  
{  
    int i,j,k;
    
    scanf("%d%d", &G.vernum,&G.arcnum);
    for(i=0;i<G.vernum;i++)
    { 
        G.vertices[i].data=i;
        G.vertices[i].firstarc=NULL;
    }//初始化顶点 
    int v1,v2,w;
    for(k=0;k<G.arcnum;k++)  
    {
        scanf("%d%d",&v1,&v2);//输入顶点和权值 
        i=LocateVer(G,v1);  
        j=LocateVer(G,v2);
		arcnode *p1,*p2;
        p1=(arcnode*)malloc(sizeof(arcnode));  
        p1->adjvex=j;//赋值给p->adjvex指向的顶点域
        //p1->weight=w;//边表结点的权值
        p1->nextarc=G.vertices[i].firstarc;//它的nextarc指针域指向i结点的firstarc指针域  
        G.vertices[i].firstarc=p1;
        p2=(arcnode*)malloc(sizeof(arcnode)); 
        p2->adjvex=i;
		//p2->weight=w;
        p2->nextarc=G.vertices[j].firstarc;
		G.vertices[j].firstarc=p1;//将点i的第一条指针指向 
    }
} 
/*采用邻接表表示图的广度优先遍历*/
void BFS(graph &G)
{
	printf("0 ");
	int u,w,v;
	arcnode *p;
	linkqueue q;
	linkqueue_init(q);
	int visited[G.arcnum]={0};
	visited[0]=1;			//顶点v0已被访问
	linkqueue_push(q,0);		//将顶点v0入队
	while(linkqueue_empty(q)==error)
	{
		u=linkqueue_getfront(q);		
		linkqueue_pop(q);//将顶点元素u出队,开始访问u的所有邻接点
		v=LocateVer(G,u);//得到顶点u的对应下标
		for(p=G.vertices[v].firstarc;p;p=p->nextarc)		//遍历顶点u的邻接点
		{
			w=p->adjvex;	
			if(visited[w]==0)	//顶点p未被访问
			{
				printf("%d ",G.vertices[w].data);	//打印顶点p
				visited[w]=1;				//顶点p已被访问
				linkqueue_push(q,G.vertices[w].data);			//将顶点p入队
			}
		}
	}
}
int main()
{
	graph G;
	CreateG(G);
	BFS(G);
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值