前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Swift4.2画"图"(Graph)

Swift4.2画"图"(Graph)

作者头像
gojam
发布2019-05-14 14:30:26
5220
发布2019-05-14 14:30:26
举报
文章被收录于专栏:gojam技术备忘录

看看你需要啥:

  • 一些编程基础
  • 一台装了Xcode的mac或者装了SwiftPlayground的iPad
  • 学习能力
  • 没了
  • 不,还有“图”是啥

30秒学会图

与图有关的概念
  • 一个图是多个顶点与他们的连边的集合,因此我们只需要描述顶点和边
  • 连边可以有方向,也可以没有,比如单行道
  • 连边可以有权重,也可以没有,比如道路的距离
怎样实现图结构
  • 顶点可以存储在数组或链表中
  • 边可以存储在以顶点为head的链表中,也可以用二维数组表示顶点和边

我们开始了

我们的教学是渐进式的(

  1. 认识链表
  2. 描绘图的结构
  3. 实现对图的遍历

认识链表

链表作为一种最基础的数据结构,实现了对多个元素线性的、动态的组织和管理,是实现图的基础之一。这里涉及到了类、模板、引用的知识。

链表上的结点类
代码语言:javascript
复制
class LinkedListNode<T> {
    var value:T
    var next:LinkedListNode?
    weak var previous:LinkedListNode?
    init(value:T){
        self.value = value
    }
}

weak关键字:weak声明previous是对被引用对象的弱引用,用于防止循环引用(互相被引用的对象无法释放)。例如A引用B,B引用A,因为他们都被引用,垃圾回收机制无法释放他们,但如果A对B的引用是弱引用,那么B没有被强引用,因而可以被直接释放,循环引用被破除。这里用来防止特定情况下的循环引用。

链表类
代码语言:javascript
复制
class LinkedList<T> {
    typealias Node = LinkedListNode<T>
    var head:Node?
}

描绘图的结构

我们知道,图可以用邻接矩阵或邻接表实现,这里采用邻接表实现图:一个存储结点的数组+n个扩展结点的链表(用于表达连边)。在Swift中,数组可以自由扩展,虽然和链表有很大区别,但我们用数组代替可以省很多事:-D。

存储结点的图

从链表结构转化

代码语言:javascript
复制
class Graph<T> {
    typealias Node = LinkedListNode<T>
    var nodes=[Node]()
}
顶点类
代码语言:javascript
复制
class graphNode<T> {
    var value:T
    var edges=[edge<T>]()
    init(value:T){
        self.value = value
    }
}
边类
代码语言:javascript
复制
class edge<T>{
    typealias node = graphNode<T>
    var vertex:node
    init(vertex:node){
        self.vertex=vertex
    }
}
添加顶点
代码语言:javascript
复制
class graph<T> {
    typealias node = graphNode<T>//用node代替graphNode比较简洁
    var nodes=[node]()//可以使用nodes.count
    func addNode(value:T) -> node {
        let newNode=node(value:value)//我们不需要更改结点内容,用lets表示常量
        nodes.append(newNode)
        return newNode
    }
}
添加边
代码语言:javascript
复制
class graph<T> {
    typealias node = graphNode<T>//用node代替graphNode比较简洁
    var nodes=[node]()//可以使用nodes.count
    func addNode(value:T) -> node {
        let newNode=node(value:value)//我们不需要更改结点内容,用lets表示常量
        nodes.append(newNode)
        return newNode
    }
    func addEdge(vertexA:node,vertexB:node) -> Bool {
        for n in vertexA.edges{//已经有边就不能再添加了
            if(n.vertex===vertexB){
                return false}
        }
        vertexA.edges.append(edge(vertex:vertexB))
        vertexB.edges.append(edge(vertex:vertexA))
        return true
    }
}

实现对图的遍历

深度优先遍历

我们只实现深度优先遍历,实现思路:从出发点开始,选择一个未访问过的邻居,递归下去,所有邻居都被访问时返回。为了区别,我们向顶点类添加visited属性。

代码语言:javascript
复制
class graph<T> {
    typealias node = graphNode<T>//用node代替graphNode比较简洁
    var nodes=[node]()//可以使用nodes.count
    func addNode(value:T) -> node {
        let newNode=node(value:value)//我们不需要更改结点内容,用lets表示常量
        nodes.append(newNode)
        return newNode
    }
    func addEdge(vertexA:node,vertexB:node) -> Bool {
        for v in vertexA.edges{//已经有边就不能再添加了
            if(v.vertex===vertexB){
                return false}
        }
        vertexA.edges.append(edge(vertex:vertexB))
        vertexB.edges.append(edge(vertex:vertexA))
        return true
    }
    func DFS(start:node) -> Void {
        for v in start.edges {
            if(v.vertex.visited==false){
                proc(v:v.vertex)
                DFS(start: v.vertex)
            }
        }
        return
    }
    func proc(v:node) -> Void{
        v.visited=true
        //对顶点进行的操作
    }
}

class graphNode<T> {
    var value:T
    var edges=[edge<T>]()
    init(value:T){
        self.value = value
    }
    var visited = false
}

class edge<T>{
    typealias node = graphNode<T>
    var vertex:node
    init(vertex:node){
        self.vertex=vertex
    }
}

//验证性操作
var G = graph<Int>()
var v1=G.addNode(value:5)
var v2=G.addNode(value: 10)
G.addEdge(vertexA: v1, vertexB: v2)
G.nodes[0]
G.nodes[1]
G.DFS(start: v1)
G.nodes[0]
G.nodes[1]

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2019年1月4日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 看看你需要啥:
  • 30秒学会图
    • 与图有关的概念
      • 怎样实现图结构
      • 我们开始了
      • 认识链表
        • 链表上的结点类
          • 链表类
          • 描绘图的结构
            • 存储结点的图
              • 顶点类
                • 边类
                  • 添加顶点
                    • 添加边
                    • 实现对图的遍历
                      • 深度优先遍历
                      相关产品与服务
                      对象存储
                      对象存储(Cloud Object Storage,COS)是由腾讯云推出的无目录层次结构、无数据格式限制,可容纳海量数据且支持 HTTP/HTTPS 协议访问的分布式存储服务。腾讯云 COS 的存储桶空间无容量上限,无需分区管理,适用于 CDN 数据分发、数据万象处理或大数据计算与分析的数据湖等多种场景。
                      领券
                      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档