【算法学习】图相关算法编程实现-深度优先遍历和广度优先遍历

2023-05-16

一、图的表示

图G=(V,E)。要表示一个图,通常有两种方法:邻接表和邻接矩阵。两种方法都既可以表示有向图,也可以表示无向图。

邻接表表示由一个包含|V|个列表的数组组成,其中每个列表对应V中的一个顶点。每个邻接表中的顶点一般以任意顺序存储。

实例:


图一 无向图的邻接矩阵表示


图二 无向图的邻接表表示


图三 有向图的邻接矩阵


图四 有向图的邻接表表示


图五 带权图的邻接矩阵表示

邻接表适合表示稀疏图。所需要的存储空间是O(V+E)。

邻接矩阵所需存储空间:O(V*V)。


二、图的广度优先搜索

算法思想:

广度优先搜索假设从图中某个顶点v出发,在访问了v之后依次访问v的各个未曾访问过的邻接点,然后再分别从这些邻接点出发依次访问它们的邻接点,并使先被访问的顶点的邻接点先于后被访问的顶点的邻接点被访问(因此需要用队列来存储顶点),直到图中所有已被访问的顶点的邻接点都被访问为止。如果此时图中还有未被访问的顶点,则另选图中未被访问的顶点作为起点,重复上述过程,直到图中所有顶点都被访问为止。


通常采用队列作为辅助结构。


图示:


图六 用于广度优先搜索的图-德国城市分布图


图七 广度优先搜索结果

注意:广度优先搜索计算出来的每个顶点到源顶点之间的距离就是最短路径距离。


时间复杂度:O(V+E)。


采用了队列辅助数据结构。每个顶点只入队列一次,也最多出队列一次。入队和出队的时间复杂度均为O(1)。因此队列操作所需的时间O(V)。当每个顶点出队时才需要扫描链表,每个顶点的邻接表只被扫描一次。所有邻接表长度为O(E),因此扫描邻接表时间复杂度为O(E)。初始化开销为O(V)。


简易代码:

 std::queue<node*> visited, unvisited; 
 node nodes[9];
 node* current;
 
 unvisited.push(&nodes[0]); //先把root放入unvisited queue
 
 while(!unvisited.empty()) //只有unvisited不空
 {
    current = (unvisited.front()); //目前應該檢驗的
 
    if(current -> left != NULL)
       unvisited.push(current -> left); //把左邊放入queue中
 
    if(current -> right != NULL) //右边压入。因为QUEUE是一个先进先出的结构,所以即使后面再压其他东西,依然会先访问这个。
       unvisited.push(current -> right);
 
    visited.push(current);
 
    cout << current -> self << endl;
 
    unvisited.pop();
 }



三、深度优先搜索


算法思想


对于最新发现的顶点,如果它还有以此起点而未探测到的边,就沿此边继续探测下去。当顶点v的所有边都已被探寻过后,搜索将回溯到发现顶点v有起始点的那些边。这个过程一直进行到已发现从源顶点可达的所有顶点时为止。如果还存在未被发现的顶点,则选择其中一个作为源顶点,并重复以上过程。

深度优先搜索的先辈子图形成一个由数棵深度优先树组成的深度优先森林。


伪代码:

DFS(G,s)
	for each vertex v in V(G)
		status[v] = WHITE
		/******其他初始化******/
	for each vertex v in V(G)
		if(status[v]==WHITE)
			DFS-VISIT(v)

DFS-VISIT(v)
	status[v] = GRAY
	for each vertex t in Adj(v)
		if status[t] = WHITE
			DFS-VISIT(t)
			/******其他操作******/
	status[v] = BLACK

时间复杂度:O(V+E)。采用聚集分析方法。

DFS中两个循环所花时间为O(V),其中不包括调用DFS-VISIT()的时间。对于每个顶点,DFS-VISIT()只被调用一次。在这个函数的一次执行过程中,其中的循环执行的次数是与当前顶点v相邻的顶点的个数。一次所有调用函数DFS-VISIT()所花时间是O(E)。

