图的广搜、深搜及拓扑排序

#include<stdio.h>
#include<string.h>
#include<malloc.h>
#include<stdlib.h>

#define MAX_NUM 100		// 图的点的个数 
#define ERROR -1

typedef struct ArcNode{
	int adjvex;				// 顶点所在的位置 
	struct ArcNode *nextarc;	// 下一条边的指针 
}ArcNode;

typedef struct VNode{
	char data;			// 顶点信息 
	ArcNode * firsearc;	// 指向第一条依附该顶点的边的指针 
}VNode , AdjList[MAX_NUM];

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

/*********************创建邻接表**********************************************/
void CreatALGraph(ALGraph &G){	// 创建无向图的邻接表 
	int i,j,k;
	ArcNode *s,*p;
	printf("请输入该无向图的顶点数及边数:");
	scanf("%d %d",&G.vexnum,&G.arcnum);
	printf("请输入顶点信息(为字符型):\n"); 
	for( i = 0 ; i < G.vexnum ; ++i ){
		printf("请输入第%d个顶点的信息:",i+1);
		scanf("%*c%c",&G.vertices[i].data);
		G.vertices[i].firsearc = NULL;
	}
	printf("请输入边的信息(格式为:i,j):\n");
	for( k = 0 ; k < G.arcnum ; ++k ){
		printf("请输入第%d条边的信息:",k+1);
		scanf("%d %d",&i,&j);
		p = (ArcNode *)malloc(sizeof(ArcNode));
		if(!p) exit(ERROR);
		s = (ArcNode *)malloc(sizeof(ArcNode));
		if(!s) exit(ERROR);
		s->adjvex = j;
		if(G.vertices[i].firsearc == NULL || G.vertices[i].firsearc->adjvex < j){	 
			s->nextarc = G.vertices[i].firsearc;
			G.vertices[i].firsearc = s;
		}
		else{
			for( p = G.vertices[i].firsearc;(p->nextarc) && p->nextarc->adjvex > j;p = p->nextarc )
				 ;
			s->nextarc = p->nextarc;
			p->nextarc = s;
		}
		s = (ArcNode *)malloc(sizeof(ArcNode));
		if(!s) exit(ERROR);
		s->adjvex = i;
		if(G.vertices[j].firsearc == NULL || G.vertices[j].firsearc->adjvex < i){
			s->nextarc = G.vertices[j].firsearc;
			G.vertices[j].firsearc = s;
		}
		else{
			for( p = G.vertices[j].firsearc;(p->nextarc) && p->nextarc->adjvex > i;p = p->nextarc )
				 ;
			s->nextarc = p->nextarc;
			p->nextarc = s;
		}
	}
}

void creatALGraph(ALGraph &G){	// 创建有向图的邻接表 
	int i,j,k;
	ArcNode *s,*p;
	printf("请输入该有向图的顶点数及边数:");
	scanf("%d %d",&G.vexnum,&G.arcnum);
	printf("请输入顶点信息(为字符型):\n"); 
	for( i = 0 ; i < G.vexnum ; ++i ){
		printf("请输入第%d个顶点的信息:",i+1);
		scanf("%*c%c",&G.vertices[i].data);
		G.vertices[i].firsearc = NULL;
	}
	printf("请输入边的指向信息(格式为:i  j):\n");
	for( k = 0 ; k < G.arcnum ; ++k ){
		printf("请输入第%d条边的信息:",k+1);
		scanf("%d %d",&i,&j);
		p = (ArcNode *)malloc(sizeof(ArcNode));
		if(!p) exit(ERROR);
		s = (ArcNode *)malloc(sizeof(ArcNode));
		if(!s) exit(ERROR);
		s->adjvex = j;
		if(G.vertices[i].firsearc == NULL || G.vertices[i].firsearc->adjvex < j){
			s->nextarc = G.vertices[i].firsearc;
			G.vertices[i].firsearc = s;
		}
		else{
			for( p = G.vertices[i].firsearc;(p->nextarc) && p->nextarc->adjvex > j;p = p->nextarc )
				 ;
			s->nextarc = p->nextarc;
			p->nextarc = s;
		}
	}
}

