首页 > 编程语言 >小白学算法-数据结构和算法教程: 队列的应用

小白学算法-数据结构和算法教程: 队列的应用

时间:2023-10-24 11:07:11浏览次数:28  
标签:graph self range queue 算法 小白学 顶点 colorArr 数据结构

小白学算法-数据结构和算法教程: 队列的应用_服务端

检查给定图是否是二分图

二分图是一种图,其顶点可以分为两个独立的集合 U 和 V,使得每条边 (u, v) 要么连接从 U 到 V 的顶点,要么连接从 V 到 U 的顶点。换句话说,对于每个边 (u, v),要么 u 属于 U,v 属于 V,要么 u 属于 V,v 属于 U。我们也可以说,不存在连接同一集合的顶点的边。

小白学算法-数据结构和算法教程: 队列的应用_服务端_02

如果图着色可以使用两种颜色使得集合中的顶点使用相同颜色着色,则二分图是可能的。

请注意,可以使用两种颜色对具有偶数循环的循环图进行着色。例如,请参见下图。 

小白学算法-数据结构和算法教程: 队列的应用_python_03


不可能使用两种颜色对具有奇数循环的循环图进行着色。 

小白学算法-数据结构和算法教程: 队列的应用_服务端_04

检查图是否为二分图的算法:


解法步骤:

一种方法是使用 回溯算法 m 着色问题来检查图是否为 2-colorable 。 

以下是一个使用广度优先搜索 (BFS) 来确定给定图是否为二分图的简单算法。 

  1. 将红色分配给源顶点(放入 U 组)。 
  2. 将所有邻居涂成蓝色(放入集合 V 中)。 
  3. 将所有邻居的邻居涂成红色(放入集合 U 中)。 
  4. 为所有顶点分配颜色,使其满足 m 路着色问题的所有约束,其中 m = 2。
  5. 在分配颜色时,如果我们找到与当前顶点颜色相同的邻居,则图不能用 2 个顶点着色(或者图不是二分图)

回溯算法

Python:

# Python 程序查找 给定图形是否为二方图
class Graph(): 

	def __init__(self, V): 
		self.V = V 
		self.graph = [[0 for column in range(V)] \ 
								for row in range(V)] 

# 如果图 G[V][V] 返回 true,则此函数返回 true。
# 是二方图,否则返回 false 
	def isBipartite(self, src): 
		colorArr = [-1] * self.V 

		# 将第一种颜色指定给源
		colorArr[src] = 1

		# 创建一个顶点编号的队列(先进先出),
		# 将源顶点入队以进行BFS遍历。
		queue = [] 
		queue.append(src) 

		# 在队列中有顶点时运行 (类似于 BFS)
		while queue: 

			u = queue.pop() 

			# 如果存在自循环,则返回 false
			if self.graph[u][u] == 1: 
				return False; 

			for v in range(self.V): 

				# An edge from u to v exists and destination 
				# v is not colored 
				if self.graph[u][v] == 1 and colorArr[v] == -1: 

					# Assign alternate color to this 
					# adjacent v of u 
					colorArr[v] = 1 - colorArr[u] 
					queue.append(v) 

				# An edge from u to v exists and destination 
				# v is colored with same color as u 
				elif self.graph[u][v] == 1 and colorArr[v] == colorArr[u]: 
					return False

		# If we reach here, then all adjacent 
		# vertices can be colored with alternate 
		# color 
		return True

# Driver program to test above function 
g = Graph(4) 
g.graph = [[0, 1, 0, 1], 
			[1, 0, 1, 0], 
			[0, 1, 0, 1], 
			[1, 0, 1, 0] 
			] 
			
print ("Yes" if g.isBipartite(0) else "No")

输出

是的

复杂度分析

时间复杂度:O(V*V) 作为邻接矩阵用于图,但可以通过使用邻接列表将其变为 O(V+E)
辅助空间:由于队列和颜色向量,O(V)。

上述算法仅在 图是连通的情况下才有效。在上面的代码中,我们总是从源 0 开始,并假设从源 0 访问顶点。一个重要的观察是,没有边的图也是二分图。请注意,二分条件表示所有边都应从一组到另一组。

我们可以扩展上面的代码来处理图未连接的情况。对于所有尚未访问的顶点,重复调用上述方法。 

Python:

# Python3 程序来找出 给定图形是否为二方图
class Graph(): 

	def __init__(self, V): 
		self.V = V 
		self.graph = [[0 for column in range(V)] 
					for row in range(V)] 

		self.colorArr = [-1 for i in range(self.V)] 

# 如果图 G[V][V] 返回 true,则此函数返回 true。 是二方图,否则返回 false
	def isBipartiteUtil(self, src): 
		# 创建顶点编号队列(先进先出)并
		# 为 BFS 遍历登记源顶点
		queue = [] 
		queue.append(src) 

		# 在队列中有顶点时运行	(类似于 BFS)
		while queue: 

			u = queue.pop() 

			# 如果存在自循环,则返回 false
			if self.graph[u][u] == 1: 
				return False

			for v in range(self.V): 

			# 存在一条从 u 到 v 的边,并且目的地 v 没有着色
				if (self.graph[u][v] == 1 and
						self.colorArr[v] == -1): 

					# 为 u 的相邻 v
					self.colorArr[v] = 1 - self.colorArr[u] 
					queue.append(v) 

				# 存在一条从 u 到 v 的边,且目的地 v 的颜色与 u 相同
				elif (self.graph[u][v] == 1 and
					self.colorArr[v] == self.colorArr[u]): 
					return False
		return True

	def isBipartite(self): 
		self.colorArr = [-1 for i in range(self.V)] 
		for i in range(self.V): 
			if self.colorArr[i] == -1: 
				if not self.isBipartiteUtil(i): 
					return False
		return True