所以时间复杂度是O(V+E)。


四、编程实现

Graph.h

//图相关算法编程实现《算法导论(第二版)》P322 第22章 图的基本算法
//Date:2013-03-27
//Author:江南烟雨(E-Mail:xiajunhust@gmail.com)
#include <iostream>
#include <queue>

//图的基本算法类封装实现
//这里图用邻接表表示法(且是不带权的无向图)
template <class ElemType>
class GraphClass{
public:
	//图邻接表表示中节点数据结构
	typedef struct StructGraphNode{
		ElemType elem;
		struct StructGraphNode *next;
	}GraphNode,*GraphNodeLink;

	//图遍历时节点颜色标记
	enum NodeColor{
		WHITE,//未被发现
		GRAY,//已被发现但是未访问
		BLACK//已被访问
	};

	static const int MaxVal = 99999;

	GraphClass();//默认构造函数
	~GraphClass();//析构函数
	//依据图中包含的节点以及邻接矩阵创建邻接链表表示的图
	void createGraph(ElemType *a,int n,char *matrix);
	void BFSGraph();//图的广度优先搜索
	void DFSGraph();//图的深度优先搜索

	void __printAdjacencyList();//输出图的当前邻接表

private:
	GraphNodeLink *root;//邻接表,包含了对应于每个节点的列表
	int num_nodes;//图中节点个数

	int __getNodeIndex(GraphNodeLink node);//得到某个顶点在颜色等数组中的索引
	void __DFSSubGraph(GraphNodeLink u,int &time,int *d,int *f,enum NodeColor *color,GraphNodeLink *parent);//从某个子节点开始深度优先遍历
	//删除邻接表所占空间
	void __deleteAdjacencyList();
	void __deleteSingleLinkList(GraphNodeLink head);//删除一个单链表
};

template <class ElemType>
GraphClass<ElemType>::GraphClass()
{
	root = NULL;
}

//析构函数
template <class ElemType>
GraphClass<ElemType>::~GraphClass()
{
	__deleteAdjacencyList();
}

//函数:依据图的邻接矩阵表示创建图的临界表表示
//参数:
//matrix:图的邻接矩阵,行优先,以一维数组表示
template <class ElemType>
void GraphClass<ElemType>::createGraph(ElemType *a,int n,char *matrix)
{
	num_nodes = n;
	root = new GraphNodeLink[n];
	for (int i = 0;i < n;++i)
		root[i] = NULL;

	//创建邻接表中的每个列表,每个列表对应一个顶点
	for (int i = 0;i < n;++i)
	{
		root[i] = new GraphNode;
		root[i]->elem = *(a + i);
		root[i]->next = NULL;
		GraphNodeLink loopNode = root[i];
		for (int j = 0;j < n;++j)
		{
			if (*(matrix + i * n + j) == 1)
			{
				GraphNodeLink newNode = new GraphNode;
				newNode->elem = *(a + j);
				newNode->next = NULL;
				//寻找插入的正确位置
				while(loopNode->next != NULL)
					loopNode = loopNode->next;
				loopNode->next = newNode;
			}
		}
	}
}