void PrintfALGraph( ALGraph G ){	// 输出邻接表 
	int v;
	ArcNode *p = (ArcNode *)malloc(sizeof(ArcNode));
	for( v = 0 ; v < G.vexnum ; ++v ){
		printf("%d %c",v,G.vertices[v].data);	// 输出顶点信息 
		for( p = G.vertices[v].firsearc ; p != NULL ; p = p->nextarc )
			printf("->%d",p->adjvex);	// 输出与该顶点相关联的点的序号 
		printf("\n");
	}
}

/*********************深度优先搜索********************************************/
bool visited[MAX_NUM],flag; // visited 记录顶点是否被访问过,flag 控制输出 

void DFS( ALGraph G , int v , bool flag ){	// 搜索与顶点相关联的点 
	visited[v] = true;
	if( flag ){	// flag为true时 
		printf("->%c",G.vertices[v].data);
	}
	else{
		flag = true;	// flag默认初始为false,输出访问到的第一个顶点后 变为true 
		printf("  %c",G.vertices[v].data);
	}
	ArcNode *s = (ArcNode *)malloc(sizeof(ArcNode));
	if(!s) exit(ERROR);
	if( G.vertices[v].firsearc != NULL )
		for( s = G.vertices[v].firsearc ; s != NULL ; s = s->nextarc )
			if(!visited[s->adjvex])	// 若未被访问,则DFS递归,访问该顶点 
				DFS(G,s->adjvex,flag);
}

void DFSTraverse( ALGraph G ){	// 搜索图的每一个顶点 
	int v,ch;
	for( v = 0 ; v < G.vexnum ; ++v)
		visited[v] = false;		// 初始化visited为false 
	printf("请输入需要搜索的点的序号:");
	scanf("%d",&ch);
	flag = false; 
	DFS(G,ch,flag);
	printf("\n");
	for( v = 0 ; v < G.vexnum ; ++v)
		if( !visited[v] ){
			flag = false;	// flag初始为false 
			DFS(G,v,flag);
			printf("\n");
		}
}

/*********************广度优先搜索********************************************/
bool visit[MAX_NUM];	// visit 记录顶点是否被访问过 

typedef struct QNode{	// 链式队列结点 
	int base;
	struct QNode *next;
}QNode;

typedef struct Queue{	// 链式队列 
	QNode *front;
	QNode *rear;
}Queue;

Queue *CreatQueue(){	// 创建队列 
	Queue *Q = (Queue *)malloc(sizeof(Queue));
	if(!Q) exit(ERROR);
	Q->front = Q->rear = NULL;
	return Q;
}

int QueueEmpty( Queue Q ){	// 判断队列是否为空 
	if( Q.front == NULL )
		return 1;
	else return 0;
}

void EnQueue( Queue &Q , int &v ){	// 入队 
	QNode *p = (QNode *)malloc(sizeof(QNode));
	if(!p) exit(ERROR);
	p->base = v;	
	p->next = NULL;
	if( QueueEmpty(Q) )
		Q.front = Q.rear = p;
	else{
		Q.rear->next = p ;
		Q.rear = p;
	}
}

void DeQueue( Queue &Q , int &u ){	// 出队 
	u = Q.front->base;
	Q.front = Q.front->next;
}

void BFS( ALGraph G , int v , Queue &Q ){	// 搜索与该顶点相关联的点 
	int u;
	ArcNode *s;
	visit[v] = true;
	printf("  %c",G.vertices[v].data);
	EnQueue(Q,v);	// 该次访问的第一个顶点入队 
	while( !QueueEmpty(Q) ){	// 队空跳出 
		DeQueue(Q,u);
		for( s = G.vertices[u].firsearc ; s != NULL ; s = s->nextarc )	// 依次访问与v顶点相关联的点 
			if( !visit[s->adjvex] ){	// 若未被访问,则入队并记录
				visit[s->adjvex] = true;
				EnQueue(Q,s->adjvex);
				printf("->%c",G.vertices[s->adjvex].data);
			}
	}
}

void BFSTraverse( ALGraph G ){	// 搜索每一个顶点 
	int v,ch;
	Queue Q = *CreatQueue();
	for( v = 0 ; v < G.vexnum ; ++v )
		visit[v] = false;	// 初始化visit数组为false 
	printf("请输入需要搜索的点的序号:");
	scanf("%d",&ch);
	BFS(G,ch,Q);
	printf("\n");
	for( v = 0 ; v < G.vexnum ; ++v )
		if( !visit[v] ){	// 对未访问到的顶点 继续访问 
			BFS(G,v,Q);
			printf("\n");
		}
}

