Teknologian jakaminen

Wen Xin Yi Yan VS iFlytek Spark VS chatgpt (300) - Algoritmien johdatus 22.1 4 kysymystä

2024-07-12

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

4. Annettu useita kuvia G = ( V , E ) G= (V, E)G=(V,E)vierekkäisyyksiin linkitetty luettelo (multigrafi on graafi, joka sallii toistuvat reunat ja itsesilmukaiset reunat), anna aika O ( V + E ) O (V + E)O(V+E)algoritmi, jota käytetään graafin "vastaavan" suuntaamattoman graafin laskemiseen G ′ = ( V , E ′ ) G^{'}=(V,E^{'})G=(V,E) edustaa vierekkäisyyksiin linkitetty luettelo.tässä E′ E^{'}ESe tulee olemaan EEE Redundantit reunat sisään ja jäljellä olevat reunat itsesilmukan reunojen poistamisen jälkeen. Jäljellä olevien reunojen poistaminen tarkoittaa useiden reunojen korvaamista kahden solmun välillä yhdellä reunalla. Jos haluat kirjoittaa koodin, käytä go-kieltä.

Wen Xinin sanat:

Vierekkäin linkitetty luetteloesitys

Viereisyyteen linkitetyssä listaesityksessä jokainen kärkipiste vvv On linkitetty luettelo, ja jokainen linkitetyn luettelon solmu edustaa orjaa vvv Aloitusreuna.laskeakseen GTG^TGT, meidän täytyy kulkea GGG Lisää jokaiselle reunalle , ja käännä reunan suunta GTG^TGT vastaavassa linkitetyssä luettelossa.

Siirry kielen käyttöön

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

aika monimutkaisuus

  • Kunkin reunan ylittämisen aika monimutkaisuus on O ( E ) O (E)O(E),sisään EEE on reunojen lukumäärä.
  • Suoritamme kullekin reunalle vakioaikaisen operaation (lisätään toisen graafin viereisyysluetteloon).
  • Siksi kokonaisaika monimutkaisuus on O ( E ) O (E)O(E)

Vierekkäisyysmatriisiesitys

Viereisyysmatriisiesituksessa käytämme kaksiulotteista taulukkoa tallentamaan reunainformaatiota, missä matrix[u][v] Osoittaa, onko linja alkaen uuu saapua vvv puolella.laskeakseen GTG^TGT, kuljemme matriisin ylemmän kolmion (tai alemman kolmion, riippuen matriisin esitystavoistasi) poikki ja käännämme reunojen suunnan, eli matrix[u][v] Arvo on määritettymatrixT[v][u]

Siirry kielen käyttöön(Yksinkertaistettu versio, ottaa huomioon vain olemassaolon, ei huomioi reunapainoja):

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

aika monimutkaisuus

  • Matriisin jokaisen elementin iterointi vaatii O ( V 2 ) O (V^2)O(V2) aika, mukaan lukien VVV on pisteiden lukumäärä.
  • Siksi kokonaisaika monimutkaisuus on O ( V 2 ) O (V^2)O(V2) . Tämä ei ehkä ole tehokkainta, kun kärkien lukumäärä on paljon suurempi kuin reunojen lukumäärä.

Lisää kuvan kuvaus tähän

Lisää kuvan kuvaus tähän

Lisää kuvan kuvaus tähän

Lisää kuvan kuvaus tähän

iFlytek Spark:

Suunnatussa graafissa, jota edustaa viereisyysluettelo, voimme lisätä kunkin kärjen viereiset pisteet uuden graafin transponoidun kärjen viereisyysluetteloon kulkemalla kunkin kärjen vierekkäisyysluettelon läpi. Tarkat vaiheet ovat seuraavat:

  1. Luo uusi vierekkäisyysluettelo GTG^{T}GT, alustettu tyhjäksi.
  2. Siirrä alkuperäinen kuva poikki GGG jokainen kärkipiste vvv
  3. Poikki kärjet vvv vierekkäisyyteen linkitetty luettelo, jokainen viereinen kärkipiste uuu Lisää uuteen kuvaan GTG^{T}GT keskivertex vvv vierekkäisyyksiin linkitetyssä luettelossa.
  4. Paluu uuteen kuvaan GTG^{T}GT

Aikamonimutkaisuusanalyysi: alkuperäisen graafin jokaisen kärjen läpikäyminen vaatii O ( ∣ V ∣ ) O(|V|)O(V) Kunkin huippupisteen viereisyysluettelon kulkemiseen tarvittava aika on O ( ∣ E ∣ ) O(|E|)O(E) aika, joten kokonaisaika monimutkaisuus on O ( ∣ V ∣ + ∣ E ∣ ) O(|V| + |E|)O(V+E)

Viereisyysmatriisin edustamalle suunnatulle graafille voimme saada uuden graafin viereisyysmatriisin transponoimalla alkuperäisen graafin viereisyysmatriisi. Tarkat vaiheet ovat seuraavat:

  1. Luo uusi koolla ∣ V ∣ × ∣ V ∣ |V| kertaa |V|V×V matriisi GTG^{T}GT, alustettu nollamatriisiin.
  2. Kulje alkuperäisen kuvan vierekkäisyysmatriisi GGG,Tahtoa G [ i ] [ j ] G[i][j]G[i][j] Arvo on määritetty GT [ j ] [ i ] G^{T}[j][i]GT[j][i]
  3. Palauttaa uuden kaavion viereisyysmatriisin GTG^{T}GT

Aikamonimutkaisuusanalyysi: alkuperäisen kaavion viereisyysmatriisin läpikulku vaatii O ( ∣ V ∣ 2 ) O(|V|^2)O(V2) aika, joten kokonaisaika monimutkaisuus on O ( ∣ V ∣ 2 ) O(|V|^2)O(V2)

Seuraava on Go-kielellä toteutettu koodi:

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

Vierekkäin linkitetty luetteloesitys

Vierekkäisyyksiin linkitetyssä listaesityksessä voimme kulkea suoraan alkuperäisen kuvan läpi GGGKunkin solmun vierekkäisyysluettelo lisätään sitten uuteen kuvaajaan sen jälkeen, kun kunkin reunan suunta on käännetty. GTG^{T}GTvastaavassa solmussa.

Siirry kielikoodin käyttöönottoon:
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
Aika monimutkaisuusanalyysi:
  • Läpi kunkin solmun läpi alkuperäisessä kaaviossa: O ( ∣ V ∣ ) O(|V|)O(V)
  • Käy läpi kunkin solmun vierekkäisyysluettelo: O ( ∣ E ∣ ) O(|E|)O(E)

Siksi kokonaisaika monimutkaisuus on O ( ∣ V ∣ + ∣ E ∣ ) O(|V| + |E|)O(V+E)

Vierekkäisyysmatriisimerkintä

Viereisyysmatriisin merkinnöissä voimme luoda uuden viereisyysmatriisin ja kulkea sitten alkuperäisen kuvan läpi GGGviereisyysmatriisi, jokainen matriisin elementti (i, j) (i, j)(i,j)uuteen matriisiin (j , i ) (j, i)(j,i)asemaan, jolloin reunan käännös on valmis.

Siirry kielikoodin käyttöönottoon:
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
Aika monimutkaisuusanalyysi:
  • Luo uusi viereisyysmatriisi: O ( ∣ V ∣ 2 ) O(|V|^2)O(V2)
  • Kierrä alkuperäisen kuvan vierekkäisyysmatriisi: O ( ∣ V ∣ 2 ) O(|V|^2)O(V2)

Siksi kokonaisaika monimutkaisuus on O ( ∣ V ∣ 2 ) O(|V|^2)O(V2)

Tee yhteenveto

Viereisyyteen linkitetyn listaesityksen osalta transponointialgoritmin aikamonimutkaisuus on O ( ∣ V ∣ + ∣ E ∣ ) O(|V| + |E|)O(V+E), ja viereisyysmatriisiesitystä varten transponointialgoritmin aikamonimutkaisuus on O ( ∣ V ∣ 2 ) O(|V|^2)O(V2) .Käytännön sovelluksissa, jos graafi on suhteellisen harva (esim. ∣ E ∣ |E|Epaljon pienempi kuin ∣ V ∣ 2 |V|^2V2 ), olisi tehokkaampaa käyttää viereisyyteen linkitettyä listaesitystä.Jos kuvaaja on tiheä (esim. ∣ E ∣ |E|Elähellä ∣ V ∣ 2 |V|^2V2), niin viereisyysmatriisiesitys voi olla sopivampi.

Viisausspektrin selkeät sanat:

Graafiesityksessä viereisyyteen linkitetyt listat ja viereisyysmatriisit ovat molemmat yleisesti käytettyjä menetelmiä. Vierekkäisyyksiin linkitettyjä listoja käytetään edustamaan suuntaamattomia ja suunnattuja graafisia, kun taas vierekkäisyysmatriiseja käytetään yleensä edustamaan suuntaamattomia graafisia. Suunnatun graafin transponoimiseksi voimme käyttää viereisyyslinkitettyä listaa ja viereisyysmatriisia erikseen.

Siirrä vierekkäisyyksiin linkitetty luettelo

Suunnatussa graafissa, jota edustaa vierekkäisyyksiin linkitetty lista, graafin transponointi voidaan saavuttaa kulkemalla alkuperäisen graafin kunkin kärjen poikki ja muokkaamalla alkuperäisen graafin lähtevät reunat sisääntuleviksi reunoksi.

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

Viereisyysmatriisin transponointi

Viereisyysmatriisin edustaman suunnatun graafin tapauksessa graafin transponointi voidaan saavuttaa kääntämällä jokainen alkuperäisen graafin rivi uuden graafin vastaavaksi sarakkeeksi.

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

Algoritmin ajoaikaanalyysi

  1. Vierekkäisyyksiin linkitetyn listan transponointia varten algoritmin aikamonimutkaisuus on O(E), missä E on graafin reunojen lukumäärä. Tämä johtuu siitä, että jokainen reuna on ajettava kerran.

  2. Viereisyysmatriisin transponoimiseksi algoritmin aikamonimutkaisuus on O(V^2), missä V on graafin kärkien lukumäärä. Tämä johtuu siitä, että jokainen matriisielementti on ajettava kerran ja matriisin koko on V×V.
    Nämä algoritmit ovat kaikki tehokkaita ja ajettavia

Tiangong:

Toteuttaa algoritmi suunnatun graafin laskemiseksi GGG siirtäminen osaksi kansallista lainsäädäntöä GTG^{T}GT , voimme käsitellä vierekkäisyyksiin linkitetyn listan ja viereisyysmatriisin kaksi esitystä. Alla kuvailen näiden kahden tapauksen algoritmeja ja annan koodiesimerkkejä Go-kielellä.

Vierekkäin linkitetty luetteloesitys

Algoritmin vaiheet:
  1. Luo uusi vierekkäisyysluettelo newAdjList Käytetään transponoidun graafin tallentamiseen.
  2. Käy läpi alkuperäisen kuvan vierekkäisyyksiin linkitetty luettelo adjList
  3. jokaiselle reunalle (u, v), lisää se joukkoon newAdjList[v] keskellä.
  4. Palauttaa uuden vierekkäisyysluettelon newAdjList
Siirry kielikoodiesimerkkiin:
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
Ajoaika-analyysi:

Tämän algoritmin ajoaika on O(|V| + |E|), jossa |V| on kärkien lukumäärä ja |E|. Tämä johtuu siitä, että meidän täytyy kulkea kaikki kärjet ja reunat kerran.

Vierekkäisyysmatriisimerkintä

Algoritmin vaiheet:
  1. Luo uusi viereisyysmatriisi newAdjMatrix Käytetään transponoidun graafin tallentamiseen.
  2. Kulje alkuperäisen kuvan vierekkäisyysmatriisi adjMatrix
  3. jokaiselle elementille adjMatrix[i][j], määritä se newAdjMatrix[j][i]
  4. Palauttaa uuden viereisyysmatriisin newAdjMatrix
Siirry kielikoodiesimerkkiin:
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
Ajoaika-analyysi:

Tämän algoritmin ajoaika on O(|V|^2), jossa |V| on pisteiden lukumäärä. Tämä johtuu siitä, että meidän täytyy kulkea koko viereisyysmatriisin läpi ja vierekkäisyysmatriisin koko on|V| x |V|.

Yllä oleva koodiesimerkki on vain algoritmin ydinosa Varsinaisissa sovelluksissa saattaa olla tarpeen lisätä muita toimintoja, kuten virheiden käsittelyä, syöttöä ja tulostusta. Lisäksi koodin yksinkertaistamiseksi oletetaan, että graafissa ei ole toistuvia reunoja ja pistenumerot numeroidaan peräkkäin 0:sta alkaen.

chatgpt:

Seuraavassa on Go-kielellä kirjoitettu algoritmi G^T:n laskemiseksi graafista G, ja myös vastaavat vierekkäisyydet linkitetty lista ja viereisyysmatriisiesitystavat on annettu:

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

Tämän algoritmin aikamonimutkaisuus on O(V + E), missä V on kärkien lukumäärä ja E on reunojen lukumäärä. Transponoidun graafin konstruointi edellyttää alkuperäisen graafin kaikkien reunojen läpikulkua ja niiden lisäämistä transponoituun graafiin käänteisesti, joten kokonaisaikamonimutkaisuus on verrannollinen kärkien ja reunojen lukumäärään.

kimi:

Suunnattujen graafien transponoidut graafit voidaan esittää kahdella päätietorakenteella: viereisyyteen linkitetyillä listoilla ja viereisyysmatriiseilla. Alla esittelen algoritmit näissä kahdessa tapauksessa ja toimitan esimerkkikoodin Go-kielellä.

Vierekkäin linkitetty luetteloesitys

Graafille, jota edustaa vierekkäisyyksiin linkitetty luettelo, voimme transponoida graafin kulkemalla kunkin kärjen vierekkäisyysluettelon läpi ja lisäämällä sitten käänteisreunan jokaiseen viereisyyspisteeseen. Tämän menetelmän aikamonimutkaisuus on O(V + E), jossa V on kärkien lukumäärä ja E on reunojen lukumäärä.

Siirry kielimallikoodiin:
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

Vierekkäisyysmatriisiesitys

Viereisyysmatriisin edustaman graafin tapauksessa voimme toteuttaa transponoinnin vaihtamalla matriisin rivejä ja sarakkeita. Tämän menetelmän aikamonimutkaisuus on O(V^2).

Siirry kielimallikoodiin:
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

Algoritmien analyysi

  • läheisyysluettelo : Algoritmin tulee kulkea kunkin kärjen viereisyysluettelon läpi, ja jokaiselle reunalle on lisättävä käänteinen reuna viereisen pisteen viereisyysluetteloon. Jos naapurilistan keskimääräinen pituus on k, on algoritmin aikakompleksisuus O(V + E * k). Pahimmassa tapauksessa k voi olla lähellä V:tä ja aikakompleksisuus on lähellä O(V^2). Parhaimmassa tapauksessa k on lähellä 1:tä ja aikakompleksisuus on lähellä O(E).
  • viereisyysmatriisi : Algoritmin täytyy käydä läpi jokainen matriisin elementti ja vaihtaa rivit ja sarakkeet. Koska matriisi on VxV, aikamonimutkaisuus on O(V^2).

Käytännön sovelluksissa valitaan algoritmi riippuu graafin harvaksesta ja käytettävissä olevasta muistista. Harvassa graafissa vierekkäisyyteen linkitetyt listat voivat olla muistitehokkaampia tiheissä kaavioissa, viereisyysmatriisit voivat olla tehokkaampia.

Hunyuan:

Suunnatun graafin laskeminen G = ( V , E ) G= (V, E)G=(V,E) siirtäminen osaksi kansallista lainsäädäntöä GT = ( V , ET ) G^T=(V,E^T)GT=(V,ET), voimme antaa vastaavat algoritmit vierekkäisyyksiin linkitetyn listan ja viereisyysmatriisin kahdelle esitysmenetelmälle ja analysoida niiden ajoaikaa.

Vierekkäin linkitetty luetteloesitys

Algoritmin kuvaus
  1. Alusta tyhjä vierekkäisyysluettelo tallentaaksesi transponoidun graafin reunat.
  2. Siirrä alkuperäinen kuva poikki GGG kaikista solmuista.
  3. jokaiselle solmulle uuu, kulkee kaikkien viereisyysluettelonsa naapurisolmujen läpi vvv
  4. Lisää uusi vierekkäisyysluettelo kohteesta vvv saapua uuu puolella.
  5. Kun läpikulku on suoritettu, uusi vierekkäisyyksiin linkitetty luettelo on transponoitu graafi GTG^TGT
Ajoaika-analyysi
  • aika monimutkaisuus: O ( ∣ E ∣ ) O(|E|)O(E),sisään ∣ E ∣ |E|E on alkuperäisen kuvan sivujen lukumäärä. Koska meidän täytyy kulkea jokainen reuna kahdesti (kerran lukea ja kerran kirjoittaa).

Vierekkäisyysmatriisimerkintä

Algoritmin kuvaus
  1. Alusta lähetysmatriisi, joka on samankokoinen kuin alkuperäinen kuvaaja tallentaaksesi transponoidun graafin reunat.
  2. Siirrä alkuperäinen kuva poikki GGG viereisyysmatriisi.
  3. Jokaiselle matriisin nollasta poikkeavalle elementille (eli on reuna ( u , v ) (u, v)(u,v)), vastaava sijainti transponoidun graafin vierekkäisyysmatriisissa ( v , u ) (v, u)(v,u) Aseta nollasta poikkeava elementti.
  4. Kun läpikulku on suoritettu, uusi viereisyysmatriisi on transponoitu graafi GTG^TGT
Ajoaika-analyysi
  • aika monimutkaisuus: O ( ∣ V ∣ 2 ) O(|V|^2)O(V2),sisään ∣ V ∣ |V|V on solmujen lukumäärä alkuperäisessä kaaviossa. Koska meidän täytyy kulkea koko viereisyysmatriisi.

Siirry-kielitoteutus (viereinen linkitetyn luettelon esitys)

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

Tässä koodissa määrittelemme a Edge rakenne edustamaan reunoja, ja aAdjacencyList Rakenne, joka edustaa vierekkäisyyteen linkitettyä luetteloa.TransposeGraph Funktio hyväksyy aAdjacencyList type-parametrin ja palauttaa transponoidun graafin viereisyyteen linkitetyn luetteloesityksen.olla olemassamain -funktion avulla luomme esimerkkikaavion, laskemme ja tulostamme sen transponoidun kaavion.