//图的广度优先遍历
template <class ElemType>
void GraphClass<ElemType>::BFSGraph()
{
	if (NULL == root)
	{
		cout << "The graph is empty!" << endl;
		return;
	}

	cout << "BFS :" << endl;
	//标记每个顶点的颜色,表示是否被访问过、被发现
	enum NodeColor *color = new enum NodeColor[num_nodes];
	//记录遍历时源顶点到其他顶点的距离
	int *d = new int[num_nodes];
	//记录每个顶点的父节点
	GraphNodeLink *parentNode = new GraphNodeLink[num_nodes];
	for(int i = 0;i < num_nodes;++i)
	{
		*(color + i) = WHITE;
		*(d + i) = MaxVal;
		*(parentNode + i) = NULL;
	}

	//从源顶点(邻接表中第一个列表首节点开始遍历)
	int index = __getNodeIndex(*(root + 0));
	*(color + index) = GRAY;
	*(d + index) = 0;
	*(parentNode + index) = NULL;

	std::queue<GraphNodeLink> BFSQueue;//辅助数据结构:队列
	BFSQueue.push(*(root + 0));//源节点入队列
	while(!BFSQueue.empty())
	{
		GraphNodeLink tempNode = BFSQueue.front();
		cout << tempNode->elem << " ";
		BFSQueue.pop();
		int tempIndex = __getNodeIndex(tempNode);
		*(color + tempIndex) = BLACK;
		GraphNodeLink loopNode = (*(root + tempIndex))->next;//找到邻接表中对应的列表
		while(loopNode)
		{
			int index = __getNodeIndex(loopNode);
			if (WHITE == *(color + index))//当前节点未被发现
			{
				*(d + index) = *(d + tempIndex) + 1;
				*(parentNode + index) = tempNode;
				*(color + index) = GRAY;
				BFSQueue.push(loopNode);
			}
			loopNode = loopNode->next;
		}
	}

	cout << endl;
	cout << "distance from the source node : " << endl;
	for(int i = 0;i < num_nodes;++i)
	{
		if(MaxVal == *(d + i))
			cout << "The node cannot be visited from the source node!" << endl;
		else
		cout << "node " << (*(root + i))->elem << " has distance :" << *(d + i) << " from the source node"<< endl;
	}
}

//图的深度优先遍历
template <class ElemType>
void GraphClass<ElemType>::DFSGraph()
{
	if (NULL == root)
	{
		cout << "The graph is empty!" << endl;
		return;
	}

	cout << "DFS :" << endl;
	//标记每个顶点的颜色,表示是否被访问过、被发现
	enum NodeColor *color = new enum NodeColor[num_nodes];
	//记录每个顶点的父节点
	GraphNodeLink *parentNode = new GraphNodeLink[num_nodes];
	//时间戳:顶点第一次被发现的时间以及被访问的时间
	int *d = new int[num_nodes];
	int *f = new int[num_nodes];
	for(int i = 0;i < num_nodes;++i)
	{
		*(color + i) = WHITE;
		*(parentNode + i) = NULL;
	}

	int time = 0;//标记访问时间戳
	//从图中未被发现的节点开始,调用深度优先搜索函数
	for (int i = 0;i < num_nodes;++i)
	{
		GraphNodeLink currentNode = *(root + i);
		while(currentNode)
		{
			int tempIndex = __getNodeIndex(currentNode);
			if(WHITE == *(color + tempIndex))
				__DFSSubGraph(currentNode,time,d,f,color,parentNode);

			currentNode = currentNode->next;
		}
	}

	cout << endl;

	cout << "time of nodes :(first find the node,end of checking) " << endl;
	for (int i = 0;i < num_nodes;++i)
	{
		cout << "(" << *(d + i) << ", " << *(f + i) << ")  ";
	}
	cout << endl;
}

//从某个子节点开始深度优先搜索
template <class ElemType>
void GraphClass<ElemType>::__DFSSubGraph(typename GraphClass<ElemType>::GraphNodeLink u,int &time,int *d,int *f,
										 enum NodeColor *color,typename GraphClass<ElemType>::GraphNodeLink *parent)
{
	cout << u->elem << " ";
	++time;
	int currentIndex = __getNodeIndex(u);
	*(color + currentIndex) = GRAY;
	*(d + currentIndex) = time;
	GraphNodeLink loopNodeLink = (*(root + currentIndex))->next;
	while(loopNodeLink)
	{
		int tempIndex = __getNodeIndex(loopNodeLink);
		//与当前节点相邻的节点未被发现
		if (WHITE == *(color + tempIndex))
		{
			*(parent + tempIndex) = u;
			__DFSSubGraph(loopNodeLink,time,d,f,color,parent);
		}
		loopNodeLink = loopNodeLink->next;
	}
	
