邻接矩阵的深度优先、广度优先遍历

1.图的深度优先搜索DFS

DFS类似于树的先序遍历,是树的先序遍历的推广。在邻接矩阵中,DFS算法的空间复杂度为O(N),时间复杂度为O(N^2)。

DFS算法主要思路

1.从图中某个顶点v出发,访问v。

2.找出刚才访问过的顶点的第一个未被访问的邻接点,访问该顶点。以该顶点为起点,重复此步骤,直至刚访问过的顶点没有未被访问的邻接点为止。

3.返回前一个访问过的且未被访问的邻接点的顶点,找出该顶点的下一个未被访问的邻接点,访问该顶点。

4.重复步骤2,3,直至图中所有顶点都被访问过,搜索结束。

2.广度优先搜索BFS

BFS遍历类似于树的层次遍历。在邻接矩阵中,BFS算法的空间复杂度为O(N),时间复杂度为O(N^2)。

BFS算法主要思路

1。从图中某个顶点v出发,访问v。

2.依次访问v的各个未曾访问过的邻接点。

3.分别从这些邻接点出发依次访问它们的邻接点,并使“先被访问的顶点的邻接点”先于“后被访问的顶点的邻接点”被访问。重复步骤3,直至所有图中已被访问的顶点的邻接点都被访问。

3.代码实现

代码中DFS运用了递归的思想,BFS则使用队列实现类似层次遍历的效果。

#include<stdio.h>
#include<stdlib.h>
#define QUEUE_MAX 20

int* visitedPtr;

typedef struct Graph {
	int** connections;
	int numNode;
}*GraphPtr;

typedef struct Queue {
	int* nodes;
	int front, rear;
}Queue,*QueuePtr;

QueuePtr InitQueue()
{
	QueuePtr resultPtr = (QueuePtr)malloc(sizeof(Queue));
	resultPtr->nodes = (int*)malloc(QUEUE_MAX * sizeof(int));
	resultPtr->front = 0;
	resultPtr->rear = 1;
	return resultPtr;
}//off InitQueue

bool isEmptyQueue(QueuePtr paraQueue)
{
	if ((paraQueue->front + 1) % QUEUE_MAX == paraQueue->rear)
	{
		return true;
	}//off if

	return false;
}//off isEmptyQueue

void enqueue(QueuePtr paraQueue, int paraNode)
{
	if ((paraQueue->rear + 1) & QUEUE_MAX == paraQueue->front)
	{
		printf("Queue full\r\n");
		return;
	}//off if

	paraQueue->nodes[paraQueue->rear] = paraNode;
	paraQueue->rear = (paraQueue->rear + 1) % QUEUE_MAX;
}//off enqueue

int dequeue(QueuePtr paraQueue)
{
	if (isEmptyQueue(paraQueue))
	{
		printf("Error,queue empty\n");
		return NULL;
	}//off if

	paraQueue->front = (paraQueue->front + 1) % QUEUE_MAX;
	return paraQueue->nodes[paraQueue->front];
}//off dequeue

GraphPtr InitGraph(int paraSize, int** paraData)
{
	GraphPtr resultPtr = (GraphPtr)malloc(sizeof(Graph));
	resultPtr->numNode = paraSize;
	resultPtr->connections = (int**)malloc(paraSize * sizeof(int*));

	for (int i = 0; i < paraSize; i++)
	{
		resultPtr->connections[i] = (int*)malloc(paraSize * sizeof(int));

		for (int j = 0; j < paraSize; j++)
		{
			resultPtr->connections[i][j] = paraData[i][j];
		}//off for j
	}//off for i

	return resultPtr;
}//off InitQueue

void InitTranverse(GraphPtr paraGraphPtr)
{
	visitedPtr = (int*)malloc(paraGraphPtr->numNode * sizeof(int));

	for (int i = 0; i < paraGraphPtr->numNode; i++)
	{
		visitedPtr[i] = 0;
	}//off for
}//off InitTranverse

void depthFirstTranverse(GraphPtr paraGarphPtr, int paraNode)
{
	visitedPtr[paraNode] = 1;
	printf("%d\t", paraNode);

	for (int i = 0; i < paraGarphPtr->numNode; i++)
	{
		if (!visitedPtr[i])
		{
			if (paraGarphPtr->connections[paraNode][i])
			{
				depthFirstTranverse(paraGarphPtr, i);
			}//off if
		}//off if
	}//off for
}//off depthFirstTranverse