g = Graph(4) 
g.graph = [[0, 1, 0, 1], 
		[1, 0, 1, 0], 
		[0, 1, 0, 1], 
		[1, 0, 1, 0]] 

print ("Yes" if g.isBipartite() else "No")

输出

是的

复杂度分析

时间复杂度O(V+E)
辅助空间:O(V),因为我们有一个 V 大小的数组。

如果使用邻接表来表示图,时间复杂度将为 O(V+E)。

适用于连接图和断开图。


标签:graph,self,range,queue,算法,小白学,顶点,colorArr,数据结构
From: https://blog.51cto.com/demo007x/8001556

相关文章

  • 小白学算法: 哈希 - 数据结构和算法教程
    散列是指使用称为散列函数的数学公式从可变大小的输入生成固定大小的输出的过程。该技术确定数据结构中项目存储的索引或位置。需要Hash数据结构互联网上的数据每天都在成倍增加,有效存储这些数据始终是一个难题。在日常编程中,这些数据量可能不是那么大,但仍然需要轻松高效地存储、访......
  • 小白学数据结构和算法: 哈希数据结构实现原理
    使用哈希函数计算哈希值的复杂度时间复杂度:O(n)空间复杂度:O(1)哈希问题如果我们考虑上面的例子,我们使用的哈希函数是字母的总和,但是如果我们仔细检查哈希函数,那么问题可以很容易地可视化,对于不同的字符串,哈希函数开始生成相同的哈希值。 例如:{“ab”,“ba”}具有相同的哈希值,字符串......
  • 小白学算法-数据结构和算法教程: 使用开放寻址线性探测实现自己的哈希表
    Java中使用链接实现哈希表所有数据结构都有其自身的特点,例如,当需要快速搜索元素(在log(n)中)时,会使用BST。当需要在恒定时间内获取最小或最大元素时,使用堆或优先级队列。类似地,哈希表用于在恒定时间内获取、添加和删除元素。在继续实施方面之前,任何人都必须清楚哈希表的工作原理。因此......
  • 【基础算法】- 贪心
    贪心定义贪心算法适用于最优子结构问题。意思是问题在分解成子问题来解决时,子问题的最优解能递推到最终问题的最优解。常见的符合这种性质的问题如:「我们将XXX按照某某顺序排序,然后按某种顺序(例如从小到大)选择。」「我们每次都取XXX中最大/小的东西,并更新XXX。」但比......
  • 子序列相关算法
    1、最长公共子序列最长公共子序列(LongestCommonSubsequence,LCS)是动态规划中的经典问题,顾名思义,即求两个序列最长的公共子序列(可以不连续)。 1#include<iostream>2#include<string>3usingnamespacestd;//使用动态规划算法;分为两种情况4chara[102],b[102];......
  • md5算法实现
    前言md5算法是我们经常会用到的一个hash函数,虽然已经被证明是不安全的了,但其应用依然十分广泛.哈希函数具有如下特点:将任意长度的字符串映射为固定长度源数据微小的改动会导致结果差异巨大不可逆暴力破解困难你有没有好奇过,哈希函数是如何做到这些的呢?本文就拿m......
  • 数据结构之数组(Java)
    一:概述什么是数组呢?数组对应的英文名为array,是有限个相同类型所组成的集合,数组中的每一个变量被称为元素。数组是最为简单、最为常用的数据结构。举例说明:元素31254972索引01234567正如军队里的士兵存在编号一样,数组中的每一个元素也有着自己的小标,这......
  • Codeforces Round 905 (Div. 2) C. You Are So Beautiful(数据结构)
    CodeforcesRound905(Div.2)C.YouAreSoBeautiful定义:设数组abcd子数组定义:从原数组砍去前面若干元素,后边若干元素,剩余的数组。如:bc、ab子序列定义:从原数组删除若干元素,剩余元素拼凑一起,组成的数组。如:ac、bd思路:作为结果的连续子数组,如果他为[\(a_l\),……,\(a_......
  • 【数据结构】Splay 树
    SplaySplay树(伸展树),是平衡树的一种,而且可以维护序列,进行一些序列操作。有些序列操作功能甚至是线段树实现不了的(经典的区间翻转)。维护集合时,Splay的中序遍历单调递增,而维护序列时,Splay的中序遍历是维护的序列。Splay通过均摊(势能分析)来保证复杂度正确,单次插入,删除,查找操作......
  • diff算法
    什么是Diff算法?Diff算法是Vue.js的一个核心特性,它是一种用于比较虚拟DOM树的差异,并最小化DOM操作的数量。当Vue.js检测到数据更改时,它会生成一个新的虚拟DOM树,并将其与旧虚拟DOM树进行比较。Diff算法会查找差异,并仅对需要更改的部分进行DOM操作。这种算法可以帮助我们在前端开发中......