Compartir tecnología

Wen Xin Yi Yan VS iFlytek Spark VS chatgpt (300) - Introducción a los algoritmos 22.1 4 preguntas

2024-07-12

한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina

4. Dadas varias imágenes G = (V, E) G=(V, E)GRAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMO=(V,mi)lista enlazada de adyacencia (multigraph es un gráfico que permite bordes repetidos y bordes de bucle automático), proporcione un tiempo de O ( V + E ) O(V+E)Ohhhhhhhhhhhhhhhhhhhh(V+mi)algoritmo, utilizado para calcular el gráfico no dirigido "equivalente" del gráfico G′=(V,E′) G^{'}=(V,E^{'})GRAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMO=(V,mi) representado por una lista enlazada de adyacencia.aquí mi ′ E^{'}miSerá EEmi Los bordes redundantes y los bordes restantes después de eliminar los bordes del bucle automático. Eliminar los bordes restantes se refiere a reemplazar múltiples bordes entre dos nodos con un borde. Si desea escribir código, utilice el idioma go.

Palabras de Wen Xin:

Representación de lista enlazada de adyacencia

En la representación de lista enlazada de adyacencia, cada vértice Verboen Hay una lista vinculada y cada nodo en la lista vinculada representa un esclavo Verboen Borde inicial.para calcular GiganteGRAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMOyo, necesitamos atravesar GGGRAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMO para cada borde de, e invirtiendo la dirección del borde, agregue a GiganteGRAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMOyo en la lista enlazada correspondiente.

Ir a la implementación del lenguaje

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)
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56

complejidad del tiempo

  • La complejidad temporal de atravesar cada borde es O ( E ) O(E)Ohhhhhhhhhhhhhhhhhhhh(mi),en EEmi es el número de aristas.
  • Para cada borde, realizamos una operación de tiempo constante (agregándola a la lista de adyacencia de otro gráfico).
  • Por lo tanto, la complejidad del tiempo total es O ( E ) O(E)Ohhhhhhhhhhhhhhhhhhhh(mi)

Representación de matriz de adyacencia

En la representación de matriz de adyacencia, utilizamos una matriz bidimensional para almacenar información de borde, donde matrix[u][v] Indica si hay una línea desde uu llegar Verboen lado.para calcular GiganteGRAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMOyo, atravesamos el triángulo superior (o el triángulo inferior, dependiendo de sus hábitos de representación matricial) de la matriz e invertimos la dirección de los bordes, es decir, matrix[u][v] El valor se asigna amatrixT[v][u]

Ir a la implementación del lenguaje(Versión simplificada, solo considera la existencia y no considera los pesos de los bordes):

// 假设使用二维布尔切片表示邻接矩阵
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函数
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

complejidad del tiempo

  • Iterar sobre cada elemento de la matriz requiere O ( V 2 ) O(V^2)Ohhhhhhhhhhhhhhhhhhhh(V2) tiempo, entre los cuales VVV es el número de vértices.
  • Por lo tanto, la complejidad del tiempo total es O ( V 2 ) O(V^2)Ohhhhhhhhhhhhhhhhhhhh(V2) . Puede que esto no sea lo más eficiente cuando el número de vértices es mucho mayor que el número de aristas.

Insertar descripción de la imagen aquí

Insertar descripción de la imagen aquí

Insertar descripción de la imagen aquí

Insertar descripción de la imagen aquí

chispa iFlytek:

Para un gráfico dirigido representado por una lista de adyacencia, podemos agregar los vértices adyacentes de cada vértice a la lista de adyacencia del vértice transpuesto del nuevo gráfico atravesando la lista de adyacencia de cada vértice. Los pasos específicos son los siguientes:

  1. Crear una nueva lista de adyacencia GTA^{T}GRAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMOyo, inicializado para vaciar.
  2. Recorrer la imagen original. GGGRAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMO cada vértice de Verboen
  3. Atravesar vértices Verboen lista enlazada de adyacencia, cada vértice adyacente uu Agregar a nueva imagen GTA^{T}GRAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMOyo vértice medio Verboen en la lista enlazada de adyacencia.
  4. Volver a la nueva imagen GTA^{T}GRAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMOyo

Análisis de complejidad del tiempo: atravesar cada vértice del gráfico original requiere O ( ∣ V ∣ ) O(|V|)Ohhhhhhhhhhhhhhhhhhhh(V) El tiempo necesario para recorrer la lista de adyacencia de cada vértice es O ( ∣ E ∣ ) O(|E|)Ohhhhhhhhhhhhhhhhhhhh(mi) tiempo, por lo que la complejidad del tiempo total es O ( ∣ V ∣ + ∣ E ∣ ) O(|V| + |E|)Ohhhhhhhhhhhhhhhhhhhh(V+mi)

