Partage de technologie

Wen Xin Yi Yan VS iFlytek Spark VS chatgpt (300) -- Introduction aux algorithmes 22.1 4 questions

2024-07-12

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

4. Étant donné plusieurs photos G = ( V , E ) G=(V,E)g=(V,E)liste chaînée de contiguïté (le multigraphe est un graphique qui permet des arêtes répétées et des arêtes en boucle automatique), veuillez donner une heure de O ( V + E ) O(V+E)O(V+E)algorithme, utilisé pour calculer le graphe non orienté « équivalent » du graphe G ′ = ( V , E ′ ) G^{'}=(V,E^{'})g=(V,E) représenté par une liste chaînée de contiguïté.ici E ′ E^{'}ECe sera É.-U.E Les bords redondants et les bords restants après la suppression des bords en boucle automatique. La suppression des arêtes restantes fait référence au remplacement de plusieurs arêtes entre deux nœuds par une seule arête. Si vous souhaitez écrire du code, veuillez utiliser le langage go.

Les mots de Wen Xin :

Représentation de liste chaînée de contiguïté

Dans la représentation de liste chaînée de contiguïté, chaque sommet vvv Il existe une liste chaînée, et chaque nœud de la liste chaînée représente un esclave vvv Bord de départ.afin de calculer GTG^TgT, nous devons traverser GGg pour chaque bord de , et en inversant la direction du bord, ajoutez à GTG^TgT dans la liste chaînée correspondante.

Aller à l'implémentation du langage

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

complexité temporelle

  • La complexité temporelle du parcours de chaque arête est O ( E ) O(E)O(E),dans É.-U.E est le nombre d'arêtes.
  • Pour chaque arête, nous effectuons une opération à temps constant (ajout à la liste de contiguïté d'un autre graphe).
  • La complexité temporelle totale est donc O ( E ) O(E)O(E)

Représentation matricielle de contiguïté

Dans la représentation matricielle de contiguïté, nous utilisons un tableau bidimensionnel pour stocker les informations de bord, où matrix[u][v] Indique s'il y a une ligne de euhtoi arriver vvv côté.afin de calculer GTG^TgT, nous parcourons le triangle supérieur (ou le triangle inférieur, selon vos habitudes de représentation matricielle) de la matrice et inversons la direction des bords, c'est-à-dire matrix[u][v] La valeur est attribuée àmatrixT[v][u]

Aller à l'implémentation du langage(Version simplifiée, ne prend en compte que l'existence et ne prend pas en compte les poids des bords) :

// 假设使用二维布尔切片表示邻接矩阵
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

complexité temporelle

  • Itérer sur chaque élément de la matrice nécessite O ( V 2 ) O(V^2)O(V2) temps, parmi lesquels VVV est le nombre de sommets.
  • La complexité temporelle totale est donc O ( V 2 ) O(V^2)O(V2) . Cela n’est peut-être pas le plus efficace lorsque le nombre de sommets est bien supérieur au nombre d’arêtes.

Insérer la description de l'image ici

Insérer la description de l'image ici

Insérer la description de l'image ici

Insérer la description de l'image ici

iFlytek Spark :

Pour un graphe orienté représenté par une liste d'adjacence, on peut ajouter les sommets adjacents de chaque sommet à la liste d'adjacence du sommet transposé du nouveau graphe en parcourant la liste d'adjacence de chaque sommet. Les étapes spécifiques sont les suivantes :

  1. Créer une nouvelle liste de contiguïté GTG^{T}gT, initialisé à vide.
  2. Traverser l'image originale GGg chaque sommet de vvv
  3. Traverser les sommets vvv liste chaînée de contiguïté, chaque sommet adjacent euhtoi Ajouter à une nouvelle image GTG^{T}gT sommet du milieu vvv dans la liste chaînée de contiguïté.
  4. Revenir à la nouvelle image GTG^{T}gT

Analyse de complexité temporelle : parcourir chaque sommet du graphe d'origine nécessite O ( ∣ V ∣ ) O(|V|)O(V) Le temps nécessaire pour parcourir la liste de contiguïté de chaque sommet est O ( ∣ E ∣ ) O(|E|)O(E) temps, donc la complexité temporelle totale est O ( ∣ V ∣ + ∣ E ∣ ) O(|V| + |E|)O(V+E)

Pour un graphe orienté représenté par une matrice de contiguïté, on peut obtenir la matrice de contiguïté d'un nouveau graphe en transposant la matrice de contiguïté du graphe d'origine. Les étapes spécifiques sont les suivantes :

  1. Créez-en un nouveau avec la taille ∣ V ∣ × ∣ V ∣ |V| fois |V|V×V matrice GTG^{T}gT, initialisé à une matrice entièrement nulle.
  2. Parcourez la matrice de contiguïté de l'image originale GGg,Volonté G [ i ] [ j ] G[i][j]g[je][j] La valeur est attribuée à GT [ j ] [ i ] G^{T}[j][i]gT[j][je]
  3. Renvoie la matrice de contiguïté du nouveau graphique GTG^{T}gT

Analyse de complexité temporelle : parcourir la matrice d'adjacence du graphe d'origine nécessite O ( ∣ V ∣ 2 ) O(|V|^2)O(V2) temps, donc la complexité temporelle totale est O ( ∣ V ∣ 2 ) O(|V|^2)O(V2)

Voici le code implémenté en langage 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

Cerveau intelligent à 360° :

Représentation de liste chaînée de contiguïté

Dans la représentation de liste chaînée de contiguïté, nous pouvons parcourir directement l'image d'origine GGgLa liste de contiguïté de chaque nœud est ensuite ajoutée au nouveau graphique après avoir inversé la direction de chaque arête. GTG^{T}gTsur le nœud correspondant.

Aller à l'implémentation du code de langue :
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
Analyse de la complexité temporelle :
  • Parcourez chaque nœud dans le graphique d'origine : O ( ∣ V ∣ ) O(|V|)O(V)
  • Parcourez la liste de contiguïté de chaque nœud : O ( ∣ E ∣ ) O(|E|)O(E)

La complexité temporelle totale est donc O ( ∣ V ∣ + ∣ E ∣ ) O(|V| + |E|)O(V+E)

Notation matricielle de contiguïté

En notation matricielle de contiguïté, nous pouvons créer une nouvelle matrice de contiguïté puis parcourir l'image d'origine GGgmatrice de contiguïté, chaque élément de la matrice (i, j) (i, j)(je,j)affecté à la nouvelle matrice (j, i) (j, i)(j,je)position, complétant ainsi l’inversion du bord.

Aller à l'implémentation du code de langue :
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
Analyse de la complexité temporelle :
  • Créez une nouvelle matrice de contiguïté : O ( ∣ V ∣ 2 ) O(|V|^2)O(V2)
  • Parcourez la matrice de contiguïté de l'image originale : O ( ∣ V ∣ 2 ) O(|V|^2)O(V2)

La complexité temporelle totale est donc O ( ∣ V ∣ 2 ) O(|V|^2)O(V2)

Résumer

Pour la représentation de liste chaînée de contiguïté, la complexité temporelle de l'algorithme de transposition est O ( ∣ V ∣ + ∣ E ∣ ) O(|V| + |E|)O(V+E), et pour la représentation matricielle de contiguïté, la complexité temporelle de l'algorithme de transposition est O ( ∣ V ∣ 2 ) O(|V|^2)O(V2) .Dans les applications pratiques, si le graphique est relativement clairsemé (c'est-à-dire ∣ E ∣ |E|Ebeaucoup plus petit que ∣ V ∣ 2 |V|^2V2 ), il serait plus efficace d'utiliser la représentation de liste chaînée de contiguïté.Si le graphique est dense (c'est-à-dire ∣ E ∣ |E|Eprès ∣ V ∣ 2 |V|^2V2), alors la représentation matricielle de contiguïté peut être plus appropriée.

Spectre de sagesse mots clairs :

Dans la représentation graphique, les listes chaînées de contiguïté et les matrices de contiguïté sont toutes deux des méthodes couramment utilisées. Les listes chaînées de contiguïté sont utilisées pour représenter des graphiques non orientés et orientés, tandis que les matrices de contiguïté sont généralement utilisées pour représenter des graphiques non orientés. Pour la transposition d'un graphe orienté, nous pouvons opérer séparément sur la liste chaînée d'adjacence et la matrice d'adjacence.

Transposer la liste chaînée de contiguïté

Pour un graphe orienté représenté par une liste chaînée de contiguïté, la transposition du graphe peut être réalisée en parcourant chaque sommet du graphe d'origine et en modifiant les arêtes sortantes du graphe d'origine en arêtes 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

Transposition de la matrice de contiguïté

Pour un graphe orienté représenté par une matrice de contiguïté, la transposition du graphe peut être réalisée en transformant chaque ligne du graphe d'origine en la colonne correspondante du nouveau graphe.

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

Analyse du temps d'exécution de l'algorithme

  1. Pour la transposition d'une liste chaînée de contiguïté, la complexité temporelle de l'algorithme est O(E), où E est le nombre d'arêtes dans le graphe. En effet, chaque arête doit être traversée une fois.

  2. Pour la transposition de la matrice de contiguïté, la complexité temporelle de l'algorithme est O(V^2), où V est le nombre de sommets dans le graphe. En effet, chaque élément de la matrice doit être parcouru une fois et la taille de la matrice est V×V.
    Ces algorithmes sont tous efficaces et exécutés

Tiangong :

Implémenter un algorithme pour calculer un graphe orienté GGg transposition de GTG^{T}gT , nous pouvons traiter respectivement les deux représentations de la liste chaînée de contiguïté et de la matrice de contiguïté. Ci-dessous, je décrirai respectivement les algorithmes pour ces deux cas et fournirai des exemples de code en langage Go.

Représentation de liste chaînée de contiguïté

Étapes de l'algorithme :
  1. Créer une nouvelle liste de contiguïté newAdjList Utilisé pour stocker le graphique transposé.
  2. Parcourez la liste chaînée de contiguïté de l'image d'origine adjList
  3. pour chaque bord (u, v), ajoutez-le à newAdjList[v] milieu.
  4. Renvoie la nouvelle liste de contiguïté newAdjList
Exemple de code de langue :
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
Analyse du temps d'exécution :

Le temps d'exécution de cet algorithme est O(|V| + |E|), où |V| est le nombre de sommets et |E| est le nombre d'arêtes. En effet, nous devons parcourir tous les sommets et arêtes une fois.

Notation matricielle de contiguïté

Étapes de l'algorithme :
  1. Créer une nouvelle matrice de contiguïté newAdjMatrix Utilisé pour stocker le graphique transposé.
  2. Parcourez la matrice de contiguïté de l'image originale adjMatrix
  3. pour chaque élément adjMatrix[i][j], attribuez-le à newAdjMatrix[j][i]
  4. Renvoie la nouvelle matrice de contiguïté newAdjMatrix
Exemple de code de langue :
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
Analyse du temps d'exécution :

Le temps d'exécution de cet algorithme est O(|V|^2), où |V| est le nombre de sommets. En effet, nous devons parcourir toute la matrice de contiguïté et la taille de la matrice de contiguïté est de |V| x |V|.

L'exemple de code ci-dessus ne constitue que la partie centrale de l'algorithme. Dans les applications réelles, d'autres fonctions telles que la gestion des erreurs, l'entrée et la sortie peuvent devoir être ajoutées. De plus, pour simplifier le code, on suppose qu’il n’y a pas d’arêtes répétées dans le graphique et que les numéros de sommets sont numérotés consécutivement à partir de 0.

chatgpt :

Ce qui suit est un algorithme écrit en langage Go pour calculer G ^ T à partir du graphique G, et les méthodes de liste chaînée de contiguïté et de représentation matricielle de contiguïté correspondantes sont également données :

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 complexité temporelle de cet algorithme est O(V + E), où V est le nombre de sommets et E est le nombre d'arêtes. Le processus de construction du graphe transposé nécessite de parcourir toutes les arêtes du graphe d'origine et de les ajouter au graphe transposé à l'envers, de sorte que la complexité temporelle totale est proportionnelle au nombre de sommets et d'arêtes.

Kimi :

Les graphes transposés de graphes orientés peuvent être représentés par deux structures de données principales : les listes chaînées de contiguïté et les matrices de contiguïté. Ci-dessous, je présenterai respectivement les algorithmes dans ces deux cas et fournirai un exemple de code en langage Go.

Représentation de liste chaînée de contiguïté

Pour un graphe représenté par une liste chaînée de contiguïté, nous pouvons transposer le graphe en parcourant la liste de contiguïté de chaque sommet puis en ajoutant une arête inverse à chaque point de contiguïté. La complexité temporelle de cette méthode est O(V + E), où V est le nombre de sommets et E est le nombre d’arêtes.

Accédez à un exemple de code de langue :
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

Représentation matricielle de contiguïté

Pour un graphique représenté par une matrice de contiguïté, nous pouvons implémenter la transposition en échangeant les lignes et les colonnes de la matrice. La complexité temporelle de cette méthode est O(V^2).

Accédez à un exemple de code de langue :
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

Analyse des algorithmes

  • liste de contiguïté : L'algorithme doit parcourir la liste de contiguïté de chaque sommet, et pour chaque arête, une arête inverse doit être ajoutée à la liste de contiguïté du point adjacent. Si la longueur moyenne de la liste voisine est k, la complexité temporelle de l'algorithme est O(V + E * k). Dans le pire des cas, k peut être proche de V et la complexité temporelle est proche de O(V^2). Dans le meilleur des cas, k est proche de 1 et la complexité temporelle est proche de O(E).
  • matrice de contiguïté : L'algorithme doit parcourir chaque élément de la matrice et échanger les lignes et les colonnes. Puisque la matrice est VxV, la complexité temporelle est O(V^2).

Dans les applications pratiques, l'algorithme à choisir dépend de la rareté du graphique et de la mémoire disponible. Pour les graphiques clairsemés, les listes chaînées de contiguïté peuvent être plus efficaces en termes de mémoire ; pour les graphiques denses, les matrices de contiguïté peuvent être plus efficaces.

Hunyuan :

Pour calculer un graphe orienté G = ( V , E ) G=(V,E)g=(V,E) transposition de GT = ( V , ET ) G^T=(V,E^T)gT=(V,ET), nous pouvons donner des algorithmes correspondants pour les deux méthodes de représentation de la liste chaînée de contiguïté et de la matrice de contiguïté respectivement, et analyser leur temps d'exécution.

Représentation de liste chaînée de contiguïté

Description de l'algorithme
  1. Initialisez une liste de contiguïté vide pour stocker les arêtes du graphe transposé.
  2. Traverser l'image originale GGg de tous les nœuds.
  3. pour chaque nœud euhtoi, traverse tous les nœuds voisins dans sa liste de contiguïté vvv
  4. Ajouter une nouvelle liste de contiguïté à partir de vvv arriver euhtoi côté.
  5. Après avoir terminé le parcours, la nouvelle liste chaînée de contiguïté est le graphe transposé GTG^TgT
Analyse du temps d'exécution
  • complexité temporelle : O ( ∣ E ∣ ) O(|E|)O(E),dans ∣ E ∣ |E|E est le nombre de côtés de l’image originale. Parce que nous devons parcourir chaque arête deux fois (une fois pour lire et une fois pour écrire).

Notation matricielle de contiguïté

Description de l'algorithme
  1. Initialisez une matrice de contiguïté de la même taille que le graphe d'origine pour stocker les arêtes du graphe transposé.
  2. Traverser l'image originale GGg matrice de contiguïté.
  3. Pour chaque élément non nul de la matrice (c'est-à-dire qu'il y a une arête ( u , v ) ( u , v )(toi,v)), position correspondante dans la matrice d'adjacence du graphe transposé (v, u) (v, u)(v,toi) Définir sur un élément différent de zéro.
  4. Après avoir terminé le parcours, la nouvelle matrice d'adjacence est le graphe transposé GTG^TgT
Analyse du temps d'exécution
  • complexité temporelle : O ( ∣ V ∣ 2 ) O(|V|^2)O(V2),dans ∣ V ∣ |V|V est le nombre de nœuds dans le graphique d'origine. Parce que nous devons parcourir toute la matrice de contiguïté.

Implémentation du langage Go (représentation par liste chaînée adjacente)

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

Dans ce code, nous définissons un Edge structure pour représenter les bords, et unAdjacencyList Structure pour représenter une liste chaînée de contiguïté.TransposeGraph La fonction accepte unAdjacencyList paramètre de type et renvoie une représentation de liste chaînée de contiguïté de son graphe transposé.existermain fonction, nous créons un exemple de graphique, calculons et imprimons son graphique transposé.