	*(color + currentIndex) = BLACK;
	*(f + currentIndex) = ++time;
}

template <class ElemType>
int GraphClass<ElemType>::__getNodeIndex(GraphNodeLink node)
{
	for (int i = 0;i <num_nodes;++i)
	{
		if((*(root + i))->elem == node->elem)
			return i;
	}

	return -1;
}

template <class ElemType>
void GraphClass<ElemType>::__printAdjacencyList()
{
	for (int i = 0;i < num_nodes;++i)
	{
		GraphNodeLink loopNode = *(root + i);
		while(loopNode)
		{
			cout << loopNode->elem << " ";
			loopNode = loopNode->next;
		}
		cout << endl;
	}
}

//空间释放:删除邻接表所占空间
template <class ElemType>
void GraphClass<ElemType>::__deleteAdjacencyList()
{
	if(NULL == root)
		return;
	for(int i = 0;i < num_nodes;++i)
	{
		GraphNodeLink head= *(root + i);
		if(head)
			__deleteSingleLinkList(head);
	}
}

//删除一个单链表所占空间
template <class ElemType>
void GraphClass<ElemType>::__deleteSingleLinkList(typename GraphClass<ElemType>::GraphNodeLink head)
{
	if(NULL == head)
		return;

	__deleteSingleLinkList(head->next);
	delete head;
}



Graph.cpp

#include "Graph.h"

using namespace std;

int main()
{
	//《算法导论(第二版)》P322 图22-1无向图测试例子
	//const int n = 5;
	//int a[n] = {1,2,3,4,5};
	//char matrix[n * n] = {0,1,0,0,1,
	//								1,0,1,1,1,
	//								0,1,0,1,0,
	//								0,1,1,0,1,
	//								1,1,0,1,0};

	//《算法导论(第二版)》P322 图22-2有向图测试例子
	const int n = 6;
	int a[n] = {1,2,3,4,5,6};
	char matrix[n * n] = {0,1,0,1,0,0,
									0,0,0,0,1,0,
									0,0,0,0,1,1,
									0,1,0,0,0,0,
									0,0,0,1,0,0,
									0,0,0,0,0,1};

	GraphClass<int> *graphObj = new GraphClass<int>;
	graphObj->createGraph(a,n,matrix);
	graphObj->__printAdjacencyList();
	graphObj->BFSGraph();
	graphObj->DFSGraph();

	return 0;
}

运行结果:



