【用TypeScript实现内存型图数据库】0x03:实现顶点、边、图的构建

导读

本章节用TypeScript来实现上一章【用TypeScript实现内存型图数据库】0x02:Dagoba内存型图数据库相关的类中提到的Graph,Edge,Vertex三个类。
在程序设计时,先设计好哪个功能由哪个类实现,思路会更清晰,实现出来的代码也会更具备“高内聚,低耦合”的特性。
在逆向根据代码推理设计的时候也是如此,通过代码理出类图,可以对提高对整体的理解程度,加速从代码逆向理解设计。

VertexEdge

首先从这两个基本元素类开始,因为Graph类依赖这两个类,但VertexEdge不依赖Vertex

类图

这两个类的类图为:

1
n
1
2
Vertex
+string id
+Edge[] outEdges
+Edge[] inEdges
Edge
+Vertex inVertex
+Vertex outVertex

代码实现

对应的TS代码实现为:

/**
 * 边
 */
class Edge {
    inVertex: Vertex | undefined;
    outVertex: Vertex | undefined;
}

/**
 * 顶点
 */
class Vertex {
    id: string;
    inEdges: Edge[] = [];
    outEdges: Edge[] = [];

    constructor(id: string) {
        this.id = id;
    }
}

另外还有其对应的函数参数,在后面Graph的方法中会用到:

// 顶点参数
type VertexParam = { id: string };
// 边参数
type EdgeParam = { in: string, out: string };

Graph

Graph对应的类图为

Graph
+Edge[] edges
+Vertex[] vertices
+Map<string, Vertex> vertexIndex
+number autoid
+addVertices(Vertices[] vertices)
+addEdges(Edges[] edges)
+addVertex(Vertex vertex)
+addEdge(Edge edge)
+findVerticesByIds(string[] ids) : Vertex[]
+findVertexById(string id) : Vertex
+v() : Query
+findVertices()
+searchVertices()
+findInEdges(Vertex vertex) : Edge[]
+findOutEdges(Vertex vertex) : Edge[]
+toString() : string

但本节我们仅实现以下有关图构建的属性和方法:

Graph
+Edge[] edges
+Vertex[] vertices
+Map<string, Vertex> vertexIndex
+number autoid
+addVertices(Vertices[] vertices)
+addEdges(Edges[] edges)
+addVertex(Vertex vertex)
+addEdge(Edge edge)
+findInEdges(Vertex vertex) : Edge[]
+findOutEdges(Vertex vertex) : Edge[]

代码实现

/**
 * 图
 */
class Graph {
    edges: Edge[] = [];
    vertices: Vertex[] = [];
    vertexIndex: Map<string, Vertex> = new Map();
    autoId: number;

    public constructor(vertices: VertexParam[], edges: EdgeParam[]) {
        this.addVertices(vertices);
        this.addEdges(edges);
        this.autoId = 1;
    }

    /**
     * 添加顶点
     * @param verticeParams 顶点列表
     */
    addVertices(verticeParams: VertexParam[]): void {
        verticeParams.forEach(this.addVertex.bind(this));
    }

    /**
     * 添加边
     * @param edgeParams 边参数列表
     */
    addEdges(edgeParams: EdgeParam[]): void {
        edgeParams.forEach(this.addEdge.bind(this));
    }

    /**
     * 添加顶点
     * @param vertexParam 顶点参数
     */
    addVertex(vertexParam: VertexParam): void {
        vertexParam.id = vertexParam.id ? vertexParam.id : `${this.autoId++}`;
        // 如果顶点已存在,则提示异常
        if (this.vertexIndex.has(vertexParam.id)) {
            error('A vertex with that ID already exists');
        }
        const vertex: Vertex = new Vertex(vertexParam.id);
        // 添加顶点进顶点列表
        this.vertices.push(vertex);
        // 添加顶点到检索映射中
        this.vertexIndex.set(vertex.id, vertex);
    }

    /**
     * 添加边
     * @param edgeParam 边参数
     */
    addEdge(edgeParam: EdgeParam): void {
        const edge: Edge = new Edge();
        edge.inVertex = this.findVerticeById(edgeParam.in);
        edge.outVertex = this.findVerticeById(edgeParam.out);
        /* 如果任一顶点不存在则返回,并输出异常信息,但不抛出异常 */
        if (!(edge.inVertex && edge.outVertex)) {
            error("That edge's " + (edge.inVertex ? 'out' : 'in') + " vertex wasn't found");
            return;
        }
        // 往出方向顶点的出边列表中添加边
        edge.outVertex.outEdges.push(edge);
        // 往入方向顶点的出边列表中添加边
        edge.inVertex.inEdges.push(edge);
        this.edges.push(edge);
    }

    /**
     * 根据顶点ID列表找到顶点列表
     * @param ids 顶点ID列表
     * @returns 顶点列表
     */
    findVerticesByIds(ids: string[]): (Vertex | undefined)[] {
        return (ids || []).map(this.findVerticeById);
    }

    /**
     * 根据顶点ID找到顶点
     * @param id 顶点ID
     * @returns 顶点
     */
    findVerticeById(id: string): Vertex | undefined {
        return this.vertexIndex.get(id);
    }
}

export {
    Graph
}

用到的工具方法:

/**
 * 异常输出
 * @param msg 异常消息
 * @returns 否
 */
function error(msg: string): boolean {
    console.error(msg);
    return false;
}

运行

将上述代码放到一个名为Dagoba.ts的文件中,然后新建另一个main.ts作为入口文件进行试运行,以下是main.ts的代码:

import { Graph } from './Dagoba';

const graph: Graph = new Graph(
    [{ id: 'grandpa' }, { id: 'grandma' }, { id: 'father' }, { id: 'mother' }],
    [{ in: 'grandma', out: 'grandpa' }, { in: 'father', out: 'grandma' }, { in: 'mother', out: 'grandma' }]);
console.log(graph);

调试输出的结果,可以看到有生成了一个有4个顶点,3条边的图。
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值