optimize topologic graph and add delete node func
This commit is contained in:
parent
dd67dd5462
commit
945669c85e
|
|
@ -1,54 +1,151 @@
|
|||
package diagram
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"sync"
|
||||
|
||||
"github.com/gofrs/uuid"
|
||||
)
|
||||
|
||||
// Graph represents a topological structure using an adjacency list
|
||||
type Graph struct {
|
||||
vertices map[string][]string
|
||||
sync.RWMutex
|
||||
// 根节点
|
||||
rootVertex uuid.UUID
|
||||
// 游离节点
|
||||
freeVertexs map[string]struct{}
|
||||
verticeLinks map[string][]uuid.UUID
|
||||
// 存储多个上级节点同时指向同一下级节点的情况,key为下级节点,value为上级节点集合
|
||||
backLinks map[string][]uuid.UUID
|
||||
}
|
||||
|
||||
// NewGraph creates a new graph
|
||||
// TODO 修改结构为map[uuid][]orm.Topologic
|
||||
func NewGraph() *Graph {
|
||||
func NewGraph(root uuid.UUID) *Graph {
|
||||
return &Graph{
|
||||
vertices: make(map[string][]string),
|
||||
rootVertex: root,
|
||||
freeVertexs: make(map[string]struct{}),
|
||||
verticeLinks: make(map[string][]uuid.UUID),
|
||||
backLinks: make(map[string][]uuid.UUID),
|
||||
}
|
||||
}
|
||||
|
||||
// AddVertex adds a vertex to the graph
|
||||
func (g *Graph) AddVertex(vertex string) {
|
||||
if _, exists := g.vertices[vertex]; !exists {
|
||||
g.vertices[vertex] = []string{}
|
||||
// AddNode adds a node to the graph
|
||||
func (g *Graph) AddNode(vertex string) {
|
||||
if _, exists := g.verticeLinks[vertex]; !exists {
|
||||
g.verticeLinks[vertex] = []uuid.UUID{}
|
||||
}
|
||||
}
|
||||
|
||||
// AddEdge adds an edge between two vertices
|
||||
func (g *Graph) AddEdge(from, to string) {
|
||||
g.AddVertex(from)
|
||||
g.AddVertex(to)
|
||||
g.vertices[from] = append(g.vertices[from], to)
|
||||
// CreateBackLink adds a node to the graph
|
||||
func (g *Graph) CreateBackLink(vertex string) {
|
||||
if _, exists := g.backLinks[vertex]; !exists {
|
||||
g.backLinks[vertex] = []uuid.UUID{}
|
||||
}
|
||||
}
|
||||
|
||||
// AddEdge adds an edge between two verticeLinks
|
||||
func (g *Graph) AddEdge(from, to uuid.UUID) {
|
||||
g.Lock()
|
||||
defer g.Unlock()
|
||||
|
||||
fromKey := from.String()
|
||||
toKey := to.String()
|
||||
|
||||
g.CreateBackLink(toKey)
|
||||
g.backLinks[toKey] = append(g.backLinks[toKey], from)
|
||||
|
||||
g.AddNode(fromKey)
|
||||
g.AddNode(toKey)
|
||||
g.verticeLinks[fromKey] = append(g.verticeLinks[fromKey], to)
|
||||
|
||||
// 创建新的拓扑信息时,如果被链接的点已经存在于游离节点中
|
||||
// 则将其移除
|
||||
if _, exist := g.freeVertexs[toKey]; exist {
|
||||
delete(g.freeVertexs, toKey)
|
||||
}
|
||||
}
|
||||
|
||||
// DelNode delete a node to the graph
|
||||
func (g *Graph) DelNode(vertex string) error {
|
||||
childNodes, exists := g.verticeLinks[vertex]
|
||||
if exists {
|
||||
if len(childNodes) > 1 {
|
||||
return errors.New("delete node failed,that vertex contains more than one child node")
|
||||
}
|
||||
delete(g.verticeLinks, vertex)
|
||||
}
|
||||
|
||||
parentNodes, exists := g.backLinks[vertex]
|
||||
if exists {
|
||||
if len(parentNodes) > 1 {
|
||||
return errors.New("delete node failed,that vertex contains more than one parent node")
|
||||
}
|
||||
delete(g.backLinks, vertex)
|
||||
} else {
|
||||
return errors.New("that vertex don't have parent node")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// DelEdge delete an edge between two verticeLinks
|
||||
func (g *Graph) DelEdge(from, to uuid.UUID) error {
|
||||
g.Lock()
|
||||
defer g.Unlock()
|
||||
|
||||
toKey := to.String()
|
||||
var fromKeys []uuid.UUID
|
||||
if _, exist := g.backLinks[toKey]; exist {
|
||||
fromKeys = g.backLinks[toKey]
|
||||
} else {
|
||||
fromKeys = []uuid.UUID{from}
|
||||
}
|
||||
|
||||
childvertex := g.verticeLinks[toKey]
|
||||
err := g.DelNode(toKey)
|
||||
if err != nil {
|
||||
return fmt.Errorf("delete edge failed: %w", err)
|
||||
}
|
||||
|
||||
for _, fromUUID := range fromKeys {
|
||||
fromKey := fromUUID.String()
|
||||
var delIndex int
|
||||
for index, vertex := range g.verticeLinks[fromKey] {
|
||||
if vertex == to {
|
||||
delIndex = index
|
||||
}
|
||||
}
|
||||
vertex := g.verticeLinks[fromKey]
|
||||
copy(vertex[delIndex:], vertex[delIndex+1:])
|
||||
vertex = vertex[:len(vertex)-1]
|
||||
g.verticeLinks[fromKey] = vertex
|
||||
}
|
||||
|
||||
fromKey := from.String()
|
||||
g.verticeLinks[fromKey] = append(g.verticeLinks[fromKey], childvertex...)
|
||||
return nil
|
||||
}
|
||||
|
||||
// PrintGraph prints the graph in adjacency list format
|
||||
func (g *Graph) PrintGraph() {
|
||||
for vertex, edges := range g.vertices {
|
||||
g.RLock() // 读锁
|
||||
defer g.RUnlock()
|
||||
for vertex, edges := range g.verticeLinks {
|
||||
fmt.Printf("%s -> %v\n", vertex, edges)
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
graph := NewGraph()
|
||||
// func main() {
|
||||
// graph := NewGraph()
|
||||
|
||||
// Add vertices and edges
|
||||
graph.AddEdge("A", "B")
|
||||
graph.AddEdge("A", "C")
|
||||
graph.AddEdge("B", "D")
|
||||
graph.AddEdge("C", "D")
|
||||
graph.AddEdge("C", "E")
|
||||
graph.AddEdge("E", "F")
|
||||
// // Add verticeLinks and edges
|
||||
// graph.AddEdge("A", "B")
|
||||
// graph.AddEdge("A", "C")
|
||||
// graph.AddEdge("B", "D")
|
||||
// graph.AddEdge("C", "D")
|
||||
// graph.AddEdge("C", "E")
|
||||
// graph.AddEdge("E", "F")
|
||||
|
||||
// Print the graph
|
||||
graph.PrintGraph()
|
||||
}
|
||||
// // Print the graph
|
||||
// graph.PrintGraph()
|
||||
// }
|
||||
|
|
|
|||
Loading…
Reference in New Issue