跟我一起学“仓颉”算法-图

目录

一、图

二、实现

三、小结


一、图

图通常用一个二元组G=<V,E>表示,V表示节点集,E表示边集。|V|表示节点集中元素的个数,即节点数,|E|表示边集中元素的个数。如果图中每条边都是没有方向的,称为无向图,如果图中每条边都有方向,则称为有向图。图的常见实现分为:邻接矩阵和邻接表。

二、实现

邻接矩阵

package Algorithm.graph

/*
* 邻接矩阵
*/
public class GraphAdjMatrix {
    private var adjMatrix: Array<Array<Int64>>
    private var numVertices: Int64

    public init(numVertices: Int64) {
        this.numVertices = numVertices
        this.adjMatrix = Array<Array<Int64>>(numVertices, item: Array<Int64>(numVertices, item: 0))
    }
 
    // 添加边
    public func addEdge(i: Int64, j: Int64): Unit {
        // 无向图需要对称设置
        adjMatrix[i][j] = 1
        adjMatrix[j][i] = 1 
    }
 
    // 移除边
    public func removeEdge(i: Int64, j: Int64): Unit {
        // 无向图需要对称设置
        adjMatrix[i][j] = 0
        adjMatrix[j][i] = 0
    }
 
    // 打印邻接矩阵
    public func printMatrix(): Unit {
        for (i in 0..numVertices) {
            for (j in 0..numVertices) {
                print("${adjMatrix[i][j]} ")
            }
            println()
        }
    }
 
    // 检查两个顶点之间是否有边
    public func hasEdge(i: Int64, j: Int64): Bool {
        return adjMatrix[i][j] == 1
    }
}

邻接表

package Algorithm.graph
import std.collection.*

/*
* 节点
*/
class Node{
    //起始点下标
    public var src: Int64
    //终止点下标
    public var dest: Int64
    //权值
    public var weight: Int64
    public var next: Option<Node> = Option<Node>.None

    public Node(src: Int64, dest: Int64, weight: Int64) {
        this.src = src
        this.dest = dest
        this.weight = weight
    }
}

/*
* 邻接表
*/
public class GraphAdjList {
    //顶点集
    private var arrayV: Array<String>
    //是否是有向图
    private var isDirect: Bool
    //存储顶点下标
    private var indexV: HashMap<String, Int64> = HashMap<String, Int64>()
    //存储每个顶点的边结点链表
    private var list: ArrayList<Node>

    public init (size: Int64, isDirect: Bool){
        this.arrayV = Array<String>(size, item: "")
        this.isDirect = isDirect
        //给个初始大小并且置为null,方便后面判断
        this.list = ArrayList<Node>(size)
    }

    /**
     * 初始化顶点集
     */
    public func initArrayV(arrV: Array<String>): Unit {
        for (i in 0..arrV.size) {
            this.arrayV[i] = arrV[i]
            this.indexV.put(arrV[i], i)
        }
    }

    /**
     * 插入边结点到链表中
     */
    public func addEdge(v1: String, v2: String, weight: Int64){
        let src = indexV[v1]
        let dest = indexV[v2]
        addEdgeChild(src, dest, weight)
        //如果是无向图,需要反着再添加一次
        if(!isDirect){
            addEdgeChild(dest, src, weight)
        }
    }

    private func addEdgeChild(src: Int64, dest: Int64, weight: Int64): Unit {
        let node = Node(src, dest, weight)
        //头插入法
        //获取src的链表头位置
        let cur= list.get(src)
        if(cur.isNone()){
            list.set(src, node)
        } else {
            let tmp = list.get(src)
            node.next = tmp
            list.set(src, node)
        }
    }

    public func printGraph(): Unit {
        for (i in 0..arrayV.size) {
            print("${arrayV[i]}-> ")
            var cur = list.get(i)
            while (cur.isSome()) {
                match (cur) {
                    case Some(c) => 
                        print("${c.dest}-> ")
                        cur = c.next
                    case None => return
                }
                
            }
            println("空")
        }
    }
}

三、小结

本章为大家详细的介绍了仓颉数据结构与算法中图的内容,下一章,为大家带来图的遍历。最后,创作不易,如果大家觉得我的文章对学习仓颉数据结构与算法有帮助的话,就动动小手,点个免费的赞吧!收到的赞越多,我的创作动力也会越大哦,谢谢大家🌹🌹🌹!!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

学徒钝子生

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值