广度优先遍历、深度优先遍历、拓扑序列算法实现

广度优先遍历、深度优先遍历、拓扑序列算法实现

一、广度优先遍历

邻接矩阵存储结构

typedef  char VerTexType;
typedef  int ArcType;
/* 邻接矩阵表示法 */
typedef struct Graph { 
    char vertex[vexnum];               //顶点表 
    EleType arcs[MAX_VERTEX_NUM][MAX_VERTEX_NUM];    /* 邻接矩阵 */
    int vexnum, arcnum;                              /* 图的顶点数和弧数 */
} AMraph ,Graph;

要点:

  1. 找到与一个顶点相邻的结点
  2. 标记数组(标记哪些顶点被访问)
  3. 需要一个辅助队列
  4. 图的基本操作
    (1)FIrstAdjVex(G,v):求图G中顶点的第一个相邻结点,若存在,返回顶点号,若v不存在邻接点或图中不存在x,则返回-1
    (2)NextAdjvex(G,v,w):除v外的,下一个邻接点W,若存在,返回顶点号,若v不存在邻接点或者图中不存在x,则返回-1
//寻找图G中顶点V的第一个邻接点,若存在,返回改结点的列数;不存在,返回-1 
int FirstAdjVex(Graph G,int v){	
	int i=0;
	fot(int i=0;i<G.vexnum;i++){
		if(G.arcs[v][i]==1){
			return i;
		}
	}
	return -1;
}
//寻找图G中开始结点v除了w之外的邻接结点
int NextAdjVex(Graph G,int v,int w){
	int i;
	for(i=w+1;i<G.arcs[v][w];i++){	//跳过w进行遍历,若存在,返回该结点的列数;不存在,返回-1 
		if(G.arcs[v][w]==1)
			return i;
	}
	return -1; 
} 

// 广度优先遍历---BFS
void BFS(Graph G,int v){//v是开始结点
 	InitQueue(Q);	//初始化一个队列
 	int w,u;
	for(int i=0;i<G.vexnum;i++)//初始化vextex数组(访问数组) 
		G.visited[i]=false;
	printf("%d	",v);//访问v
	visited[v]=ture;//已访问过置为true 
	EnQueue(Q,v);//将结点入队
	while(!QueueEmpty(Q)){
		DeQueue(Q,u);		//将对头元素出队并置为u
		for(w=FirstAdjVex(G,v);w>=0;w=NextAdjVex(G,u,w)){
			if(!Visited[w]){	//当前结点为访问的时候 
				printf("%d	",w);visited[w]=ture;//访问w,并标记 
				EnQueue(Q,w);	//w 入队 
			}	
		}  
	} 
 } 

二、深度优先遍历(递归)

算法思想:

  1. 从图中一个顶点V出发,访问V,并置visited[v]=true
  2. 依次检查V的所有临结点w,如果visited【w】==false,再从w出发遍历,知道图中的所有结点都已经访问过
bool visited[MVNum];		//访问标志数组,初值全为false
void DFS(ALGraph G,int v){
	//从第v个结点出发,深度优先遍历图G
	printf("%d ",v);visited[v]=ture;//访问并标记
	for(w=FirstAdjVex(G,v);w>=0;w=NextAdjVex(G,v,w)){
	//依次检查v的所有邻接点w,FirstAdjVex(G,v)表示V的第一个邻接点
	//NextAdjVex(G,v,w):表示v的邻接点除了w之外的邻接点
		if(!visited[w]) DFS(G,w);			//对为访问的结点w,直接递归调用DFS(G,w);
	}

}

三、拓扑排序:判断有向图是否存在回路

图的邻接表的存储结构

#define MVNum 100		//最大顶点数
typedef struct ArcNode{	//边结点
	int adjvex;			//该边所指向的结点的位置
	struct ArcNode *nextarc;	//指向下一条边的指针
	int info;					//和边有关的信息---权值 
}ArcNode; 
typedef struct VNode{	//顶点信息
	VerTexType data; 
	ArcNode *firstarc;			//指向第一条依附改顶点的边的指针 
}VNode,AdjList[MVNum];			//AdjList表示邻接表的类型 

typedef struct{
	AdjList vertices;
	int vexnum,arcnum;		//图的当前顶点数和边数 
}ALGraph;  

算法思想:

  1. 求出各顶点的入度存入到indegree[i],并将入度为0的点入栈
  2. 若栈不为空
    A:将栈顶的顶点Vi出栈并保存在拓扑序列数组topo中
    B:对顶点Vi的每个邻接点Vk的入度减一,如果Vk的入度为0,则将Vk入栈
  3. 如果输出的顶点数小于AOV网的顶点个数,则网中存在有向环,无法进行拓扑排序,不然,拓扑序列成功
//拓扑排序:判断有向图是否有没有回路      向图G采用邻接表的存储结构
bool ToPuSort(ALGraph G,int topo[]){
	//若G没有回路,生成G的拓扑序列并存入到topo[]
	FindInDegree(G,indegree);		//FIndIndegree()函数胡:求各个结点的入度并存放到indegree[]数组中。
	InitStack(S);		//初始化一个工作栈
	for(int i=0;i<G.vexnum;i++)
		if(!indegree[i]) push(S,i);		//入度为0的入栈
	count=0;		//记数--用与和顶点数比较
	while(!StackEmpty(S)){		//栈不为空
		pop(S,i);				//弹出栈顶元素,并存到拓扑序列数组topo中 
		topo[count]=i; 
		count++;
		for(p=G.vertices[i].firstarc;p;p=p->nextarc){
			k=p->adjvex;		//Vk为Vi的邻接点 
			--indegree[k];		//Vi的每个邻接点入度减一 
			if(indegree[k]==) push(S,k);
		}
	} 
	//计数器count和vexnum比较
	if(count<vexnum) return false;	//   该图有回路?
	else return ture;
}
  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值