Para un gráfico dirigido representado por una matriz de adyacencia, podemos obtener la matriz de adyacencia de un nuevo gráfico transponiendo la matriz de adyacencia del gráfico original. Los pasos específicos son los siguientes:

  1. Crea uno nuevo con tamaño ∣ V ∣ × ∣ V ∣ |V| veces |V|V×V matriz GTA^{T}GRAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMOyo, inicializado en una matriz todo cero.
  2. Recorrer la matriz de adyacencia de la imagen original. GGGRAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMO,Voluntad G[i][j] G[i][j]GRAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMO[i][yo] El valor se asigna a GT[j][i] G^{T}[j][i]GRAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMOyo[yo][i]
  3. Devuelve la matriz de adyacencia del nuevo gráfico. GTA^{T}GRAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMOyo

Análisis de complejidad temporal: atravesar la matriz de adyacencia del gráfico original requiere O ( ∣ V ∣ 2 ) O(|V|^2)Ohhhhhhhhhhhhhhhhhhhh(V2) tiempo, por lo que la complejidad del tiempo total es O ( ∣ V ∣ 2 ) O(|V|^2)Ohhhhhhhhhhhhhhhhhhhh(V2)

El siguiente es el código implementado en lenguaje 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
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25

Cerebro inteligente 360:

Representación de lista enlazada de adyacencia

En la representación de la lista vinculada de adyacencia, podemos atravesar directamente la imagen original. GGGRAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMOLuego, la lista de adyacencia de cada nodo se agrega al nuevo gráfico después de invertir la dirección de cada borde. GTA^{T}GRAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMOyoen el nodo correspondiente.

Ir a la implementación del código de idioma:
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
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
Análisis de complejidad del tiempo:
  • Recorre cada nodo en el gráfico original: O ( ∣ V ∣ ) O(|V|)Ohhhhhhhhhhhhhhhhhhhh(V)
  • Recorra la lista de adyacencia de cada nodo: O ( ∣ E ∣ ) O(|E|)Ohhhhhhhhhhhhhhhhhhhh(mi)

Por lo tanto, la complejidad del tiempo total es O ( ∣ V ∣ + ∣ E ∣ ) O(|V| + |E|)Ohhhhhhhhhhhhhhhhhhhh(V+mi)

Notación matricial de adyacencia

En la notación de matriz de adyacencia, podemos crear una nueva matriz de adyacencia y luego recorrer la imagen original. GGGRAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMOmatriz de adyacencia, cada elemento de la matriz (yo, j) (yo, j)(i,yo)asignado a la nueva matriz (j, yo) (j, yo)(yo,i)posición, completando así la inversión del borde.

Ir a la implementación del código de idioma:
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
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
Análisis de complejidad del tiempo:
  • Cree una nueva matriz de adyacencia: O ( ∣ V ∣ 2 ) O(|V|^2)Ohhhhhhhhhhhhhhhhhhhh(V2)
  • Recorre la matriz de adyacencia de la imagen original: O ( ∣ V ∣ 2 ) O(|V|^2)Ohhhhhhhhhhhhhhhhhhhh(V2)

Por lo tanto, la complejidad del tiempo total es O ( ∣ V ∣ 2 ) O(|V|^2)Ohhhhhhhhhhhhhhhhhhhh(V2)

Resumir

Para la representación de la lista enlazada de adyacencia, la complejidad temporal del algoritmo de transposición es O ( ∣ V ∣ + ∣ E ∣ ) O(|V| + |E|)Ohhhhhhhhhhhhhhhhhhhh(V+mi), y para la representación de la matriz de adyacencia, la complejidad temporal del algoritmo de transposición es O ( ∣ V ∣ 2 ) O(|V|^2)Ohhhhhhhhhhhhhhhhhhhh(V2) .En aplicaciones prácticas, si el gráfico es relativamente disperso (es decir, ∣ mi ∣ |mi|mimucho más pequeño que ∣ V ∣ 2 |V|^2V2 ), sería más eficiente utilizar la representación de lista vinculada de adyacencia.Si el gráfico es denso (es decir, ∣ mi ∣ |mi|micerca ∣ V ∣ 2 |V|^2V2), entonces la representación de la matriz de adyacencia puede ser más apropiada.

Palabras claras del espectro de sabiduría:

En la representación de gráficos, las listas enlazadas de adyacencia y las matrices de adyacencia son métodos comúnmente utilizados. Las listas enlazadas de adyacencia se utilizan para representar gráficos dirigidos y no dirigidos, mientras que las matrices de adyacencia se utilizan generalmente para representar gráficos no dirigidos. Para la transposición de un gráfico dirigido, podemos operar con la lista enlazada de adyacencia y la matriz de adyacencia por separado.

Transposición de lista enlazada de adyacencia

Para un gráfico dirigido representado por una lista enlazada de adyacencia, la transposición del gráfico se puede lograr atravesando cada vértice del gráfico original y modificando los bordes salientes del gráfico original en bordes entrantes.

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)
		}
	}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53

Transpuesta de matriz de adyacencia

Para un gráfico dirigido representado por una matriz de adyacencia, la transposición del gráfico se puede lograr convirtiendo cada fila del gráfico original en la columna correspondiente del nuevo gráfico.

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)
	}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34

Análisis del tiempo de ejecución del algoritmo.

  1. Para la transposición de una lista enlazada de adyacencia, la complejidad temporal del algoritmo es O (E), donde E es el número de aristas en el gráfico. Esto se debe a que cada borde debe atravesarse una vez.

  2. Para la transpuesta de la matriz de adyacencia, la complejidad temporal del algoritmo es O(V^2), donde V es el número de vértices del gráfico. Esto se debe a que cada elemento de la matriz debe atravesarse una vez y el tamaño de la matriz es V × V.
    Todos estos algoritmos son eficientes y se ejecutan.

Tiangong:

Implementar un algoritmo para calcular un gráfico dirigido. GGGRAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMO transposición de GTA^{T}GRAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMOyo , podemos procesar las dos representaciones de la lista enlazada de adyacencia y la matriz de adyacencia respectivamente. A continuación, describiré los algoritmos para estos dos casos respectivamente y proporcionaré ejemplos de código en lenguaje Go.

Representación de lista enlazada de adyacencia

Pasos del algoritmo:
  1. Crear una nueva lista de adyacencia newAdjList Se utiliza para almacenar el gráfico transpuesto.
  2. Recorrer la lista vinculada de adyacencia de la imagen original adjList
  3. para cada borde (u, v), añádelo a newAdjList[v] medio.
  4. Devuelve la nueva lista de adyacencia newAdjList
Ir ejemplo de código de idioma:
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
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
Análisis de tiempo de ejecución:

El tiempo de ejecución de este algoritmo es O(|V| + |E|), donde |V| es el número de vértices y |E| Esto se debe a que necesitamos atravesar todos los vértices y aristas una vez.

Notación matricial de adyacencia

Pasos del algoritmo:
  1. Crear una nueva matriz de adyacencia newAdjMatrix Se utiliza para almacenar el gráfico transpuesto.
  2. Recorrer la matriz de adyacencia de la imagen original. adjMatrix
  3. para cada elemento adjMatrix[i][j], asígnalo a newAdjMatrix[j][i]
  4. Devuelve la nueva matriz de adyacencia newAdjMatrix
Ir ejemplo de código de idioma:
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
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
Análisis de tiempo de ejecución:

El tiempo de ejecución de este algoritmo es O(|V|^2), donde |V| es el número de vértices. Esto se debe a que necesitamos atravesar toda la matriz de adyacencia y el tamaño de la matriz de adyacencia es |V x |V|.

El ejemplo de código anterior es solo la parte central del algoritmo. En aplicaciones reales, es posible que sea necesario agregar otras funciones, como manejo de errores, entrada y salida. Además, para simplificar el código, se supone que no hay aristas repetidas en el gráfico y que los números de los vértices se numeran consecutivamente comenzando desde 0.

chatgpt:

El siguiente es un algoritmo escrito en lenguaje Go para calcular G^T a partir del gráfico G, y también se proporcionan los métodos de representación de matriz de adyacencia y lista enlazada de adyacencia correspondientes:

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)
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164

La complejidad temporal de este algoritmo es O (V + E), donde V es el número de vértices y E es el número de aristas. El proceso de construcción del gráfico transpuesto requiere atravesar todos los bordes del gráfico original y agregarlos al gráfico transpuesto a la inversa, por lo que la complejidad del tiempo total es proporcional al número de vértices y aristas.

yo:

Los gráficos transpuestos de gráficos dirigidos se pueden representar mediante dos estructuras de datos principales: listas enlazadas de adyacencia y matrices de adyacencia. A continuación, presentaré los algoritmos en estos dos casos respectivamente y proporcionaré un código de muestra en lenguaje Go.

