le mie informazioni di contatto
Posta[email protected]
2024-07-12
한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina
Nella rappresentazione della lista concatenata di adiacenza, ogni vertice vvla Esiste una lista collegata e ciascun nodo nella lista collegata rappresenta uno schiavo vvla Bordo iniziale.per calcolare Buono a sapersiGT, dobbiamo attraversare GGG per ciascun bordo di , e invertendo la direzione del bordo, aggiungi a Buono a sapersiGT nell'elenco collegato corrispondente.
Vai all'implementazione della lingua:
package main
import (
"fmt"
)
// Graph 使用邻接链表表示
type Graph struct {
vertices int
adjList map[int][]int
}
// NewGraph 创建一个新的图
func NewGraph(vertices int) *Graph {
return &Graph{
vertices: vertices,
adjList: make(map[int][]int),
}
}
// AddEdge 添加一条边到图中
func (g *Graph) AddEdge(u, v int) {
g.adjList[u] = append(g.adjList[u], v)
}
// Transpose 计算图的转置
func (g *Graph) Transpose() *Graph {
gT := NewGraph(g.vertices)
for u, adj := range g.adjList {
for _, v := range adj {
gT.AddEdge(v, u) // 反转边的方向
}
}
return gT
}
func main() {
g := NewGraph(4)
g.AddEdge(0, 1)
g.AddEdge(0, 2)
g.AddEdge(1, 2)
g.AddEdge(2, 0)
g.AddEdge(2, 3)
gT := g.Transpose()
fmt.Println("Original Graph:")
for u, adj := range g.adjList {
fmt.Printf("%d -> %vn", u, adj)
}
fmt.Println("nTransposed Graph:")
for u, adj := range gT.adjList {
fmt.Printf("%d -> %vn", u, adj)
}
}
complessità temporale:
Nella rappresentazione della matrice di adiacenza, utilizziamo un array bidimensionale per memorizzare le informazioni sui bordi, dove matrix[u][v]
Indica se c'è una linea da uuio arrivare vvla lato.per calcolare Buono a sapersiGT, attraversiamo il triangolo superiore (o il triangolo inferiore, a seconda delle abitudini di rappresentazione della matrice) della matrice e invertiamo la direzione dei bordi, ovvero matrix[u][v]
Il valore è assegnato amatrixT[v][u]
。
Vai all'implementazione della lingua(Versione semplificata, considera solo l'esistenza e non considera i pesi dei bordi):
// 假设使用二维布尔切片表示邻接矩阵
type GraphMatrix [][]bool
// Transpose 计算图的转置
func (g GraphMatrix) Transpose() GraphMatrix {
n := len(g)
gT := make(GraphMatrix, n)
for i := range gT {
gT[i] = make([]bool, n)
}
for i := 0; i < n; i++ {
for j := 0; j < n; j++ {
gT[j][i] = g[i][j] // 反转边的方向
}
}
return gT
}
// 注意:这里没有完整的GraphMatrix类型实现,因为示例仅关注Transpose函数
complessità temporale:
Per un grafo diretto rappresentato da una lista di adiacenza, possiamo aggiungere i vertici adiacenti di ciascun vertice alla lista di adiacenza del vertice trasposto del nuovo grafo attraversando la lista di adiacenza di ciascun vertice. I passaggi specifici sono i seguenti:
Analisi della complessità temporale: richiede l'attraversamento di ciascun vertice del grafico originale O ( ∣ V ∣ ) O(|V|)Lo(∣E∣) Il tempo necessario per attraversare la lista di adiacenza di ciascun vertice è O ( ∣ E ∣ ) O(|E|)Lo(∣E∣) tempo, quindi la complessità temporale totale è O ( ∣ V ∣ + ∣ E ∣ ) O(|V| + |E|)Lo(∣E∣+∣E∣)。
Per un grafo diretto rappresentato da una matrice di adiacenza, possiamo ottenere la matrice di adiacenza di un nuovo grafo trasponendo la matrice di adiacenza del grafo originale. I passaggi specifici sono i seguenti:
Analisi della complessità temporale: richiede l'attraversamento della matrice di adiacenza del grafo originale O( ∣ V ∣ 2 ) O(|V|^2)Lo(∣E∣2) tempo, quindi la complessità temporale totale è O( ∣ V ∣ 2 ) O(|V|^2)Lo(∣E∣2)。
Quello che segue è il codice implementato in linguaggio Go:
// 邻接链表表示的有向图转置
func transposeAdjList(G map[int][]int) map[int][]int {
GT := make(map[int][]int)
for v, neighbors := range G {
for _, u := range neighbors {
GT[u] = append(GT[u], v)
}
}
return GT
}
// 邻接矩阵表示的有向图转置
func transposeAdjMatrix(G [][]int) [][]int {
n := len(G)
GT := make([][]int, n)
for i := range GT {
GT[i] = make([]int, n)
}
for i := 0; i < n; i++ {
for j := 0; j < n; j++ {
GT[j][i] = G[i][j]
}
}
return GT
}
Nella rappresentazione della lista concatenata di adiacenza, possiamo attraversare direttamente l'immagine originale GGGL'elenco delle adiacenze di ciascun nodo viene quindi aggiunto al nuovo grafico dopo aver invertito la direzione di ciascun bordo. Buono a sapersiGTsul nodo corrispondente.
type Graph struct {
Vertices []*Node // 存储图中所有节点的指针
}
type Node struct {
Value int
Adjacent []*Node // 存储与该节点相邻的所有节点的指针
}
func (g *Graph) Transpose() *Graph {
transposed := &Graph{make([]*Node, len(g.Vertices))}
for i, node := range g.Vertices {
transposed.Vertices[i] = &Node{node.Value, make([]*Node, 0)}
}
for _, node := range g.Vertices {
for _, adj := range node.Adjacent {
// 将边反向添加到转置图中
transposed.Vertices[adj.Value].Adjacent = append(transposed.Vertices[adj.Value].Adjacent, transposed.Vertices[node.Value])
}
}
return transposed
}
Pertanto, la complessità temporale totale è O ( ∣ V ∣ + ∣ E ∣ ) O(|V| + |E|)Lo(∣E∣+∣E∣)。
Nella notazione della matrice di adiacenza, possiamo creare una nuova matrice di adiacenza e quindi attraversare l'immagine originale GGGmatrice di adiacenza, ogni elemento della matrice (io, j) (io, j)(ioooo,J)assegnato alla nuova matrice (j, io) (j, io)(J,ioooo)posizione, completando così l'inversione del bordo.
type MatrixGraph struct {
Matrix [][]bool // 存储邻接矩阵
}
func (mg *MatrixGraph) Transpose() *MatrixGraph {
transposed := &MatrixGraph{make([][]bool, len(mg.Matrix))}
for i := range mg.Matrix {
transposed.Matrix[i] = make([]bool, len(mg.Matrix))
for j := range mg.Matrix[i] {
// 将边反向赋值到转置矩阵中
transposed.Matrix[i][j] = mg.Matrix[j][i]
}
}
return transposed
}
Pertanto, la complessità temporale totale è O( ∣ V ∣ 2 ) O(|V|^2)Lo(∣E∣2)。
Per la rappresentazione della lista concatenata di adiacenza, la complessità temporale dell'algoritmo di trasposizione è O ( ∣ V ∣ + ∣ E ∣ ) O(|V| + |E|)Lo(∣E∣+∣E∣), e per la rappresentazione della matrice di adiacenza, la complessità temporale dell'algoritmo di trasposizione è O( ∣ V ∣ 2 ) O(|V|^2)Lo(∣E∣2) .Nelle applicazioni pratiche, se il grafico è relativamente scarno (es. ∣ E ∣ |E|∣E∣molto più piccolo di ∣ V ∣ 2 |V|^2∣E∣2 ), sarebbe più efficiente utilizzare la rappresentazione della lista concatenata di adiacenza.Se il grafico è denso (es. ∣ E ∣ |E|∣E∣vicino ∣ V ∣ 2 |V|^2∣E∣2), allora la rappresentazione della matrice di adiacenza potrebbe essere più appropriata.
Nella rappresentazione grafica, gli elenchi collegati di adiacenza e le matrici di adiacenza sono entrambi metodi comunemente usati. Le liste collegate di adiacenza vengono utilizzate per rappresentare i grafi non orientati e diretti, mentre le matrici di adiacenza vengono solitamente utilizzate per rappresentare i grafi non orientati. Per la trasposizione di un grafo orientato possiamo operare separatamente sulla lista concatenata di adiacenza e sulla matrice di adiacenza.
Per un grafo diretto rappresentato da una lista concatenata di adiacenza, la trasposizione del grafo può essere ottenuta attraversando ciascun vertice del grafo originale e modificando i bordi in uscita del grafo originale in bordi in entrata.
package main
import (
"fmt"
)
// 定义图的顶点结构
type Vertex struct {
Name string
Edges []*Vertex
Visited bool
}
// 计算图的转置
func Transpose(g *Vertex) {
for _, v := range g.Edges {
// 遍历顶点v的所有出边
for _, w := range v.Edges {
// 在原图中查找顶点w指向顶点v的边,并反转
for i, e := range w.Edges {
if e == v {
w.Edges[i] = v
break
}
}
}
}
}
func main() {
// 创建顶点
a := &Vertex{Name: "A"}
b := &Vertex{Name: "B"}
c := &Vertex{Name: "C"}
// 建立有向图关系
a.Edges = []*Vertex{b, c}
b.Edges = []*Vertex{a}
c.Edges = []*Vertex{a}
// 打印原图
fmt.Println("原图:")
PrintGraph(a)
// 计算转置图
Transpose(a)
// 打印转置图
fmt.Println("转置图:")
PrintGraph(a)
}
// PrintGraph 用于打印图的邻接链表表示
func PrintGraph(g *Vertex) {
g.Visited = true
for _, v := range g.Edges {
if !v.Visited {
fmt.Println(g.Name, "->", v.Name)
PrintGraph(v)
}
}
}
Per un grafo diretto rappresentato da una matrice di adiacenza, la trasposizione del grafo può essere ottenuta trasformando ciascuna riga del grafo originale nella colonna corrispondente del nuovo grafo.
package main
import (
"fmt"
)
// 计算邻接矩阵的转置
func TransposeMatrix(mat [][]int) [][]int {
transposed := make([][]int, len(mat[0]))
for i := range transposed {
transposed[i] = make([]int, len(mat))
}
for i, row := range mat {
for j, val := range row {
if val == 1 {
transposed[j][i] = 1
}
}
}
return transposed
}
func main() {
// 创建邻接矩阵
originalMatrix := [][]int{
{0, 1, 1},
{0, 0, 1},
{1, 0, 0},
}
// 计算转置矩阵
transposedMatrix := TransposeMatrix(originalMatrix)
// 打印转置矩阵
fmt.Println("转置矩阵:")
for _, row := range transposedMatrix {
fmt.Println(row)
}
}
Per la trasposizione di una lista concatenata di adiacenza, la complessità temporale dell'algoritmo è O(E), dove E è il numero di archi nel grafico. Questo perché ogni bordo deve essere attraversato una volta.
Per la trasposizione della matrice di adiacenza, la complessità temporale dell'algoritmo è O(V^2), dove V è il numero di vertici nel grafico. Questo perché ogni elemento della matrice deve essere attraversato una volta e la dimensione della matrice è V×V.
Questi algoritmi sono tutti efficienti e funzionano
Implementare un algoritmo per calcolare un grafo orientato GGG trasposizione di Buono a sapersiGT , possiamo elaborare rispettivamente le due rappresentazioni della lista concatenata di adiacenza e della matrice di adiacenza. Di seguito descriverò rispettivamente gli algoritmi per questi due casi e fornirò esempi di codice in linguaggio Go.
newAdjList
Utilizzato per memorizzare il grafico trasposto.adjList
。(u, v)
, aggiungilo a newAdjList[v]
mezzo.newAdjList
。type Graph struct {
vertices []*Vertex
}
type Vertex struct {
key int
adjacent []*Vertex
}
func (g *Graph) Transpose() *Graph {
gt := &Graph{make([]*Vertex, len(g.vertices))}
for i := range g.vertices {
gt.vertices[i] = &Vertex{key: i}
}
for _, u := range g.vertices {
for _, v := range u.adjacent {
// Add edge (v, u) to the transpose graph.
gt.vertices[v.key].adjacent = append(gt.vertices[v.key].adjacent, gt.vertices[u.key])
}
}
return gt
}
Il tempo di esecuzione di questo algoritmo è O(|V| + |E|), dove |V| è il numero di vertici e |E| è il numero di archi. Questo perché dobbiamo attraversare tutti i vertici e i bordi una volta.
newAdjMatrix
Utilizzato per memorizzare il grafico trasposto.adjMatrix
。adjMatrix[i][j]
, assegnalo a newAdjMatrix[j][i]
。newAdjMatrix
。type Graph struct {
matrix [][]bool
}
func (g *Graph) Transpose() *Graph {
gt := &Graph{make([][]bool, len(g.matrix))}
for i := range gt.matrix {
gt.matrix[i] = make([]bool, len(g.matrix))
}
for i := range g.matrix {
for j := range g.matrix[i] {
// Copy the adjacency values with swapped indices.
gt.matrix[j][i] = g.matrix[i][j]
}
}
return gt
}
Il tempo di esecuzione di questo algoritmo è O(|V|^2), dove |V| è il numero di vertici. Questo perché dobbiamo attraversare l'intera matrice di adiacenza e la dimensione della matrice di adiacenza è |V|
L'esempio di codice sopra è solo la parte principale dell'algoritmo. Nelle applicazioni reali, potrebbe essere necessario aggiungere altre funzioni come la gestione degli errori, l'input e l'output. Inoltre, per semplificare il codice, si assume che non vi siano archi ripetuti nel grafico e che i numeri dei vertici siano numerati consecutivamente a partire da 0.
Quello che segue è un algoritmo scritto in linguaggio Go per calcolare G ^ T dal grafico G, e vengono forniti anche i corrispondenti metodi di rappresentazione della lista concatenata di adiacenza e della matrice di adiacenza:
package main
import "fmt"
// 图的节点结构体
type Node struct {
Value int // 节点的值
Next *Node // 下一个节点指针
}
// 邻接链表表示法的图结构体
type Graph struct {
Vertices []*Node // 图中所有节点的数组
}
// 添加有向边到邻接链表
func (g *Graph) AddEdge(u, v int) {
newNode := &Node{Value: v}
if g.Vertices[u] == nil {
g.Vertices[u] = newNode
} else {
curr := g.Vertices[u]
for curr.Next != nil {
curr = curr.Next
}
curr.Next = newNode
}
}
// 输出邻接链表表示的图信息
func (g *Graph) Print() {
for i, node := range g.Vertices {
fmt.Printf("顶点 %d:", i)
for node != nil {
fmt.Printf("%d ", node.Value)
node = node.Next
}
fmt.Println()
}
}
// 获取图 G 的转置图 G^T 的邻接链表表示法
func GetTranspose(g *Graph) *Graph {
transpose := &Graph{
Vertices: make([]*Node, len(g.Vertices)),
}
for i, node := range g.Vertices {
for node != nil {
v := node.Value
// 在转置图中添加反向边
transpose.AddEdge(v, i)
node = node.Next
}
}
return transpose
}
// 输出邻接链表表示的转置图信息
func PrintTranspose(g *Graph) {
fmt.Println("转置图 G^T:")
g.Print()
}
// 邻接矩阵表示法的图结构体
type Matrix struct {
Vertices [][]int // 邻接矩阵,存储边的连接关系(0 表示无边,1 表示有边)
}
// 初始化邻接矩阵表示的图
func InitMatrix(numVertices int) *Matrix {
matrix := &Matrix{
Vertices: make([][]int, numVertices),
}
for i := range matrix.Vertices {
matrix.Vertices[i] = make([]int, numVertices)
}
return matrix
}
// 添加有向边到邻接矩阵
func (m *Matrix) AddEdge(u, v int) {
m.Vertices[u][v] = 1
}
// 获取图 G 的转置图 G^T 的邻接矩阵表示法
func GetTransposeMatrix(m *Matrix) *Matrix {
numRows := len(m.Vertices)
numCols := len(m.Vertices[0])
transpose := InitMatrix(numRows)
for i := 0; i < numRows; i++ {
for j := 0; j < numCols; j++ {
if m.Vertices[i][j] == 1 {
// 在转置矩阵中添加反向边
transpose.AddEdge(j, i)
}
}
}
return transpose
}
// 输出邻接矩阵表示的转置图信息
func PrintTransposeMatrix(m *Matrix) {
numRows := len(m.Vertices)
numCols := len(m.Vertices[0])
fmt.Println("转置图 G^T:")
for i := 0; i < numRows; i++ {
fmt.Printf("顶点 %d:", i)
for j := 0; j < numCols; j++ {
if m.Vertices[i][j] == 1 {
fmt.Printf("%d ", j)
}
}
fmt.Println()
}
}
func main() {
// 邻接链表表示的有向图 G
g := &Graph{
Vertices: make([]*Node, 4),
}
g.AddEdge(0, 1)
g.AddEdge(1, 2)
g.AddEdge(2, 3)
g.AddEdge(3, 1)
// 输出原始图 G 的邻接链表表示法
fmt.Println("原始图 G:")
g.Print()
// 获取转置图 G^T 的邻接链表表示法并输出
transpose := GetTranspose(g)
PrintTranspose(transpose)
// 邻接矩阵表示的有向图 G
m := InitMatrix(4)
m.AddEdge(0, 1)
m.AddEdge(1, 2)
m.AddEdge(2, 3)
m.AddEdge(3, 1)
// 输出原始图 G 的邻接矩阵表示法
fmt.Println("原始图 G:")
for _, row := range m.Vertices {
fmt.Println(row)
}
// 获取转置图 G^T 的邻接矩阵表示法并输出
transposeMatrix := GetTransposeMatrix(m)
PrintTransposeMatrix(transposeMatrix)
}
La complessità temporale di questo algoritmo è O(V + E), dove V è il numero di vertici ed E è il numero di archi. Il processo di costruzione del grafo trasposto richiede l'attraversamento di tutti gli spigoli del grafo originale e l'aggiunta degli stessi al grafo trasposto al contrario, quindi la complessità temporale totale è proporzionale al numero di vertici e spigoli.
I grafi trasposti di grafi diretti possono essere rappresentati da due strutture dati principali: liste collegate di adiacenza e matrici di adiacenza. Di seguito presenterò rispettivamente gli algoritmi in questi due casi e fornirò codice di esempio in linguaggio Go.
Per un grafico rappresentato da una lista concatenata di adiacenza, possiamo trasporre il grafico attraversando la lista di adiacenza di ciascun vertice e quindi aggiungendo un bordo inverso a ciascun punto di adiacenza. La complessità temporale di questo metodo è O(V + E), dove V è il numero di vertici ed E è il numero di spigoli.
type Vertex struct {
Value int
Adj []Vertex
}
func transposeGraph(graph []Vertex) []Vertex {
transposed := make([]Vertex, len(graph))
for _, v := range graph {
for _, adjV := range v.Adj {
// 为邻接点添加反向边
found := false
for _, tV := range transposed[adjV.Value].Adj {
if tV.Value == v.Value {
found = true
break
}
}
if !found {
transposed[adjV.Value].Adj = append(transposed[adjV.Value].Adj, v)
}
}
}
return transposed
}
Per un grafico rappresentato da una matrice di adiacenza, possiamo implementare la trasposizione scambiando le righe e le colonne della matrice. La complessità temporale di questo metodo è O(V^2).
func transposeMatrix(matrix [][]int) [][]int {
n := len(matrix)
transposed := make([][]int, n)
for i := 0; i < n; i++ {
transposed[i] = make([]int, n)
for j := 0; j < n; j++ {
transposed[i][j] = matrix[j][i]
}
}
return transposed
}
Nelle applicazioni pratiche, quale algoritmo scegliere dipende dalla scarsità del grafico e dalla memoria disponibile. Per i grafi sparsi, le liste collegate di adiacenza possono essere più efficienti in termini di memoria; per i grafi densi, le matrici di adiacenza possono essere più efficienti.
Calcolare un grafico orientato G = ( V , E ) G=(V,E)G=(E,E) trasposizione di GT = ( V , ET ) G^T=(V,E^T)GT=(E,ET), possiamo fornire algoritmi corrispondenti per i due metodi di rappresentazione rispettivamente della lista concatenata di adiacenza e della matrice di adiacenza, e analizzare il loro tempo di esecuzione.
type Edge struct {
dest int
}
type AdjacencyList struct {
edges map[int][]Edge
}
func TransposeGraph(graph AdjacencyList) AdjacencyList {
transposed := AdjacencyList{edges: make(map[int][]Edge)}
for u, neighbors := range graph.edges {
for _, edge := range neighbors {
v := edge.dest
transposed.edges[v] = append(transposed.edges[v], Edge{dest: u})
}
}
return transposed
}
func main() {
// 示例图的邻接链表表示
graph := AdjacencyList{edges: map[int][]Edge{
0: {{dest: 1}},
1: {{dest: 2}},
2: {{dest: 0}},
}}
// 计算转置图
transposedGraph := TransposeGraph(graph)
// 打印转置图的邻接链表
for u, neighbors := range transposedGraph.edges {
fmt.Printf("Node %d -> Nodes: ", u)
for _, edge := range neighbors {
fmt.Printf("%d ", edge.dest)
}
fmt.Println()
}
}
In questo codice definiamo a Edge
struttura per rappresentare i bordi e aAdjacencyList
Struttura per rappresentare una lista collegata di adiacenza.TransposeGraph
La funzione accetta aAdjacencyList
parametro di tipo e restituisce una rappresentazione di lista concatenata di adiacenza del suo grafico trasposto.esisteremain
funzione, creiamo un grafico di esempio, calcoliamo e stampiamo il suo grafico trasposto.