当前位置: 首页 > 编程日记 > 正文

数据结构的简要介绍:图形如何工作

by Michael Olorunnisola

通过Michael Olorunnisola

数据结构的简要介绍:图形如何工作 (A Gentle Introduction to Data Structures: How Graphs Work)

So who wants to work at Google, Facebook, or maybe LinkedIn? Beyond their grueling interview process, one thing all these companies have in common is their heavy reliance on the graph data structure.

那么,谁想在Google,Facebook或LinkedIn工作? 除了艰苦的采访过程外,所有这些公司的共同点是,他们严重依赖图形数据结构。

After learning a bit about graphs, you’ll understand why. By the end of this post, you’ll feel more comfortable jumping into Cracking the Coding Interview — or a similar interview prep book — and knocking out some network traversal algorithms practice problems.

在学习了一些关于图形的知识之后,您将了解原因。 到本文结束时,您会更轻松地进入“ 破解编码面试”或类似的面试准备书,并剔除一些网络遍历算法的实践问题。

图如何工作 (How Graphs Work)

Graphs are a powerful and versatile data structure that easily allow you to represent real life relationships between different types of data (nodes). There are two main parts of a graph:

图形是功能强大且用途广泛的数据结构,可以轻松地表示不同类型的数据(节点)之间的现实关系。 图有两个主要部分:

  • The vertices (nodes) where the data is stored i.e. the numbers in the image on the left

    存储数据的顶点(节点), 即左侧图像中的数字

  • The edges (connections) which connect the nodes i.e. the lines between the numbers in the image

    连接节点的边缘(连接), 即图像中数字之间的线

Graphs can be undirected or directed. Using the graph above as an example — and treating the edges as every day relationships — here’s the difference:

图可以是无向或有向的 。 以上面的图表为例-将边缘视为每天的关系-区别在于:

Undirected graph: If 6 was a friend of 4, 4 would likewise be a friend of 6. The relationship exists in both directions.

无向图:如果6是4的朋友,则4也会是6的朋友。这种关系在两个方向上都存在。

Directed graph: if 6 had a crush on 4, that doesn’t necessarily mean 4 has to have a crush on 6. Love’s tough ?. The relationships are based on the direction of the edges. It can be a one way relationship or a two-way relationship, but it must be explicitly stated.

有向图:如果6对4暗恋,那并不一定意味着4必须对6暗恋。 关系基于边缘的方向。 它可以单向关系Ø 为r的双向关系,但必须明确说明。

Here are some common operations you can perform on graphs:

以下是您可以在图表上执行的一些常见操作:

Additions

加法

  • addNode: adds vertices to your graph

    addNode 将顶点添加到图形中

  • addEdge: creates edges between two given vertices in your graph

    addEdge 在图形中的两个给定顶点之间创建边

Removals

清除

  • removeNode: removes vertices from your graph

    removeNode 从图形中删除顶点

  • removeEdge: removes edges between two given vertices in your graph

    removeEdge 删除图形中两个给定顶点之间的边

Search

搜索

  • contains: checks if your graph contains a given value

    contains 检查图形是否包含给定值

  • hasEdge: checks if a connection exists between two given nodes in your graph

    hasEdge 检查图形中两个给定节点之间是否存在连接

In addition to this, graphs can be weighted or unweighted. All this means is that there is some value or cost associated with the edges between the vertices. The best example of this would be google maps.

除此之外,图形可以加权不加权。 所有这些意味着与顶点之间的边相关联的有一些价值或成本。 最好的例子就是谷歌地图。

As you can see, there are two suggested routes between Mumbai and Delhi. But how would a Google graph algorithm know that one in blue is the best option? Simple. You give the different routes (edges) weights equivalent to their distances. Knowing that, the algorithm can deduce that one path is 50km shorter than the other, and probably faster.

如您所见,孟买和德里之间有两条建议的路线。 但是Google图形算法如何知道蓝色为最佳选择? 简单。 您给不同的路线(边)权重等于它们的距离。 知道这一点,该算法可以推断出一条路径比另一条路径短50km,并且可能更快。

Of course, there are other factors given weight like delays and speed limits. But the concept remains the same. Weighted graphs allow you to choose the quickest path, or the path of least resistance (see Dijkstra’s Algorithm).

当然,还有其他一些因素会给人以重量,例如延迟和速度限制。 但是概念保持不变。 加权图使您可以选择最快的路径或阻力最小的路径(请参见Dijkstra的算法 )。