void widthFirstTranverse(GraphPtr paraGraphPtr, int paraStart)
{
	QueuePtr tempQueuePtr = InitQueue();
	printf("%d\t", paraStart);
	visitedPtr[paraStart] = 1;
	enqueue(tempQueuePtr, paraStart);

	while (!isEmptyQueue(tempQueuePtr))
	{
		int tempNode = dequeue(tempQueuePtr);
		visitedPtr[tempNode] = 1;
		for (int i = 0; i < paraGraphPtr->numNode; i++)
		{
			if (visitedPtr[i])
			{
				continue;
			}//off if

			if (paraGraphPtr->connections[tempNode][i] == 0)
			{
				continue;
			}//off if

			printf("%d\t", i);
			visitedPtr[i] = 1;
			enqueue(tempQueuePtr, i);
		}//off for
	}//off while
}//off widthTranverse

int main()
{
	int myGraph[5][5] = { {0,1,0,1,0},{1,0,1,0,1},{0,1,0,1,1},{1,0,1,0,0},{0,1,1,0,0} };
	int** tempPtr;
	tempPtr = (int**)malloc(5 * sizeof(int*));

	for (int i = 0; i < 5; i++)
	{
		tempPtr[i] = (int*)malloc(5 * sizeof(int));

		for (int j = 0; j < 5; j++)
		{
			tempPtr[i][j] = myGraph[i][j];
		}//off for j
	}//off for i

	GraphPtr tempGraphPtr = InitGraph(5, tempPtr);

	printf("Detph first visit: ");
	InitTranverse(tempGraphPtr);
	depthFirstTranverse(tempGraphPtr, 4);

	printf("\nWidth first visit: ");
	InitTranverse(tempGraphPtr);
	widthFirstTranverse(tempGraphPtr, 4);
	
	return 0;
}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
邻接矩阵是一种图的存储结构,它可以用来表示有限个顶点之间的关系。邻接矩阵深度优先遍历广度优先遍历是图的两种基本遍历方式。 邻接矩阵深度优先遍历(Depth First Search,DFS): 深度优先遍历是一种用于遍历或搜索树或图的算法。在这个算法中,首先访问根节点,然后递归地访问每个子节点。当访问一个节点时,将其标记为已访问,以避免重复访问。深度优先遍历使用栈来实现,因此它是一种先进后出(Last In First Out,LIFO)的算法。 下面是邻接矩阵深度优先遍历的Python代码示例: ```python def DFS(graph, start): visited = set() # 用集合来存储已经访问过的节点 stack = [start] # 用列表来模拟栈 while stack: vertex = stack.pop() # 取出栈顶元素 if vertex not in visited: visited.add(vertex) # 标记为已访问 print(vertex, end=' ') # 将未访问的邻居节点入栈 stack.extend([i for i in range(len(graph[vertex])) if graph[vertex][i] and i not in visited]) # 示例 graph = [[0, 1, 1, 0], [1, 0, 0, 1], [1, 0, 0, 1], [0, 1, 1, 0]] DFS(graph, 0) # 输出:0 1 3 2 ``` 邻接矩阵广度优先遍历(Breadth First Search,BFS): 广度优先遍历是一种用于遍历或搜索树或图的算法。在这个算法中,首先访问根节点,然后逐层访问每个子节点。当访问一个节点时,将其标记为已访问,以避免重复访问。广度优先遍历使用队列来实现,因此它是一种先进先出(First In First Out,FIFO)的算法。 下面是邻接矩阵广度优先遍历的Python代码示例: ```python from collections import deque def BFS(graph, start): visited = set() # 用集合来存储已经访问过的节点 queue = deque([start]) # 用双端队列来模拟队列 while queue: vertex = queue.popleft() # 取出队首元素 if vertex not in visited: visited.add(vertex) # 标记为已访问 print(vertex, end=' ') # 将未访问的邻居节点入队 queue.extend([i for i in range(len(graph[vertex])) if graph[vertex][i] and i not in visited]) # 示例 graph = [[0, 1, 1, 0], [1, 0, 0, 1], [1, 0, 0, 1], [0, 1, 1, 0]] BFS(graph, 0) # 输出:0 1 2 3 ```

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值