Representación de lista enlazada de adyacencia

Para un gráfico representado por una lista enlazada de adyacencia, podemos transponer el gráfico atravesando la lista de adyacencia de cada vértice y luego agregando un borde inverso a cada punto de adyacencia. La complejidad temporal de este método es O (V + E), donde V es el número de vértices y E es el número de aristas.

Ir código de muestra de idioma:
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
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

Representación de matriz de adyacencia

Para un gráfico representado por una matriz de adyacencia, podemos implementar la transposición intercambiando las filas y columnas de la matriz. La complejidad temporal de este método es O (V ^ 2).

Ir código de muestra de idioma:
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
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

Análisis de algoritmos

  • lista de adyacencia : El algoritmo debe atravesar la lista de adyacencia de cada vértice y, para cada borde, se debe agregar un borde inverso a la lista de adyacencia del punto adyacente. Si la longitud promedio de la lista de vecinos es k, la complejidad temporal del algoritmo es O (V + E * k). En el peor de los casos, k puede estar cerca de V y la complejidad del tiempo está cerca de O (V ^ 2). En el mejor de los casos, k es cercano a 1 y la complejidad temporal es cercana a O(E).
  • matriz de adyacencia : El algoritmo necesita revisar cada elemento de la matriz e intercambiar las filas y columnas. Dado que la matriz es VxV, la complejidad temporal es O (V ^ 2).

En aplicaciones prácticas, qué algoritmo elegir depende de la escasez del gráfico y de la memoria disponible. Para gráficos dispersos, las listas enlazadas de adyacencia pueden ser más eficientes en cuanto a memoria; para gráficos densos, las matrices de adyacencia pueden ser más eficientes.

Hunyuan:

Para calcular una gráfica dirigida G = (V, E) G=(V, E)GRAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMO=(V,mi) transposición de GT = ( V , ET ) G^T=(V, E^T)GRAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMOyo=(V,miyo), podemos proporcionar los algoritmos correspondientes para los dos métodos de representación de lista enlazada de adyacencia y matriz de adyacencia respectivamente, y analizar su tiempo de ejecución.

Representación de lista enlazada de adyacencia

Descripción del algoritmo
  1. Inicialice una lista de adyacencia vacía para almacenar los bordes del gráfico transpuesto.
  2. Recorrer la imagen original. GGGRAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMO de todos los nodos.
  3. para cada nodo uu, atraviesa todos los nodos vecinos en su lista de adyacencia Verboen
  4. Agregar una nueva lista de adyacencia de Verboen llegar uu lado.
  5. Después de completar el recorrido, la nueva lista vinculada de adyacencia es el gráfico transpuesto GiganteGRAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMOyo
Análisis del tiempo de ejecución
  • complejidad del tiempo: O ( ∣ E ∣ ) O(|E|)Ohhhhhhhhhhhhhhhhhhhh(mi),en ∣ mi ∣ |mi|mi es el número de lados de la imagen original. Porque necesitamos atravesar cada borde dos veces (una para leer y otra para escribir).

Notación matricial de adyacencia

Descripción del algoritmo
  1. Inicialice una matriz de adyacencia del mismo tamaño que el gráfico original para almacenar los bordes del gráfico transpuesto.
  2. Recorrer la imagen original. GGGRAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMO matriz de adyacencia.
  3. Para cada elemento distinto de cero en la matriz (es decir, hay una arista ( u , v ) ( u , v )(,en)), posición correspondiente en la matriz de adyacencia del gráfico transpuesto ( v , u ) ( v , u )(en,) Establecido en un elemento distinto de cero.
  4. Después de completar el recorrido, la nueva matriz de adyacencia es el gráfico transpuesto. GiganteGRAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMORAMOyo
Análisis del tiempo de ejecución
  • complejidad del tiempo: O ( ∣ V ∣ 2 ) O(|V|^2)Ohhhhhhhhhhhhhhhhhhhh(V2),en ∣ V ∣ |V|V es el número de nodos en el gráfico original. Porque necesitamos atravesar toda la matriz de adyacencia.

Implementación del lenguaje Go (representación de lista vinculada adyacente)

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()
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39

En este código definimos un Edge estructura para representar bordes, y unaAdjacencyList Estructura para representar una lista enlazada de adyacencia.TransposeGraph La función acepta unaAdjacencyList escriba el parámetro y devuelva una representación de lista vinculada de adyacencia de su gráfico transpuesto.existirmain función, creamos un gráfico de ejemplo, calculamos e imprimimos su gráfico transpuesto.