本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【算法学习】图相关算法编程实现-深度优先遍历和广度优先遍历 的相关文章

  • Consul+Ocelot搭建微服务实践--IdentityServer集成

    文章目录 1 IdentityServer介绍2 建立IdentityServer2 1 安装IdentityServer42 2 定义配置中心2 2 1 定义Client2 2 2 定义ApiResource2 2 3定义Identity
  • 配置Linux内核版本在线或离线升级(回退)

    在线升级 一 查看系统内核 xff08 当前系统内核为3 10 xff09 uname r 二 确定当前主机能连外网 ping www baidu com 三 导入在线elrepo仓库公钥 rpm import https www elre
  • 深度学习相关网址

    深度学习教学网址 Unsupervised Feature Learning and Deep Learning Tutorial GitHub rasmusbergpalm DeepLearnToolbox Matlab Octave t
  • CentOS Docker安装并使用httpd镜像运行容器

    Docker 是一个开源的应用容器引擎 xff0c 基于 Go 语言 并遵从 Apache2 0 协议开源 CentOS Docker 安装 先卸载旧版本 xff0c 较旧的 Docker 版本称为 docker 或 docker engi
  • 基于神经辐射场NeRF的SLAM方法

    随着2020年NeRF 1 的横空出世 xff0c 神经辐射场方法 xff08 Neural Radiance Fields xff09 如雨后春笋般铺天盖地卷来 NeRF最初用来进行图像渲染 xff0c 即给定相机视角 xff0c 渲染出
  • 有限视角重叠和不准确外参标定下的多相机SLAM的鲁棒初始化

    1 摘要 本文提出了一种当相机只有有限的公共视野和不准确的外参标定情形下的用于多相机视觉SLAM系统的鲁棒初始化方法 有限的共同视野导致只有一些特征可以在相机之间匹配上 离线标定后 xff0c 由于振动或相机错误放置而导致的不准确的外部位姿
  • Unifying Flow, Stereo and Depth Estimation论文阅读

    1 序言 上篇文章中我们提到了一种在线标定光学防抖主摄和ToF方法 其中使用RAFT作为光流估计网络来进行密集匹配 xff0c 本文我们来介绍一种更新的光流估计算法GMFlow xff0c 其被CVPR2022接收为Oral 同时也将介绍其
  • BARF: Bundle-Adjusting Neural Radiance Fields论文阅读

    摘要 神经辐射场 NeRF 可以合成真实世界场景的全新视角的照片 xff0c 其性能优异 xff0c 因此在计算机视觉领域引起较大的兴趣 NeRF的一个限制条件是需要准确相机位姿 本文提出了集束调整神经辐射场 BARF xff0c 可以用不
  • 自动驾驶高精定位

    定位是高等级自动驾驶的基础 xff0c 但在高速NOA和城区NOA等场景中 xff0c 如何能够稳定地在各种工况下实现高精度定位将是个难题 一个常见的问题是 xff1a 高速NOA 城区NOA功能需要实现多高精度的定位 xff1f 需要多高
  • 高精度组合导航里的松耦合、紧耦合、深耦合

    高精度定位 xff0c 是自动驾驶车辆一切丰满理想实现的前提 它用于判断自动驾驶功能是否处于可激活的设计运行条件内 xff1b 它用于支撑自动驾驶车辆的全局路径规划 xff1b 它用于辅助自动驾驶车辆的变道 避障策略 不同的场景特点 不同的
  • 超像素分割

    1 超像素 超像素是把一张图片中具有相似特征的像素进行聚类 xff0c 形成一个更具有代表性的大 像素 这个新的像素可以作为其他图像处理算法的基本单位 xff0c 可以减低图像的维度和异常像素点 目前常用的超像素分割算法有SLIC SEED
  • Numpy使用问题汇总

    1 批量操作 1 1 现象 import numpy as np vec 61 np zeros 10 int indices 61 np array 0 0 vec indices 43 61 1 print vec 上面代码的输出不是
  • K-means聚类算法

    K means 是我们最常用的基于欧式距离的聚类算法 xff0c 其认为两个目标的距离越近 xff0c 相似度越大 本文大致思路为 xff1a 先介绍经典的牧师 村名模型来引入 K means 算法 xff0c 然后介绍算法步骤和时间复杂度
  • 自组织映射(Self-organizing map, SOM)

    1 算法原理 自组织映射 Self organizing map SOM 通过学习输入空间中的数据 xff0c 生成一个低维 离散的映射 Map xff0c 从某种程度上也可看成一种降维算法 SOM是一种无监督的人工神经网络 不同于一般神经
  • 怎么将数据存入session

    怎么将数据存入session 默认数据都是存入request 需要自己设置存入session 1 方式1 原生session代码 64 RequestMapping 34 selectUser 34 public String select
  • Octree(八叉树)

    1 算法原理 八叉树 xff08 Octree xff09 是一种用于描述三维空间的树状数据结构 八叉树的每个节点表示一个正方体的体积元素 xff0c 每个节点有八个子节点 xff0c 将八个子节点所表示的体积元素加在一起就等于父节点的体积
  • DBSCAN聚类算法

    DBSCAN是一种非常著名的基于密度的聚类算法 其英文全称是 Density Based Spatial Clustering of Applications with Noise xff0c 意即 xff1a 一种基于密度 xff0c 对
  • 搭建网盘工具kk

    1 主要功能 支持用作简单文件列表 xff0c 无需数据库 xff0c 无用户管理 xff0c 分享等功能支持基本网盘功能 xff0c 需要安装MongoDB及Redis xff0c 支持用户注册 xff0c 文件分享 xff0c 用户目录
  • numpy中transpose详解

    transpose用于numpy中高维度数组的轴变换 xff0c 在二维情况下就是通常说的转置 该方法很不好理解 xff0c 本文详细介绍该方法 该方法有两个实现 xff0c 分别是numpy ndarray transpose和numpy
  • Python压缩文件

    1 标准库中的压缩模块 在我们常用的系统windows和Linux系统中有很多支持的压缩包格式 xff0c 包括但不限于以下种类 xff1a rar zip tar xff0c 以下的标准库的作用就是用于压缩解压缩其中一些格式的压缩包 2

