图的深度优先和广度优先遍历

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>

#define MAX_NODE_NUM 10
typedef  int ElemType;
typedef enum {DG,UDG} GKind;

typedef void (*VISIT)(ElemType);   //定义一个函数指针的类型VISIT, 指向一个"返回类型为void, 参数类型为ElemType"的函数

//队列结构
typedef struct Node
{
	ElemType data;
	struct Node* next;
}Node;

typedef struct Queue
{
	Node* front, *tail;
}Queue;


//图结构
typedef struct OtherNode
{	
	int index;
	struct OtherNode* next;
}OtherNode;


typedef struct HeadNode
{
	ElemType data;
	OtherNode* otnode;
}HeadNode;


typedef struct AdjListGraph
{
	HeadNode headvec[MAX_NODE_NUM];
	int vexnum, arcnum;
	GKind kind;
}AdjListGraph;


void InitQueue(Queue* Q)
//初始化队列
{
	Node* head = (Node*)malloc(sizeof(Node));
	head->data=0;
	head->next = NULL;
	Q->front = head;
	Q->tail = head;

}


int IsEmpty(Queue* Q)
//判断队列是否为空
{
	if(Q->tail == Q->front)
		return 1;
	else 
		return 0;
}


void Enqueue(Queue* Q, ElemType v)
{
	Node* node = (Node*)malloc(sizeof(Node));
	node->data = v;
	node->next = NULL;
	Node* p = (Node*)malloc(sizeof(Node));
	p = Q->front;
	while(p->next!=NULL)
		p = p->next;
	//此时p指向队列的最后一个结点
	p->next = node;
	//修改队尾指针
	Q->tail = node;
}

ElemType Dequeue(Queue* Q)
{
	if(!IsEmpty(Q))
	{
		Node* node = (Node*)malloc(sizeof(Node));
		node = Q->front->next;

		Q->front->next = node->next;

		if(node->next ==NULL) //说明出队的这个元素是最后一个元素
			Q->tail = Q->front;  //令队尾指针指向队头
		return node->data;
	}
	else
	{
		printf("queue is empty");
		return -1000;
	}
}




int Locate(AdjListGraph* G, ElemType v)
{
	for(int i = 0; i<=G->vexnum-1; i++)
	{
		if(G->headvec[i].data == v)
			return i;
	}
	return -1000;
}


ElemType FirstAdjVex(AdjListGraph* G, ElemType v)
//返回顶点v在G中的第一个邻接顶点
{
	int i = Locate(G, v);
	if(G->headvec[i].otnode!=NULL)
	{
		int pos = G->headvec[i].otnode->index;  //第一个邻接顶点的索引
		return G->headvec[pos].data;
	}
	else
		return -1000;//不存在邻接顶点
}

ElemType NextAdjVex(AdjListGraph* G, ElemType v, ElemType w)
//,w是顶点v的一个邻接顶点, 返回顶点v的下一个(相对于w的)邻接顶点
{
	int i = Locate(G, v);
	OtherNode* p = G->headvec[i].otnode; //p指向顶点v的第一个邻接顶点
	ElemType AdjVexData = G->headvec[p->index].data;
	while(AdjVexData != w)
	{
		p = p->next;
		AdjVexData = G->headvec[p->index].data;
	}
	//此时指针p指向w顶点
	p = p->next;
	if(p)   //如果w顶点后面还有顶点
		return G->headvec[p->index].data;
	else   //如果w顶点就是最后一个顶点
		return -1000;
}




void AddNode(AdjListGraph* G, int i, OtherNode* p_new)
//给索引为i的顶点的链表中增加一个结点p_new
{
	if(G->headvec[i].otnode)
		//当前顶点已经有至少一个邻接结点了, 需要把新结点加在这个结点后面
	{
		OtherNode* tmp = G->headvec[i].otnode;
		while(tmp->next)
			tmp = tmp->next;
		//此时,tmp指向当前顶点的链表中最后一个结点
		tmp->next = p_new;
	}
	else
	{
		G->headvec[i].otnode = p_new;
	}
}



