Mi informacion de contacto
Correo[email protected]
2024-07-12
한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina
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)
}
}
complejidad del tiempo:
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 uutú 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函数
complejidad del tiempo:
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:
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:
Análisis de complejidad temporal: atravesar la matriz de adyacencia del gráfico original requiere O ( ∣ V ∣ 2 ) O(|V|^2)Ohhhhhhhhhhhhhhhhhhhh(∣V∣2) tiempo, por lo que la complejidad del tiempo total es O ( ∣ V ∣ 2 ) O(|V|^2)Ohhhhhhhhhhhhhhhhhhhh(∣V∣2)。
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
}
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.
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
}
Por lo tanto, la complejidad del tiempo total es O ( ∣ V ∣ + ∣ E ∣ ) O(|V| + |E|)Ohhhhhhhhhhhhhhhhhhhh(∣V∣+∣mi∣)。
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.
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
}
Por lo tanto, la complejidad del tiempo total es O ( ∣ V ∣ 2 ) O(|V|^2)Ohhhhhhhhhhhhhhhhhhhh(∣V∣2)。
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(∣V∣2) .En aplicaciones prácticas, si el gráfico es relativamente disperso (es decir, ∣ mi ∣ |mi|∣mi∣mucho más pequeño que ∣ V ∣ 2 |V|^2∣V∣2 ), sería más eficiente utilizar la representación de lista vinculada de adyacencia.Si el gráfico es denso (es decir, ∣ mi ∣ |mi|∣mi∣cerca ∣ V ∣ 2 |V|^2∣V∣2), entonces la representación de la matriz de adyacencia puede ser más apropiada.
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.
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)
}
}
}
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)
}
}
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.
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.
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.
newAdjList
Se utiliza para almacenar el gráfico transpuesto.adjList
。(u, v)
, añádelo a newAdjList[v]
medio.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
}
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.
newAdjMatrix
Se utiliza para almacenar el gráfico transpuesto.adjMatrix
。adjMatrix[i][j]
, asígnalo 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
}
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.
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)
}
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.
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.
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.
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
}
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).
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
}
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.
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.
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()
}
}
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.