Technologieaustausch

Wen Xin Yi Yan VS iFlytek Spark VS chatgpt (300) – Einführung in Algorithmen 22.1 4 Fragen

2024-07-12

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

4. Mehrere Bilder gegeben G = (V, E) G=(V,E)G=(V,E)Adjazenzverknüpfte Liste (Multigraph ist ein Diagramm, das wiederholte Kanten und selbstschleifende Kanten zulässt), bitte geben Sie eine Zeit an O ( V + E ) O(V+E)Ö(V+E)Algorithmus, der zur Berechnung des „äquivalenten“ ungerichteten Graphen des Graphen verwendet wird G ′ = ( V , E ′ ) G^{'}=(V,E^{'})G=(V,E) dargestellt durch eine verknüpfte Adjazenzliste.Hier E ′ E^{'}EEs wird sein EEE Die redundanten Kanten in und die verbleibenden Kanten nach dem Löschen von Selbstschleifenkanten. Das Entfernen verbleibender Kanten bezieht sich auf das Ersetzen mehrerer Kanten zwischen zwei Knoten durch eine Kante. Wenn Sie Code schreiben möchten, verwenden Sie bitte die Sprache go.

Wen Xins Worte:

Darstellung verknüpfter Adjazenzlisten

In der Darstellung der verknüpften Adjazenzliste ist jeder Scheitelpunkt vvgegen Es gibt eine verknüpfte Liste und jeder Knoten in der verknüpften Liste repräsentiert einen Slave vvgegen Startkante.um zu berechnen GTG^TGT, wir müssen durchqueren GGG Für jede Kante von addieren Sie zu, indem Sie die Richtung der Kante umkehren GTG^TGT in der entsprechenden verlinkten Liste.

Go-Sprachimplementierung

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

Zeitkomplexität

  • Die zeitliche Komplexität des Durchlaufens jeder Kante beträgt O ( E ) O(E)Ö(E),In EEE ist die Anzahl der Kanten.
  • Für jede Kante führen wir eine Operation mit konstanter Zeit durch (Hinzufügen zur Adjazenzliste eines anderen Diagramms).
  • Daher beträgt die Gesamtzeitkomplexität O ( E ) O(E)Ö(E)

Darstellung der Adjazenzmatrix

In der Darstellung der Adjazenzmatrix verwenden wir ein zweidimensionales Array zum Speichern von Kanteninformationen matrix[u][v] Gibt an, ob eine Zeile von vorhanden ist uuSie ankommen vvgegen Seite.um zu berechnen GTG^TGT, wir durchqueren das obere Dreieck (oder das untere Dreieck, abhängig von Ihren Matrixdarstellungsgewohnheiten) der Matrix und kehren die Richtung der Kanten um, d. h. matrix[u][v] Der Wert wird zugewiesenmatrixT[v][u]

Go-Sprachimplementierung(Vereinfachte Version, berücksichtigt nur die Existenz und berücksichtigt nicht die Kantengewichte):

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

Zeitkomplexität

  • Das Durchlaufen jedes Elements der Matrix erfordert O ( V 2 ) O(V^2)Ö(V2) Zeit, darunter VVV ist die Anzahl der Eckpunkte.
  • Daher beträgt die Gesamtzeitkomplexität O ( V 2 ) O(V^2)Ö(V2) . Dies ist möglicherweise nicht die effizienteste Methode, wenn die Anzahl der Scheitelpunkte viel größer ist als die Anzahl der Kanten.

Fügen Sie hier eine Bildbeschreibung ein

Fügen Sie hier eine Bildbeschreibung ein

Fügen Sie hier eine Bildbeschreibung ein

Fügen Sie hier eine Bildbeschreibung ein

iFlytek Spark:

Für einen gerichteten Graphen, der durch eine Adjazenzliste dargestellt wird, können wir die benachbarten Scheitelpunkte jedes Scheitelpunkts zur Adjazenzliste des transponierten Scheitelpunkts des neuen Graphen hinzufügen, indem wir die Adjazenzliste jedes Scheitelpunkts durchlaufen. Konkrete Schritte sind wie folgt:

  1. Erstellen Sie eine neue Adjazenzliste GTG^{T}GT, initialisiert, um leer zu sein.
  2. Durchlaufen Sie das Originalbild GGG jeder Scheitelpunkt von vvgegen
  3. Scheitelpunkte durchqueren vvgegen Adjazenzverknüpfte Liste, jeder benachbarte Scheitelpunkt uuSie Zu neuem Bild hinzufügen GTG^{T}GT mittlerer Scheitelpunkt vvgegen in der verknüpften Adjazenzliste.
  4. Zurück zum neuen Bild GTG^{T}GT

Zeitkomplexitätsanalyse: Das Durchlaufen jedes Scheitelpunkts des Originaldiagramms erfordert O ( ∣ V ∣ ) O(|V|)Ö(V) Die zum Durchlaufen der Adjazenzliste jedes Scheitelpunkts erforderliche Zeit beträgt O ( ∣ E ∣ ) O(|E|)Ö(E) Zeit, also ist die gesamte Zeitkomplexität O ( ∣ V ∣ + ∣ E ∣ ) O(|V| + |E|)Ö(V+E)

Für einen gerichteten Graphen, der durch eine Adjazenzmatrix dargestellt wird, können wir die Adjazenzmatrix eines neuen Graphen erhalten, indem wir die Adjazenzmatrix des ursprünglichen Graphen transponieren. Konkrete Schritte sind wie folgt:

  1. Erstellen Sie ein neues mit der Größe ∣ V ∣ × ∣ V ∣ |V| mal |V|V×V Matrix GTG^{T}GT, initialisiert auf eine All-Null-Matrix.
  2. Durchlaufen Sie die Adjazenzmatrix des Originalbilds GGG,Wille G [ i ] [ j ] G[i][j]G[ichchchch][J] Der Wert wird zugewiesen GT [ j ] [ ich ] G^{T}[j][i]GT[J][ichchchch]
  3. Gibt die Adjazenzmatrix des neuen Diagramms zurück GTG^{T}GT

Zeitkomplexitätsanalyse: Das Durchlaufen der Adjazenzmatrix des Originaldiagramms erfordert O ( ∣ V ∣ 2 ) O(|V|^2)Ö(V2) Zeit, also ist die gesamte Zeitkomplexität O ( ∣ V ∣ 2 ) O(|V|^2)Ö(V2)

Das Folgende ist der in der Go-Sprache implementierte Code:

// 邻接链表表示的有向图转置
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

360 Intelligentes Gehirn:

Darstellung verknüpfter Adjazenzlisten

In der Darstellung der verknüpften Adjazenzliste können wir das Originalbild direkt durchlaufen GGGDie Adjazenzliste jedes Knotens wird dann dem neuen Diagramm hinzugefügt, nachdem die Richtung jeder Kante umgekehrt wurde. GTG^{T}GTauf dem entsprechenden Knoten.

Go-Sprachcode-Implementierung:
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
Zeitkomplexitätsanalyse:
  • Durchlaufen Sie jeden Knoten im Originaldiagramm: O ( ∣ V ∣ ) O(|V|)Ö(V)
  • Durchlaufen Sie die Adjazenzliste jedes Knotens: O ( ∣ E ∣ ) O(|E|)Ö(E)

Daher beträgt die Gesamtzeitkomplexität O ( ∣ V ∣ + ∣ E ∣ ) O(|V| + |E|)Ö(V+E)

Notation der Adjazenzmatrix

In der Adjazenzmatrix-Notation können wir eine neue Adjazenzmatrix erstellen und dann das Originalbild durchlaufen GGGAdjazenzmatrix, jedes Element in der Matrix ( ich , j ) ( ich , j )(ichchchch,J)der neuen Matrix zugeordnet (j, ich) (j, ich)(J,ichchchch)Position und vervollständigt damit die Umkehrung der Kante.

Go-Sprachcode-Implementierung:
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
Zeitkomplexitätsanalyse:
  • Erstellen Sie eine neue Adjazenzmatrix: O ( ∣ V ∣ 2 ) O(|V|^2)Ö(V2)
  • Durchlaufen Sie die Adjazenzmatrix des Originalbilds: O ( ∣ V ∣ 2 ) O(|V|^2)Ö(V2)

Daher beträgt die Gesamtzeitkomplexität O ( ∣ V ∣ 2 ) O(|V|^2)Ö(V2)

Zusammenfassen

Für die Darstellung der Adjazenz-verknüpften Liste beträgt die zeitliche Komplexität des Transponierungsalgorithmus O ( ∣ V ∣ + ∣ E ∣ ) O(|V| + |E|)Ö(V+E)und für die Darstellung der Adjazenzmatrix beträgt die zeitliche Komplexität des Transponierungsalgorithmus O ( ∣ V ∣ 2 ) O(|V|^2)Ö(V2) .In praktischen Anwendungen gilt: Wenn der Graph relativ dünn besetzt ist (d. h. ∣ E ∣ |E|Eviel kleiner als ∣ V ∣ 2 |V|^2V2 ), wäre es effizienter, die Adjazenz-verknüpfte Listendarstellung zu verwenden.Wenn der Graph dicht ist (d. h. ∣ E ∣ |E|Enahe ∣ V ∣ 2 |V|^2V2), dann ist die Adjazenzmatrixdarstellung möglicherweise angemessener.

Weisheitsspektrum klare Worte:

Bei der Diagrammdarstellung sind verknüpfte Adjazenzlisten und Adjazenzmatrizen häufig verwendete Methoden. Adjazenzverknüpfte Listen werden zur Darstellung ungerichteter und gerichteter Graphen verwendet, während Adjazenzmatrizen normalerweise zur Darstellung ungerichteter Graphen verwendet werden. Für die Transponierung eines gerichteten Graphen können wir die verknüpfte Adjazenzliste und die Adjazenzmatrix separat bearbeiten.

Transponieren einer verknüpften Adjazenzliste

Für einen gerichteten Graphen, der durch eine verknüpfte Adjazenzliste dargestellt wird, kann die Transponierung des Graphen erreicht werden, indem jeder Scheitelpunkt des Originalgraphen durchlaufen und die ausgehenden Kanten des Originalgraphen in eingehende Kanten umgewandelt werden.

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

Transponierte Adjazenzmatrix

Bei einem gerichteten Graphen, der durch eine Adjazenzmatrix dargestellt wird, kann die Transponierung des Graphen erreicht werden, indem jede Zeile des ursprünglichen Graphen in die entsprechende Spalte des neuen Graphen umgewandelt wird.

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

Algorithmus-Laufzeitanalyse

  1. Für die Transposition einer adjazenzverknüpften Liste beträgt die zeitliche Komplexität des Algorithmus O(E), wobei E die Anzahl der Kanten im Diagramm ist. Dies liegt daran, dass jede Kante einmal durchlaufen werden muss.

  2. Für die Transponierung der Adjazenzmatrix beträgt die zeitliche Komplexität des Algorithmus O(V^2), wobei V die Anzahl der Eckpunkte im Diagramm ist. Dies liegt daran, dass jedes Matrixelement einmal durchlaufen werden muss und die Größe der Matrix V×V beträgt.
    Diese Algorithmen sind alle effizient und laufen

Tiangong:

Implementierung eines Algorithmus zur Berechnung eines gerichteten Graphen GGG Umsetzung von GTG^{T}GT können wir die beiden Darstellungen der verknüpften Adjazenzliste bzw. der Adjazenzmatrix verarbeiten. Im Folgenden werde ich die Algorithmen für diese beiden Fälle beschreiben und Codebeispiele in der Go-Sprache bereitstellen.

Darstellung verknüpfter Adjazenzlisten

Algorithmusschritte:
  1. Erstellen Sie eine neue Adjazenzliste newAdjList Wird zum Speichern des transponierten Diagramms verwendet.
  2. Durchlaufen Sie die verknüpfte Adjazenzliste des Originalbilds adjList
  3. für jede Kante (u, v), füge es hinzu newAdjList[v] Mitte.
  4. Gibt die neue Adjazenzliste zurück newAdjList
Beispiel für einen Go-Sprachcode:
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
Laufzeitanalyse:

Die Laufzeit dieses Algorithmus beträgt O(|V| + |E|), wobei |V| die Anzahl der Eckpunkte und |E| die Anzahl der Kanten ist. Dies liegt daran, dass wir alle Eckpunkte und Kanten einmal durchlaufen müssen.

Notation der Adjazenzmatrix

Algorithmusschritte:
  1. Erstellen Sie eine neue Adjazenzmatrix newAdjMatrix Wird zum Speichern des transponierten Diagramms verwendet.
  2. Durchlaufen Sie die Adjazenzmatrix des Originalbilds adjMatrix
  3. für jedes Element adjMatrix[i][j], weisen Sie es zu newAdjMatrix[j][i]
  4. Gibt die neue Adjazenzmatrix zurück newAdjMatrix
Beispiel für einen Go-Sprachcode:
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
Laufzeitanalyse:

Die Laufzeit dieses Algorithmus beträgt O(|V|^2), wobei |V| die Anzahl der Eckpunkte ist. Dies liegt daran, dass wir die gesamte Adjazenzmatrix durchlaufen müssen und die Größe der Adjazenzmatrix |V|

Das obige Codebeispiel ist nur der Kernteil des Algorithmus. In tatsächlichen Anwendungen müssen möglicherweise weitere Funktionen wie Fehlerbehandlung, Eingabe und Ausgabe hinzugefügt werden. Darüber hinaus wird zur Vereinfachung des Codes davon ausgegangen, dass es im Diagramm keine wiederholten Kanten gibt und die Scheitelpunktnummern beginnend bei 0 fortlaufend nummeriert sind.

chatgpt:

Das Folgende ist ein in der Go-Sprache geschriebener Algorithmus zur Berechnung von G^T aus Diagramm G, und die entsprechenden Darstellungsmethoden für verknüpfte Adjazenzlisten und Adjazenzmatrixen sind ebenfalls angegeben:

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

Die zeitliche Komplexität dieses Algorithmus beträgt O(V + E), wobei V die Anzahl der Eckpunkte und E die Anzahl der Kanten ist. Der Konstruktionsprozess des transponierten Diagramms erfordert das Durchlaufen aller Kanten des ursprünglichen Diagramms und das umgekehrte Hinzufügen zum transponierten Diagramm, sodass die Gesamtzeitkomplexität proportional zur Anzahl der Scheitelpunkte und Kanten ist.

kimi:

Transponierte Graphen gerichteter Graphen können durch zwei Hauptdatenstrukturen dargestellt werden: Adjazenzverknüpfte Listen und Adjazenzmatrizen. Im Folgenden werde ich die Algorithmen in diesen beiden Fällen vorstellen und Beispielcode in der Go-Sprache bereitstellen.

Darstellung verknüpfter Adjazenzlisten

Für einen Graphen, der durch eine verknüpfte Adjazenzliste dargestellt wird, können wir den Graphen transponieren, indem wir die Adjazenzliste jedes Scheitelpunkts durchlaufen und dann jedem Adjazenzpunkt eine umgekehrte Kante hinzufügen. Die zeitliche Komplexität dieser Methode beträgt O(V + E), wobei V die Anzahl der Eckpunkte und E die Anzahl der Kanten ist.

Beispielcode für die Go-Sprache:
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

Darstellung der Adjazenzmatrix

Für einen Graphen, der durch eine Adjazenzmatrix dargestellt wird, können wir die Transponierung implementieren, indem wir die Zeilen und Spalten der Matrix vertauschen. Die zeitliche Komplexität dieser Methode beträgt O(V^2).

Beispielcode für die Go-Sprache:
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 von Algorithmen

  • Adjazenzliste : Der Algorithmus muss die Adjazenzliste jedes Scheitelpunkts durchlaufen und für jede Kante muss eine umgekehrte Kante zur Adjazenzliste des benachbarten Punkts hinzugefügt werden. Wenn die durchschnittliche Länge der Nachbarliste k beträgt, beträgt die zeitliche Komplexität des Algorithmus O(V + E * k). Im schlimmsten Fall kann k nahe bei V liegen und die Zeitkomplexität liegt nahe bei O(V^2). Im besten Fall liegt k nahe bei 1 und die Zeitkomplexität liegt nahe bei O(E).
  • Adjazenzmatrix : Der Algorithmus muss jedes Element der Matrix durchgehen und die Zeilen und Spalten vertauschen. Da die Matrix VxV ist, beträgt die Zeitkomplexität O(V^2).

In praktischen Anwendungen hängt die Wahl des zu wählenden Algorithmus von der Sparsität des Diagramms und dem verfügbaren Speicher ab. Bei dünn besetzten Diagrammen können Adjazenzverknüpfungslisten speichereffizienter sein; bei dichten Diagrammen sind Adjazenzmatrizen möglicherweise effizienter.

Hunyuan:

Einen gerichteten Graphen berechnen G = (V, E) G=(V,E)G=(V,E) Umsetzung von GT = (V, ET) G^T=(V,E^T)GT=(V,ET), können wir entsprechende Algorithmen für die beiden Darstellungsmethoden Adjazenzverknüpfte Liste bzw. Adjazenzmatrix angeben und deren Laufzeit analysieren.

Darstellung verknüpfter Adjazenzlisten

Beschreibung des Algorithmus
  1. Initialisieren Sie eine leere Adjazenzliste, um die Kanten des transponierten Diagramms zu speichern.
  2. Durchlaufen Sie das Originalbild GGG aller Knoten.
  3. für jeden Knoten uuSie, alle Nachbarknoten in seiner Adjazenzliste durchlaufen vvgegen
  4. Fügen Sie eine neue Adjazenzliste hinzu vvgegen ankommen uuSie Seite.
  5. Nach Abschluss des Durchlaufs ist die neue verknüpfte Adjazenzliste der transponierte Graph GTG^TGT
Laufzeitanalyse
  • Zeitkomplexität: O ( ∣ E ∣ ) O(|E|)Ö(E),In ∣ E ∣ |E|E ist die Anzahl der Seiten des Originalbildes. Weil wir jede Kante zweimal durchlaufen müssen (einmal zum Lesen und einmal zum Schreiben).

Notation der Adjazenzmatrix

Beschreibung des Algorithmus
  1. Initialisieren Sie eine Adjazenzmatrix mit der gleichen Größe wie das Originaldiagramm, um die Kanten des transponierten Diagramms zu speichern.
  2. Durchlaufen Sie das Originalbild GGG Adjazenzmatrix.
  3. Für jedes Nicht-Null-Element in der Matrix (d. h. es gibt eine Kante). (u, v) (u, v)(Sie,gegen)), entsprechende Position in der Adjazenzmatrix des transponierten Graphen (v, u) (v, u)(gegen,Sie) Auf ein Element ungleich Null setzen.
  4. Nach Abschluss der Durchquerung ist die neue Adjazenzmatrix der transponierte Graph GTG^TGT
Laufzeitanalyse
  • Zeitkomplexität: O ( ∣ V ∣ 2 ) O(|V|^2)Ö(V2),In ∣ V ∣ |V|V ist die Anzahl der Knoten im Originaldiagramm. Weil wir die gesamte Adjazenzmatrix durchlaufen müssen.

Go-Sprachimplementierung (Darstellung benachbarter verknüpfter Listen)

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

In diesem Code definieren wir a Edge Struktur zur Darstellung von Kanten und aAdjacencyList Struktur zur Darstellung einer verknüpften Adjazenzliste.TransposeGraph Die Funktion akzeptiert aAdjacencyList Typparameter und gibt eine adjazenzverkettete Listendarstellung seines transponierten Diagramms zurück.existierenmain Mit dieser Funktion erstellen wir ein Beispieldiagramm, berechnen das transponierte Diagramm und drucken es aus.