void CreateAdjListGraph(AdjListGraph* G)
{
	//初始化顶点向量headvec
	for(int i = 0; i<=G->vexnum-1; i++)
	{
		printf("第%d个顶点的值为:",i);
		scanf("%d", &G->headvec[i].data);
		G->headvec[i].otnode = NULL;
	}

	//输入边的信息,对每个顶点创建链表
	for(int arc = 0; arc<=G->arcnum-1; arc++)
	{
		ElemType v1, v2, w;
		printf("第%d条边的第一个顶点,第二个顶点,权值 分别为:",arc);
		scanf("%d%d%d",&v1, &v2, &w);
		//得到两个顶点各自在顶点向量中的索引
		int i = Locate(G, v1);
		int j = Locate(G, v2);
		OtherNode* p_ij = (OtherNode*)malloc(sizeof(OtherNode));
		//若是有向图, 则第i个顶点的链表要新加一个指向j的node
		p_ij->index = j;
		p_ij->next = NULL;

		AddNode(G, i, p_ij);

		//若是无向图, 则还需要在顶点j的链表上增加一个指向i的结点
		if(G->kind == UDG)
		{
			OtherNode* p_ji = (OtherNode*)malloc(sizeof(OtherNode));
			p_ji->index = i;
			p_ji->next = NULL;
			AddNode(G, j, p_ji);
		}
	}
	printf("has created AdjListGraph.\n");
}


void visit(ElemType s)
{
	printf("visited %d, \n",s);
}


void BroadFirstSearch(AdjListGraph* G, VISIT visit_fn)
{
	//广度优先搜索
	int visited[G->vexnum];
	//初始化visited数组
	for(int i = 0; i<=G->vexnum-1; i++)
	{
		visited[i] = 0;
	}

	
	for(int i = 0; i<=G->vexnum-1; i++)
	{
		if(!visited[i])
		{
			//队列用于存放当前顶点下的所有被访问过的节点, 每次访问一个节点,就将其放入队列
			Queue Q;
			InitQueue(&Q);
			
			//访问当前顶点
			visit_fn(G->headvec[i].data);
			visited[i] = 1;
			
			Enqueue(&Q, G->headvec[i].data);

			if(!IsEmpty(&Q))
				printf("queue is not empty.\n");
			

			while(!IsEmpty(&Q))
			{
				ElemType u = Dequeue(&Q);
				printf("%d 节点出队,",u);
				
				for(ElemType w=FirstAdjVex(G,u); w>=0; w = NextAdjVex(G, u, w))
				{
					int pos = Locate(G, w);
					if(!visited[pos])
					{
						visit_fn(w);
						visited[pos] =1;
						Enqueue(&Q, w);
						printf("%d 节点入队,",w);
					}				
				}

			}

		}
		else
			printf("all the nodes are visited.\n");
	}
	return;

}

void dfs(AdjListGraph* G, ElemType v, int visited[], VISIT visit_fn)
{
	visit_fn(v);
	int pos = Locate(G, v);
	visited[pos] = 1;
	for(ElemType w = FirstAdjVex(G, v); w>=0; w = NextAdjVex(G, v, w))
	{
		int pos = Locate(G, w);
		if(!visited[pos])   //说明这个邻接结点还没被访问过
			dfs(G, w, visited, visit_fn);
	}
}

void DepthFirstSearch(AdjListGraph* G, VISIT visit_fn)
{
	int visited[G->vexnum];
	for(int i = 0; i<=G->vexnum-1; i++)
	{
		visited[i] = 0;
	}

	for(int i = 0; i<=G->vexnum-1; i++)
	{
		if(!visited[i])  //说明当前结点未被访问过
		{
			ElemType v = G->headvec[i].data;
			dfs(G,v, visited, visit_fn);
		}
	}

}





int main()
{
	VISIT visit_fn;
	visit_fn = visit;
	AdjListGraph G;
	G.vexnum = 6;
	G.arcnum = 5;
	CreateAdjListGraph(&G);
	
	BroadFirstSearch(&G, visit_fn);

	DepthFirstSearch(&G, visit_fn);


	//队列结构测试
	/*
	Queue Q;
	InitQueue(&Q);
	printf("is empty is:%d, ",IsEmpty(&Q));
	Enqueue(&Q,1);
	printf("is empty is:%d, ",IsEmpty(&Q));
	Enqueue(&Q,2);
	printf("is empty is:%d, ",IsEmpty(&Q));
	ElemType b;
	b = Dequeue(&Q);
	printf("Dequeue is:%d, ",b);
	b = Dequeue(&Q);
	printf("Dequeue is:%d, ",b);	
	b = Dequeue(&Q);
	printf("Dequeue is:%d, ",b);*/
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值