As you can see from these examples, graphs can show almost any type of relationship with just data and edges. This is why graphs have become so widely used by companies like LinkedIn, Google, and Facebook. Just read this post by Facebook about why they made the transition back in 2007 from relational databases to graph databases.

从这些示例中可以看到,图形可以显示几乎任何类型的关系,而只有数据和边。 这就是为什么图已被LinkedIn,Google和Facebook等公司广泛使用的原因。 只需阅读Facebook的这篇文章,了解他们为何在2007年从关系数据库过渡到图形数据库。

Now that you have a basic understanding of what graphs are, let’s explore some examples.

现在,您已经对什么是图形有了基本的了解,让我们探索一些示例。

Example Use Cases:

用例示例:

  • Representing a social network

    代表社交网络
  • Representing maps

    代表地图
  • Killing interview questions

    杀死面试问题

The last one there is up to you. If you’re getting ready for a coding interview, I’ve included some helpful additional resources at the end of this post.

最后一个取决于您。 如果您准备进行编码面试,那么本文结尾处将提供一些有用的其他资源。

In the mean time, let’s take a stab at social networks.

同时,让我们来看看社交网络。

使用图建立社交网络 (Building a social network using graphs)

Since Facebook kind of has a monopoly on this whole social network thing, how about we create a private social network for developers? DevBook! Of course, we could keep things simple and just create a Facebook group instead… But being grade A developers who love a good challenge, let’s take a prideful moment to throw “KISS” out the window.

由于Facebook在整个社交网络上都有垄断地位,我们如何为开发人员创建私有社交网络呢? DevBook! 当然,我们可以保持简单,而只需创建一个Facebook组即可。但是,作为热爱挑战的A级开发人员,让我们度过一个自豪的时刻,将“ KISS”扔出窗外。

First you create the storage for your graph. You realize there are probably multiple ways you can represent a graph data structure, but for now you decide upon a list that will store each unique developer as a key and all their connections as their associated values. Upon running a quick Google search, you realize that you’re making an adjacency list.

首先,为图形创建存储。 您意识到可能有多种方法可以表示图形数据结构,但是现在,您决定一个列表,该列表将每个唯一的开发人员存储为键,并将其所有连接存储为关联值。 在进行快速的Google搜索后,您会发现自己正在创建邻接表。

You prefer following a functional pattern, so you decide to go the route below:

您更喜欢遵循一种功能模式,因此决定采用以下路线:

let MakeGraph = () => {   // Function that will create our graphs  let graph = {};  return graph;}
let devBook = MakeGraph();  // Our graph representing our site

Now that you have the graph representation, you need to create a way to add developers to the graph when they sign up, and to store any future connections they might have.

现在,您已经有了图形表示形式,您需要创建一种方法,在开发人员注册时将其添加到图形中,并存储他们将来可能拥有的任何连接。

You decide to make the users keys on the object, and use an object with an edges property to keep a list of their connections.

您决定将用户键放在对象上,并使用具有edges属性的对象保留其连接列表。

let MakeGraph = () => {     let graph = {};
graph.addVertex = (node) => {       // add members as vertices here     //  store their connections as properties on an edges object        graph[node] = {edges:{}};  }
return graph;}
let devBook = MakeGraph();
devBook.addVertex('James Gosling');devBook.addVertex('Guido Rossum');devBook.addVertex('Linus Torvalds');devBook.addVertex('Michael Olorunnisola');
// Your graph will now look like this:
{ addVertex: [Function],  'James Gosling': { edges: {} },  'Guido Rossum': { edges: {} },  'Linus Torvalds': { edges: {} },  'Michael Olorunnisola': { edges: {} } }

Note that in practice, you would want to store records with unique user id’s instead of names that couldn’t be overwritten by other users with the same name, but I’ve used the names of famous programmers (plus myself) for flavor.

请注意,实际上,您将要存储具有唯一用户ID的记录,而不是不能被其他具有相同名称的用户覆盖的名称存储的记录,但是我使用了著名程序员(加上我自己)的名字来修饰。

Now you can build a contains method to check whether a user has already been stored on your graph, and prevent the overwriting of any of the relationships that are created as the site grows.

现在,您可以构建一个contains方法,以检查用户是否已经存储在图形上,并防止覆盖随着站点增长而创建的任何关系。

let MakeGraph = () => {   let graph = {};
graph.contains = (node)=> { // you can check whether a user exists    return !!graph[node];  }
graph.addVertex = (node) => {     if(!graph.contains(node)){ // call contains to prevent overwrite      graph[node] = {edges:{}};    }  }
return graph;}

Great! Now that you have a good set of unique users, you want to let them connect with each other by creating friendships with each other (edges). These edges won’t be directed, as you realize friendships don’t really work that way.

大! 现在您已经拥有了很多独特的用户,您希望通过彼此之间的友谊(边缘)来使他们彼此联系。 这些优势将无处可寻,因为您意识到友谊并不是那样工作的。

let MakeGraph = () => {   let graph = {};
graph.contains = (node)=> {    return !!graph[node];  }
graph.addVertex = (node) => {      if(!graph.contains(node)){      graph[node] = {edges:{}};    }  }
graph.addEdge = (startNode, endNode) => {    // Only if both nodes exist    // Add each node to the others edge list
if(graph.contains(startNode) && graph.contains(endNode)){      graph[startNode].edges[endNode] = true;      graph[endNode].edges[startNode] = true;    }  }
return graph;}
let devBook = MakeGraph();  // Our graph representing our site
devBook.addVertex('James Gosling');devBook.addVertex('Guido Rossum');devBook.addVertex('Linus Torvalds');devBook.addVertex('Michael Olorunnisola');
// We'll add the edges here!
devBook.addEdge('James Gosling', 'Guido Rossum');devBook.addEdge('Linus Torvalds', 'Michael Olorunnisola');
// Now our devBook will look like this:
{ contains: [Function],  addVertex: [Function],  addEdge: [Function],  'James Gosling': { edges: { 'Guido Rossum': true } },  'Guido Rossum': { edges: { 'James Gosling': true } },  'Linus Torvalds': { edges: { 'Michael Olorunnisola': true } },  'Michael Olorunnisola': { edges: { 'Linus Torvalds': true } } }

This is absolutely fantastic, but at some point Linus reaches out to you and says, “I have no idea who the Michael guy is. I assumed he was Michael Tiemann, but I finally bothered trying to read his last name.”

这绝对是太棒了,但是在某些时候,Linus会向您伸出手,说:“我不知道谁是迈克尔。 我以为他是Michael Tiemann,但我终于不愿尝试读取他的姓氏。”

Right now you don’t have a way to remove a relationship, so you hop right into the code to whip together a removeEdge method to allow Linus to keep his friends list accurate.

现在,您还没有删除关系的方法,因此,您跳入了代码中,一起使用removeEdge方法来使Linus保持其好友列表的准确性。

let MakeGraph = () => {   let graph = {};
graph.contains = (node)=> {    return !!graph[node];  }
graph.addVertex = (node) => {      if(!graph.contains(node)){      graph[node] = {edges:{}};    }  }
graph.addEdge = (startNode, endNode) => {    if(graph.contains(startNode) && graph.contains(endNode)){      graph[startNode].edges[endNode] = true;      graph[endNode].edges[startNode] = true;    }  }    graph.removeEdge = (startNode, endNode) => {    if(graph.contains(startNode) && graph.contains(endNode)){      delete graph[startNode].edges[endNode]      delete graph[endNode].edges[startNode]    }  }
return graph;}
devBook.removeEdge('Linus Torvalds', 'Michael Olorunnisola');
// Relationship removed!
{ contains: [Function],  addVertex: [Function],  addEdge: [Function],  removeEdge: [Function],  'James Gosling': { edges: { 'Guido Rossum': true } },  'Guido Rossum': { edges: { 'James Gosling': true } },  'Linus Torvalds': { edges: {} },  'Michael Olorunnisola': { edges: {} } }

Great! Unfortunately Linus says that he just wanted to try the site out, but that he’s way to0 hermitic to be on a site like this. He really wants to delete his account, but is currently unable to because you haven’t added a node removal method yet.

大! 不幸的是,Linus说他只是想尝试该站点,但是他想让隐士进入这样的站点。 他确实想删除他的帐户,但是由于您还没有添加节点删除方法而当前无法删除。

let MakeGraph = () => {   let graph = {};
graph.contains = (node)=> {    return !!graph[node];  }
graph.addVertex = (node) => {      if(!graph.contains(node)){      graph[node] = {edges:{}};    }  }
graph.removeVertex = (node) => {    if(graph.contains(node)) {    // We need to remove any existing edges the node has      for(let connectedNode in graph[node].edges) {        graph.removeEdge(node, connectedNode);      }      delete graph[node];    }
}
graph.addEdge = (startNode, endNode) => {    if(graph.contains(startNode) && graph.contains(endNode)){      graph[startNode].edges[endNode] = true;      graph[endNode].edges[startNode] = true;    }  }    graph.removeEdge = (startNode, endNode) => {    if(graph.contains(startNode) && graph.contains(endNode)){      delete graph[startNode].edges[endNode]      delete graph[endNode].edges[startNode]    }  }
return graph;}
// Now we can remove users!
devBook.removeVertex('Linus Torvalds');

Great job! Although you lost a potentially valuable user, you’ve been able to implement a basic graph system to keep track of all of your users and their friendships.

很好! 尽管您失去了一个潜在的有价值的用户,但是您已经能够实现一个基本的图形系统来跟踪所有用户及其友情。

If you notice, we didn’t implement the hasEdge method, but I think you have enough information to give it a shot! Feel free to include your implementation in the comments below ?.

如果您注意到,我们没有实现hasEdge方法,但是我认为您有足够的信息来尝试一下! 可以在下面的评论中随意包含您的实现吗?

图方法作为邻接表的时间复杂度分析 (A time complexity analysis on the graph methods as an adjacency list)

Here’s our code again:

这又是我们的代码:

let MakeGraph = () => {   let graph = {};
graph.contains = (node)=> {    return !!graph[node];  }
graph.addVertex = (node) => {      if(!graph.contains(node)){      graph[node] = {edges:{}};    }  }
graph.removeVertex = (node) => {    if(graph.contains(node)) {      for(let connectedNode in graph[node].edges) {        graph.removeEdge(node, connectedNode);      }      delete graph[node];    }  }
graph.addEdge = (startNode, endNode) => {    if(graph.contains(startNode) && graph.contains(endNode)){      graph[startNode].edges[endNode] = true;      graph[endNode].edges[startNode] = true;    }  }    graph.removeEdge = (startNode, endNode) => {    if(graph.contains(startNode) && graph.contains(endNode)){      delete graph[startNode].edges[endNode]      delete graph[endNode].edges[startNode]    }  }
return graph;}

addNode is O(1): You’re just creating a property on an object so it’s constant time

addNode O(1):您只是在对象上创建属性,因此时间恒定

addEdge is O(1): Since you’re using an object to represent your graph, it’s a constant time operation since your nodes and edges are represented as properties.

addEdge O(1):由于您使用的是对象来表示图形,因此这是一项固定时间的操作,因为您的节点和边都表示为属性。

removeNode is O(n): If a node has edges, you’re going to have to iterate over all it’s existing edges to remove it’s existence as an edge on it’s connected nodes.

removeNode O(n):如果节点具有边缘,则必须迭代所有现有边缘,以消除其作为已连接节点上边缘的存在。

removeEdge is O(1): Since your nodes are properties on your graph, you can access them in constant time and just delete the edges which are also accessible in constant time.

removeEdge O(1):由于节点是图形上的属性,因此可以在恒定时间内访问它们,而只需删除在恒定时间内也可以访问的边。

contains is O(1): As a property on your graph, it’s a constant time lookup for a node.

contains O(1):作为图上的一个属性,它是对节点的恒定时间查找。

hasEdge is O(1): Both nodes would be properties on your graph, so it would be a constant time lookup.

hasEdge O(1):两个节点都是图上的属性,因此它将是固定时间的查找。

是时候快速回顾一下 (Time for a quick recap)

Graphs:

图表:

  1. are just a combination of vertices and edges representing data and relationships

    只是表示数据和关系的顶点和边的组合
  2. have addNode, addEdge, removeNode, and removeEdge methods to manage their contents

    具有addNodeaddEdgeremoveNoderemoveEdge方法来管理其内容

  3. have a contains and a hasEdge method to help you track the state of their state

    有一个containshasEdge方法可以帮助您跟踪其状态

进一步阅读 (Further Reading)

To say that there is a lot more to the graph data structure would be a huge understatement.

要说图形数据结构还有很多其他内容,这是一个很大的轻描淡写。

You could have represented the edges as an array instead of objects, or the entire graph as a 2-d array (adjacency matrix). You could have even represented the graph solely by their edges in an array (edge list).

您可以将边缘表示为数组而不是对象,或者将整个图形表示为2维数组( 邻接矩阵 )。 您甚至可以仅通过数组中的边缘来表示图形( edge list )。

As with anything in programming, there are trade-offs associated with each representation and it’s definitely worthwhile learning what they are.

与编程中的任何内容一样,每种表示形式都需要权衡取舍,绝对值得学习它们的含义。

Graphs are by far my favorite data structure and also one of the most versatile, but that’s just my humble opinion. (Those of you who love trees really are just graph lovers in disguise ?).

到目前为止,图是我最喜欢的数据结构,也是最通用的数据结构之一,但这只是我的拙见。 ( 你们当中那些爱树的人真的只是变相的图形爱好者 ?)。

Maybe I can sway you to love them as much as I do, so here are a few additional resources for you to read up on them:

也许我可以像我一样去爱你,所以这里有一些其他资源供您阅读:

  • This Wikipedia Article does a great job not only covering the different representation of a graph, but also introducing you to some of the algorithms often associated with graphs.

    这篇Wikipedia文章做得很好,不仅涵盖了图形的不同表示形式,还向您介绍了一些通常与图形相关的算法。

  • For those of you who are using Python here’s a graph implementation from the Python team!

    对于那些正在使用Python的人,这里有Python团队提供的图形实现 !

  • TutorialsPoint does a really good job of diving into how to implement two of the algorithms: Depth First Search and Breadth First Search. You might be confronted with these graph algorithms in interviews.

    TutorialsPoint在深入研究如何实现两种算法方面做得非常好,即深度优先搜索和广度优先搜索 。 您可能在采访中遇到这些图算法。

  • Keith Woods does a great job of walking through how to implement a recommendation engine with a graph data structure here. Definitely worth a read, as it implements a lot of the concepts we didn’t get to here.

    基思·伍兹确实通过如何实现与图形数据结构的推荐引擎行走了伟大的工作在这里 。 绝对值得一读,因为它实现了许多我们以前未曾了解的概念。

  • For those of you who are familiar with relational databases like MySQL — there’s a Graph database Neo4j, which I absolutely love, that not only uses SQL-like syntax, but has an awesome graphical user interface.

    对于那些熟悉像MySQL这样的关系数据库的人来说,我绝对喜欢一个Graph数据库Neo4j ,它不仅使用类似SQL的语法,而且还具有出色的图形用户界面 。

翻译自: https://www.freecodecamp.org/news/a-gentle-introduction-to-data-structures-how-graphs-work-a223d9ef8837/

相关文章:

Catel(翻译)-为什么选择Catel

1. 介绍 这篇文章主要是为了说明,我们为什么要使用Catel框架作为开发WPF,Silverlight,和Windows phone7应用程序的开发框架。 2. 通用功能 2.1. 这是你的选择 针对需对开发者,再使用架构的时候是希望有很大的自由度的,但是大部…

iOS 三种类型的Block

Block 的copy 操作 Block 其实来讲有三种类型 全局块 NSConcreteGlobalBlock 栈块 NSConcreteStackBlock 堆块 NSConcreteMallocBlock 全局块存储在全局内存中,相当于单例 栈块存于栈内存中,超出其作用域则马上进行销毁 堆块存在于堆内存中&#x…

2.4G高频PCB天线设计

2.4G高频PCB天线设计转载于:https://www.cnblogs.com/LittleTiger/p/6215262.html

如何一起破解图形化Python调试器

15分钟内从零调试 (Zero-to-Debugging in 15 mins) You don’t realize the value of a debugger until you’re stuck working on a hard-to-visualize problem. But once you fire up a development environment with decent debugging capabilities, you’ll never look bac…

python 之路,Day11 (下)- sqlalchemy ORM

python 之路,Day11 - sqlalchemy ORM 本节内容 ORM介绍sqlalchemy安装sqlalchemy基本使用多外键关联多对多关系表结构设计作业1. ORM介绍 orm英文全称object relational mapping,就是对象映射关系程序,简单来说我们类似python这种面向对象的程序来说一切…

iOS事件响应链

1 如下 NSObject 显然是基类,都是继承与UIResponder. 可以看出UIApplication,UIView,UIViewController都是继承自UIResponder类,可以响应和处理事件 我们都是通过UIResonder 来查找控件的父视图控件。’ 发生触摸事件之后&…

论5级流水32bit risc cpu设计

前段时间用verilog写了一个32bit的risc cpu,五级流水,下板调试已经完全可用,准备后期加入浮点运算器,因为最近事情超级多,因此暂时先把RTL图传上来供大家参考,后面我会讲具体怎么设计。希望大家多多关注 :)转载于:http…

开源项目贡献者_嘿新手开源贡献者:请写博客。

开源项目贡献者by Shubheksha通过Shubheksha 嘿新手开源贡献者:请写博客。 (Hey newbie open source contributors: please blog more.) As a newbie open source contributor, I often felt lost and dejected. I couldn’t figure out how different modules fit…

instanceof, isinstance,isAssignableFrom的区别

instanceof运算符 只被用于对象引用变量,检查左边的被测试对象 是不是 右边类或接口的 实例化。如果被测对象是null值,则测试结果总是false。 形象地:自身实例或子类实例 instanceof 自身类 返回true 例: String snew String(&qu…

POJ - 3538 - Domestic Networks

先上题目: Domestic NetworksTime Limit: 2000MS Memory Limit: 65536KTotal Submissions: 732 Accepted: 204 Special JudgeDescription Alex is a system administrator of Domestic Networks Inc. His network connects apartments and spans over multiple buil…

iOS HitTest 机制

当用户触摸(Touch)屏幕进行交互时,系统首先要找到响应者(Responder)。系统检测到手指触摸(Touch)操作的时候,将Touch 以UIEvent 的方式加入到UIApplication 事件队列中去。UIApplica…

巨石加密_缓解巨石

巨石加密by Ian Belcher伊恩贝尔彻(Ian Belcher) 我们如何将技术堆栈转向基于服务,以开发人员体验为中心的设计 (How we pivoted our tech stack to a service-based, developer experience-focused design) This article documents the problems we experienced w…

Python函数中的参数(一)

函数传递参数时的简要关键点: 1、参数的传递是通过自动将对象赋值给本地变量名来实现的。函数参数在实际中只是Python赋值的一个实例。因为引用是以指针的形式实现的,所有的参数实际上都是通过指针进行传递的。 2、在函数内部的参数名的赋值不会影响调用…

LLDB 调试相关

LLDB 初始 LLDB 是一个有着 REPL 的特性和 C ,Python 插件的开源调试器。LLDB 绑定在 Xcode 内部,存在于主窗口底部的控制台中。调试器允许你在程序运行的特定时暂停它,你可以查看变量的值,执行自定的指令,并且按照你所认为合适的…

javascript优缺点_为什么要在JavaScript中使用静态类型? 优缺点

javascript优缺点by Preethi Kasireddy通过Preethi Kasireddy 为什么要在JavaScript中使用静态类型? 优缺点 (Why use static types in JavaScript? The Advantages and Disadvantages) We covered a lot of ground in Part 1! With syntax out of the way, let’…

大数的减法函数--c语言

代码展示&#xff1a; http://paste.ubuntu.com/23693598/ #include<stdio.h> #include<stdlib.h> #include<string.h> char * largeDiffer(char *a,char *b){ /* 使用说明 传入的a和b只能为整数 结果为a-b;返回的为字符指针&#xff0c;注意数组不要越…

json 基础

json格式 JSON格式&#xff1a;http://www.json.org/ python和JSON的关系请参考&#xff1a;http://docs.python.org/library/json.html JSON建构有两种结构&#xff1a; 1. “名称/值”对的集合&#xff08;A collection of name/value pairs&#xff09;。不同的语言中&#…

iOS 中 load 和 initialize的实现顺序

1 load 函数 调用时机&#xff0c;当类引用进项目的时候执行load函数&#xff0c;在main函数开始之前&#xff0c;与 这个类是否被用到是无关的&#xff0c;每个类的load函数都会自动调用一次。 1 父类和子类都实现load函数的时候&#xff0c;父类的load方法优先于子类 2 类…

需求简报_代码简报:有史以来最怪诞的丑毛衣

需求简报Here are three stories we published this week that are worth your time:这是我们本周发布的三个值得您关注的故事&#xff1a; The geekiest ugly sweater ever: 4 minute read 有史以来最怪异的丑毛衣&#xff1a; 4分钟阅读 Lessons from my post-bootcamp job …

C#内置函数 RunSql的使用

作用批量执行sql语句表达式.RunSQL(SQLStatement,UseTransaction)表达式.一个代表DoCmd对象的变量。注释&#xff1a;sqlstatement参数的最大长度为 32,768 个字符&#xff08;而"宏"窗口中的 SQL 语句操作参数的最大长度为 256 个字符&#xff09;。 官方说仅能用于…

swif 在字符串中查找特定字符索引以及改变字符串的指定位置的颜色 字体大小

1 第一种方式 var text "谁包含这个字母";let range:Range<String.Index> text.range(of: "含")!;let end_idx:Int text.distance(from: text.startIndex, to: range.lowerBound);// 打印2print(end_idx);类方法 抽取 // 查找对应索引static func…

SD卡的控制方法(指令集和控制时序)

1.SD卡的命令格式&#xff1a; SD卡的指令由6字节(Byte)组成&#xff0c;如下&#xff1a; Byte1&#xff1a;0 1 x x x x x x(命令号&#xff0c;由指令标志定义&#xff0c;如CMD39为100111即16进制0x27&#xff0c;那么完整的CMD39第一字节为01100111&#xff0c;即0x270x40…

javascript 代码_代码简介:2016年JavaScript的现状

javascript 代码Here are three stories we published this week that are worth your time:这是我们本周发布的三个值得您关注的故事&#xff1a; The state of JavaScript in 2016: 5 minute read 2016年JavaScript状况&#xff1a; 阅读5分钟 Upgrading to macOS Sierra wi…

Unity协程截图,WWWForm、WWW配合上传

先说一下原理。。 截图有两种方法&#xff0c;第一种&#xff1a; Application.CaptureScreenshot(url); 这个API可以截全屏并保存到指定路径 这里我们不采用此方法 下面的代码采用第二种方法&#xff0c;自己建一个Texture2D 这种方法灵活&#xff0c;操作性更高 WWWForm方法是…

OC 的反射机制以及使用场景

OC 的反射机制 一 定义概念 普遍的概念就是类似于java的反射机制&#xff0c;动态机制使得OC语言更加灵活。 反射机制就是可以根据指定的类名获取类的相关信息。 二 作用 1 根据类名获得class // 选择器 和字符串之间的相互转化 FOUNDATION_EXPORT NSString *NSStringFr…

centos 网卡聚合及Cisco交换机链路聚合

一、配置环境 centos 系统。网卡1口和2口做链路聚合。 交换机网口 6口和7口。 二、服务器操作步骤 centos 6 1.创建一个channel bonding interface #vi /etc/sysconfig/network-scripts/ifcfg-bond0 添加如下几行&#xff1a; GATEWAY192.168.10.1 DNS1202.106.0.20 DEVICEb…

graphql redux_如何在Redux应用程序中使用GraphQL

graphql reduxby Howon Song通过宋颂恩 如何在Redux应用程序中使用GraphQL (How to use GraphQL in your Redux app) Fetching and managing data in Redux requires too much work. As Sashko Stubailo points out:在Redux中获取和管理数据需要太多的工作。 正如Sashko Stuba…

原创:去繁存简,回归本源:微信小程序公开课信息分析《一》

以前我开过一些帖子&#xff0c;我们内部也做过一些讨论&#xff0c;我们从张小龙的碎屏图中 &#xff0c;发现了重要讯息&#xff1a; 1&#xff1a;微信支付将成为重要场景&#xff1b; 2&#xff1a;这些应用与春节关系不小&#xff0c;很多应用在春节时&#xff0c;有重要的…

ubuntu 14.0 下github 配置

一&#xff1a;创建Repositories 1:首先在github下创建一个帐号。这个不用多说&#xff0c;然后创建一个Repositories。 2:然后在ubuntu下安装git相关的东东&#xff1a; 1sudo apt-get install git-core git-gui git-doc -y 3:在ubuntu本地创建一个ssh密匙&#xff1a; 1ssh-k…

OC 消息转发实现多继承

消息转发实现多继承 在OC 中&#xff0c;一个类只支持单继承&#xff0c;但是可以通过别的手段实现多继承。 利用消息转发实现多继承。 在OC 中&#xff0c;对象调用方法实际是在发消息&#xff0c;对象接收到一条消息的时候&#xff0c;消息函数随着对象的isa 指针到自己的…