随机推荐

  • LE-VINS:固态激光雷达增强的视觉惯性导航系统

    在光照剧烈变化 动态物体 弱纹理等视觉退化场景 xff0c 视觉路标点的深度估计难度急剧增加 xff0c 导致视觉惯性导航系统 VINS 的精度和鲁棒性恶化 采用非重复扫描原理的固态激光雷达 xff0c 为解决视觉路标点深度估计问题带来便利
  • Gradio介绍

    Gradio App 就是给 AI 算法工程师训练的模型赋予分享给大众的能力 从技术侧拆分 xff0c 由三个部分组成 xff1a 前端页面 43 后端接口 43 AI算法模型推理 Gradio 做了一件事情 xff0c 就是将这三个部分封
  • GitHub Copilot 快速入门

    GitHub Copilot 是 AI 结对程序员 可以使用 GitHub Copilot 在编辑器中获取整行或整个函数的建议 1 简介 让我们首先了解一些关于 GitHub Copilot 的内容 这是 GitHub 和 OpenAI 的
  • 电池连接接触电阻的优化研究

    金属与金属接触处的接触电阻主要受以下因素影响 xff1a 表面结构机械负载 表面结构可以通过表面平整度 表面氧化和吸水性进一步描述 电池组中的这些接头将采用焊接或螺栓连接方式 最初最容易想到的是螺栓母线接头 螺栓扭矩可用于估算力 xff0c
  • (二)CAS统一认证——自定义登录(数据库)

    简介 关于CAS的登录流程 xff0c overlay中只是一个简单的用户名密码登录 casuser Mellon xff0c 这个肯定是不能满足日常生产的需求的 xff0c 在日常开发中遇到最通用的情况就是从数据库中进行身份认证密码的比对
  • springcloud

    一 什么是SpringCloud xff1f Author xff1a 呆萌老师 QQ 2398779723 微信 it daimeng Spring Cloud是一个微服务框架 xff0c 相比Dubbo等RPC框架 Spring Clo
  • 计算机操作系统学习之多生产者多消费者问题

    文章目录 一 问题描述二 问题分析1 关系分析2 整理思路3 设置信号量4 具体实现5 补充 一 问题描述 有一个盘子 xff0c 每次只能放一个水果父亲专门往盘子里放苹果 xff0c 母亲专门往盘子里放橘子女儿专门等着吃盘子里的苹果 xf
  • 姿态角与欧拉角的关系

    1 姿态角与欧拉角 姿态角 xff1a 指的是机体坐标系与地理坐标系的夹角 欧拉角 xff1a 绕机体坐标系三个轴旋转的角度 关系 xff1a 绕某种旋转顺序的欧拉角与姿态角相等 xff08 1 xff09 在NED 北东地 坐标系 xff
  • 从入门到进阶,JAVA书籍的最佳阅读顺序!

    本文首发于知乎 xff0c 已获得1000 43 赞和收藏 原文链接 xff1a https www zhihu com question 269505829 answer 1791006152 先介绍下本人的情况 xff0c 希望对大家学
  • 设计数据密集型应用-C5-主从架构及同步延迟问题

    本文是 设计数据密集型应用 第5章学习笔记 什么是Replication Replication是在多台机器上维护的相同的数据 xff0c 即副本 保存副本的原因有以下几种 xff1a 减小延迟 xff1a 使得地理位置上数据离访问者更近
  • 第一条Pulsar消息发送

    什么是Pulsar pulsar是一个多租户 高性能server to srever消息解决方案 xff0c 最初由雅虎开发 xff0c 现在由apache维护 Pulsar的核心特性 xff1a 多集群云原生支持低延迟 良好的伸缩性多语言
  • 2014找工作总结-机会往往留给有准备的人

    转发请注明出处 xff1a 2014找工作总结 机会往往留给有准备的人 计算机专业同学的充电站 CSDN博客 其实我的求职过程在十一之前就已经结束了 xff0c 总体讲比较顺利 参加面试的几家公司基本都拿到了offer xff0c 分别是阿
  • 【数字图像处理】C++读取、旋转和保存bmp图像文件编程实现

    通过我这些天用C 43 43 读写bmp图像的经历 xff0c 摸索再摸索 xff0c 终于对bmp文件的结构 操作有了一定的了解 xff0c 下面就大概介绍bmp图片纯C 43 43 的读取 旋转和保存的实现过程 要用C 43 43 读取
  • 【数字图像处理】直方图均衡化详解及编程实现

    直方图均衡化的英文名称是Histogram Equalization 图像对比度增强的方法可以分成两类 一类是直接对比度增强方法 另一类是间接对比度增强方法 直方图拉伸和直方图均衡化是两种最常见的间接对比度增强方法 直方图拉伸是通过对比度拉
  • 【GPU编程】体绘制传输函数-分类(Volume Rendering Transfer function:Pre- VS Post-Classification)

    在科学可视化中 xff0c 我们所获得的体数据集经常是代表一些光学上的不同物理属性的单值 通常没有可行的方法可以从这样的数据中获得发射和吸收属性 因此用户必须采用某种映射方法给数据值分配光学属性值来决定数据中的不同结构的模样 这离的映射就被
  • 【OpenGL】理解GL_TRIANGLE_STRIP等绘制三角形序列的三种方式

    GL TRIANGLE STRIP绘制三角形方式很多时候令人疑惑 xff0c 在这里对其运作机理进行解释 一般情况下有三种绘制一系列三角形的方式 xff0c 分别是GL TRIANGLES GL TRIANGLE STRIP和GL TRIA
  • OpenJDK与JDK的区别分析

    OpenJDK与JDK的区别分析 一 以下是具体分析 xff1a 使用过LINUX的人都应该知道 xff0c 在大多数LINUX发行版本里 xff0c 内置或者通过软件源安装JDK的话 xff0c 都是安装的OpenJDK xff0c 那么
  • 【C++深入探索】Copy-and-swap idiom详解和实现安全自我赋值

    任何管理某资源的类比如智能指针需要遵循一个规则 xff08 The Rule of Three xff09 xff1a 如果你需要显式地声明一下三者中的一个 xff1a 析构函数 拷贝构造函数或者是拷贝赋值操作符 xff0c 那么你需要显式
  • 【Linux】Vim编辑器-批量注释与反注释

    vim编辑器 批量注释与反注释 在使用vim编写代码的时候 xff0c 经常需要用到批量注释与反注释一段代码 下面简要介绍其操作 方法一 块选择模式 插入注释 xff1a 用v进入virtual模式 用上下键选中需要注释的行数 按Contr
  • 【算法学习】图相关算法编程实现-深度优先遍历和广度优先遍历

    一 图的表示 图G 61 V E 要表示一个图 xff0c 通常有两种方法 xff1a 邻接表和邻接矩阵 两种方法都既可以表示有向图 xff0c 也可以表示无向图 邻接表表示由一个包含 V 个列表的数组组成 xff0c 其中每个列表对应V中