/*********************拓扑排序************************************************/
int InDegree[MAX_NUM],Num[MAX_NUM];	// InDegree 记录每一个顶点的入度  Num存储拓扑排序出栈的顶点 

typedef struct SNode{	// 链栈结点 
	int bata;
	struct SNode *next;
}SNode;

typedef struct Stack{	// 链栈 
	SNode *top;
}Stack;

Stack *CreatStack(){	// 创建链栈 
	Stack *S = (Stack *)malloc(sizeof(Stack));
	if(!S) exit(ERROR);
	S->top = NULL;
	return S;
}

int StackEmpty( Stack S ){	// 判断链栈是否为空 
	if( S.top == NULL )
		return 1;
	else return 0;
}

int GetTop( Stack S ){	// 获取栈顶元素 
	if( !StackEmpty(S) )
		return S.top->bata;
}

void Push( Stack &S , int e ){	// 压栈 
	SNode *p = (SNode *)malloc(sizeof(SNode));
	if(!p) exit(ERROR);
	p->bata = e;
	p->next = S.top;
	S.top = p;
}

void Pop( Stack &S , int &e ){	// 出栈 
	SNode *p;
	p = S.top;
	e = p->bata;
	S.top = p->next;
	free(p);
}

void TopologicalSort( ALGraph G ){	// 拓扑排序 
	int v,u;
	ArcNode *s;
	memset(InDegree,0,sizeof(InDegree));
	for( v = 0 ; v < G.vexnum ; ++v ){	// 计算每个顶点的入度 
		for( s = G.vertices[v].firsearc ; s != NULL ; s = s->nextarc )
			InDegree[s->adjvex]++;
	}
	Stack S = *CreatStack();
	for( v = 0 ; v < G.vexnum ; ++v )	// 入度为0的顶点进栈 
		if( !InDegree[v] )
			Push(S,v);
	int count = 0;		// 对输出顶点计数 
	while( !StackEmpty(S) ){
		Pop(S,u);
		Num[count++] = u;	// 将u顶点存入Num 并计数 
		for( s = G.vertices[u].firsearc ; s != NULL ; s= s->nextarc ){
			u = s->adjvex;
			if( !(--InDegree[u]) )	// 对u号顶点的每一个邻接点的入度减 1 
				Push(S,u);			// 若入度减为0,则入栈 
		}
	}
	if( count < G.vexnum )	// 该有向图有回路 
		printf("该有向图存在回路!\n拓扑到的结果为:\n");
	else
		printf("拓扑排序后的结果:\n");
	for( v = 0 ; v < count ; ++v )	// 输出拓扑排序到的顶点 
		printf(" %c ",G.vertices[Num[v]].data);
	printf("\n\n");
}

/*********************主操作**************************************************/

void Choose1(){	// 无向图操作 
	ALGraph G;
	CreatALGraph(G);
	printf("***********************************\n");
	printf("此无向图的邻接表为:\n"); 
	PrintfALGraph(G);
	printf("\n深度优先搜索的结果:\n");
	DFSTraverse(G);
	printf("\n广度优先搜索的结果:\n");
	BFSTraverse(G);
}

void Choose2(){	// 有向图操作 
	ALGraph G;
	creatALGraph(G);
	printf("***********************************\n");
	printf("此有向图的邻接表为:\n"); 
	PrintfALGraph(G);
	printf("\n深度优先搜索的结果:\n");
	DFSTraverse(G);
	printf("\n广度优先搜索的结果:\n");
	BFSTraverse(G);
	TopologicalSort(G);
}

int GetChoose( int min , int max ){	// 获取操作选择 
	int choose;
	while(1){
		scanf("%d",&choose);
		if( choose >= min && choose <= max )
			return choose;
		else printf("输入错误!请重新输入!\n");
	}
}

int main(){
	while(1){
		printf("***********************************\n");
		printf("请选择:\n");
		printf("1、创建无向图并对其进行搜索\n");
		printf("2、创建有向图并对其进行搜索及拓扑排序\n");
		printf("3、结束\n");
		int choose = GetChoose(1,3);
		system("cls");		// 清屏 
		if( choose == 1 )
			Choose1();
		if( choose == 2 ) 
			Choose2();
		if( choose == 3 )
			break;
	} 
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值