Обмен технологиями

Вэнь Синь И Ян VS iFlytek Spark VSchatgpt (300) — Введение в алгоритмы 22.1 4 вопроса

2024-07-12

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

4. Учитывая несколько картинок Г = ( В , Э ) Г=(В,Э)г=(В,Э)связанный список смежности (мультиграф — это граф, который допускает повторяющиеся и самозацикливающиеся ребра), укажите время О ( В + Э ) О(В+Э)О(В+Э)алгоритм, используемый для расчета «эквивалентного» неориентированного графа графа G ′ = ( V , E ′ ) G^{'}=(V,E^{'})г=(В,Э) представлено связным списком смежности.здесь Э ′ Э^{'}ЭЭто будет ЭЭЭ Лишние ребра и оставшиеся ребра после удаления ребер с самопетлей. Удаление оставшихся ребер означает замену нескольких ребер между двумя узлами одним ребром. Если вы хотите писать код, используйте язык go.

Слова Вэнь Синя:

Представление связанного списка смежности

В представлении связанного списка смежности каждая вершина ввв Существует связанный список, и каждый узел в связанном списке представляет собой подчиненное устройство. ввв Стартовый край.чтобы вычислить ГТГ^ТгТ, нам нужно пересечь ГАРАНТИРОВАННАЯ ПОБЕДАг для каждого ребра и, изменив направление ребра, прибавьте к ГТГ^ТгТ в соответствующем связанном списке.

Реализация языка Go

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

временная сложность

  • Временная сложность прохождения каждого ребра равна О ( Э ) О(Э)О(Э) ЭЭЭ это количество ребер.
  • Для каждого ребра мы выполняем операцию за постоянное время (добавление в список смежности другого графа).
  • Следовательно, общая временная сложность равна О ( Э ) О(Э)О(Э)

Представление матрицы смежности

В представлении матрицы смежности мы используем двумерный массив для хранения информации о краях, где matrix[u][v] Указывает, есть ли линия от ууты приезжать ввв сторона.чтобы вычислить ГТГ^ТгТ, мы пересекаем верхний треугольник (или нижний треугольник, в зависимости от ваших привычек к представлению матрицы) матрицы и меняем направление ребер, то есть: matrix[u][v] Значение присваиваетсяmatrixT[v][u]

Реализация языка Go(Упрощенная версия учитывает только существование и не учитывает веса ребер):

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

временная сложность

  • Итерация по каждому элементу матрицы требует О ( V 2 ) О(V^2)О(В2) время, среди которого ВВВ это количество вершин.
  • Следовательно, общая временная сложность равна О ( V 2 ) О(V^2)О(В2) . Это может оказаться не самым эффективным, если количество вершин намного превышает количество ребер.

Вставьте сюда описание изображения

Вставьте сюда описание изображения

Вставьте сюда описание изображения

Вставьте сюда описание изображения

iFlytek Спарк:

Для ориентированного графа, представленного списком смежности, мы можем добавить соседние вершины каждой вершины в список смежности транспонированной вершины нового графа, просматривая список смежности каждой вершины. Конкретные шаги заключаются в следующем:

  1. Создать новый список смежности ГТГ^{Т}гТ, инициализирован как пустой.
  2. Обход исходного изображения ГАРАНТИРОВАННАЯ ПОБЕДАг каждая вершина ввв
  3. Обход вершин ввв связанный список смежности, каждая соседняя вершина ууты Добавить к новому изображению ГТГ^{Т}гТ средняя вершина ввв в связанном списке смежности.
  4. Вернуться к новой картинке ГТГ^{Т}гТ

Анализ временной сложности: для обхода каждой вершины исходного графа требуется О ( ∣ V ∣ ) О(|V|)О(В) Время, необходимое для обхода списка смежности каждой вершины, равно О ( ∣ Е ∣ ) О(|Е|)О(Э) время, поэтому общая временная сложность равна О ( ∣ V ∣ + ∣ E ∣ ) О(|V| + |E|)О(В+Э)

Для ориентированного графа, представленного матрицей смежности, мы можем получить матрицу смежности нового графа, транспонировав матрицу смежности исходного графа. Конкретные шаги заключаются в следующем:

  1. Создайте новый с размером ∣ V ∣ × ∣ V ∣ |V| раз |V|В×В матрица ГТГ^{Т}гТ, инициализированный нулевой матрицей.
  2. Перейдите матрицу смежности исходного изображения ГАРАНТИРОВАННАЯ ПОБЕДАг,Воля Г [ я ] [ дж ] Г[и][дж]г[я][дж] Значение присваивается ГТ [ дж ] [ я ] Г^{Т}[дж][я]гТ[дж][я]
  3. Возвращает матрицу смежности нового графа ГТГ^{Т}гТ

Анализ временной сложности: для обхода матрицы смежности исходного графа требуется О ( ∣ V ∣ 2 ) О(|V|^2)О(В2) время, поэтому общая временная сложность равна О ( ∣ V ∣ 2 ) О(|V|^2)О(В2)

Ниже приведен код, реализованный на языке 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

360 Интеллектуальный мозг:

Представление связанного списка смежности

В представлении связанного списка смежности мы можем напрямую перемещаться по исходному изображению. ГАРАНТИРОВАННАЯ ПОБЕДАгСписок смежности каждого узла затем добавляется в новый граф после изменения направления каждого ребра на противоположное. ГТГ^{Т}гТна соответствующем узле.

Реализация кода языка Go:
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
Анализ временной сложности:
  • Пройдите каждый узел исходного графа: О ( ∣ V ∣ ) О(|V|)О(В)
  • Просмотрите список смежности каждого узла: О ( ∣ Е ∣ ) О(|Е|)О(Э)

Следовательно, общая временная сложность равна О ( ∣ V ∣ + ∣ E ∣ ) О(|V| + |E|)О(В+Э)

Обозначение матрицы смежности

В обозначении матрицы смежности мы можем создать новую матрицу смежности, а затем пройти по исходному изображению. ГАРАНТИРОВАННАЯ ПОБЕДАгматрица смежности, каждый элемент матрицы ( я , дж ) ( я , дж )(я,дж)присвоено новой матрице ( дж , я ) (дж, я)(дж,я)положение, тем самым завершая инверсию края.

Реализация кода языка Go:
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
Анализ временной сложности:
  • Создайте новую матрицу смежности: О ( ∣ V ∣ 2 ) О(|V|^2)О(В2)
  • Перейдите матрицу смежности исходного изображения: О ( ∣ V ∣ 2 ) О(|V|^2)О(В2)

Следовательно, общая временная сложность равна О ( ∣ V ∣ 2 ) О(|V|^2)О(В2)

Подведем итог

Для представления связанного списка смежности временная сложность алгоритма транспонирования равна О ( ∣ V ∣ + ∣ E ∣ ) О(|V| + |E|)О(В+Э), а для представления матрицы смежности временная сложность алгоритма транспонирования равна О ( ∣ V ∣ 2 ) О(|V|^2)О(В2) .В практических приложениях, если граф относительно разрежен (т. ∣ Е ∣ |Е|Энамного меньше, чем ∣ В ∣ 2 |В|^2В2 ), было бы более эффективно использовать представление связанного списка смежности.Если граф плотный (т. ∣ Е ∣ |Е|Эоколо ∣ В ∣ 2 |В|^2В2), то представление матрицы смежности может быть более подходящим.

Спектр мудрости ясные слова:

В графовом представлении часто используются связанные списки смежности и матрицы смежности. Связанные списки смежности используются для представления неориентированных и ориентированных графов, тогда как матрицы смежности обычно используются для представления неориентированных графов. Для транспонирования ориентированного графа мы можем работать со связным списком смежности и матрицей смежности отдельно.

Транспонирование связанного списка смежности

Для ориентированного графа, представленного связным списком смежности, транспонирование графа может быть достигнуто путем обхода каждой вершины исходного графа и изменения исходящих ребер исходного графа во входящие.

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

Транспонирование матрицы смежности

Для ориентированного графа, представленного матрицей смежности, транспонирование графа может быть достигнуто путем превращения каждой строки исходного графа в соответствующий столбец нового графа.

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

Анализ времени работы алгоритма

  1. Для транспонирования связного списка смежности временная сложность алгоритма равна O(E), где E — количество ребер в графе. Это связано с тем, что каждое ребро необходимо пройти один раз.

  2. Для транспонирования матрицы смежности временная сложность алгоритма равна O(V^2), где V — количество вершин в графе. Это связано с тем, что каждый элемент матрицы необходимо пройти один раз, а размер матрицы равен V×V.
    Все эти алгоритмы эффективны и работают.

Тяньгун:

Чтобы реализовать алгоритм вычисления ориентированного графа ГАРАНТИРОВАННАЯ ПОБЕДАг транспозиция ГТГ^{Т}гТ , мы можем обработать два представления связанного списка смежности и матрицы смежности соответственно. Ниже я опишу алгоритмы для этих двух случаев соответственно и приведу примеры кода на языке Go.

Представление связанного списка смежности

Шаги алгоритма:
  1. Создать новый список смежности newAdjList Используется для хранения транспонированного графа.
  2. Перейдите по связанному списку смежности исходного изображения. adjList
  3. для каждого края (u, v), добавьте это в newAdjList[v] середина.
  4. Возвращает новый список смежности newAdjList
Пример кода языка Go:
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
Анализ времени выполнения:

Время работы этого алгоритма равно O(|V| + |E|), где |V| — количество вершин, а |E| — количество ребер. Это потому, что нам нужно один раз пройти все вершины и ребра.

Обозначение матрицы смежности

Шаги алгоритма:
  1. Создайте новую матрицу смежности newAdjMatrix Используется для хранения транспонированного графа.
  2. Перейдите матрицу смежности исходного изображения adjMatrix
  3. для каждого элемента adjMatrix[i][j], назначьте его newAdjMatrix[j][i]
  4. Возвращает новую матрицу смежности newAdjMatrix
Пример кода языка Go:
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
Анализ времени выполнения:

Время работы этого алгоритма равно O(|V|^2), где |V| — количество вершин. Это связано с тем, что нам нужно пройти всю матрицу смежности, а размер матрицы смежности равен |V| x |V|.

Приведенный выше пример кода является лишь основной частью алгоритма. В реальных приложениях может потребоваться добавление других функций, таких как обработка ошибок, ввод и вывод. Кроме того, для упрощения кода предполагается, что в графе нет повторяющихся ребер и номера вершин нумеруются последовательно, начиная с 0.

чатгпт:

Ниже приведен алгоритм, написанный на языке Go для расчета G^T на основе графа G, а также приведены соответствующие методы представления связанного списка смежности и матрицы смежности:

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

Временная сложность этого алгоритма равна O(V + E), где V — количество вершин, а E — количество ребер. Процесс построения транспонированного графа требует обхода всех ребер исходного графа и добавления их к транспонированному графу в обратном порядке, поэтому общая временная сложность пропорциональна количеству вершин и ребер.

Кими:

Транспонированные графы ориентированных графов могут быть представлены двумя основными структурами данных: связанными списками смежности и матрицами смежности. Ниже я представлю алгоритмы для этих двух случаев соответственно и приведу пример кода на языке Go.

Представление связанного списка смежности

Для графа, представленного связным списком смежности, мы можем транспонировать граф, пройдя по списку смежности каждой вершины, а затем добавив обратное ребро к каждой точке смежности. Временная сложность этого метода составляет O(V + E), где V — количество вершин, а E — количество ребер.

Пример кода языка Go:
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

Представление матрицы смежности

Для графа, представленного матрицей смежности, мы можем реализовать транспонирование, поменяв местами строки и столбцы матрицы. Временная сложность этого метода составляет O(V^2).

Пример кода языка Go:
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

Анализ алгоритмов

  • список смежности : Алгоритму необходимо пройти по списку смежности каждой вершины, и для каждого ребра необходимо добавить обратное ребро в список смежности соседней точки. Если средняя длина списка соседей равна k, временная сложность алгоритма равна O(V + E * k). В худшем случае k может быть близко к V, а временная сложность близка к O(V^2). В лучшем случае k близко к 1, а временная сложность близка к O(E).
  • матрица смежности : Алгоритму необходимо пройтись по каждому элементу матрицы и поменять местами строки и столбцы. Поскольку матрица имеет размер VxV, временная сложность равна O(V^2).

В практических приложениях выбор алгоритма зависит от разреженности графа и доступной памяти. Для разреженных графов связанные списки смежности могут быть более эффективными с точки зрения использования памяти; для плотных графов более эффективными могут быть матрицы смежности;

Хунюань:

Чтобы вычислить ориентированный граф Г = ( В , Э ) Г=(В,Э)г=(В,Э) транспозиция GT = ( V , ET ) G^T=(V,E^T)гТ=(В,ЭТ), мы можем предоставить соответствующие алгоритмы для двух методов представления связного списка смежности и матрицы смежности соответственно и проанализировать время их работы.

Представление связанного списка смежности

Описание алгоритма
  1. Инициализируйте пустой список смежности для хранения ребер транспонированного графа.
  2. Обход исходного изображения ГАРАНТИРОВАННАЯ ПОБЕДАг всех узлов.
  3. для каждого узла ууты, пройти все соседние узлы в своем списке смежности ввв
  4. Добавьте новый список смежности из ввв приезжать ууты сторона.
  5. После завершения обхода новый связанный список смежности представляет собой транспонированный граф. ГТГ^ТгТ
Анализ времени выполнения
  • временная сложность: О ( ∣ Е ∣ ) О(|Е|)О(Э) ∣ Е ∣ |Е|Э — количество сторон исходного изображения. Потому что нам нужно пройти каждое ребро дважды (один раз для чтения и один раз для записи).

Обозначение матрицы смежности

Описание алгоритма
  1. Инициализируйте матрицу смежности того же размера, что и исходный граф, чтобы сохранить ребра транспонированного графа.
  2. Обход исходного изображения ГАРАНТИРОВАННАЯ ПОБЕДАг матрица смежности.
  3. Для каждого ненулевого элемента матрицы (т.е. существует ребро ( у , в ) (у, в)(ты,в)), соответствующая позиция в матрице смежности транспонированного графа (в, у) (в, у)(в,ты) Установите ненулевой элемент.
  4. После завершения обхода новая матрица смежности представляет собой транспонированный граф ГТГ^ТгТ
Анализ времени выполнения
  • временная сложность: О ( ∣ V ∣ 2 ) О(|V|^2)О(В2) ∣ В ∣ |В|В — количество узлов в исходном графе. Потому что нам нужно пройти всю матрицу смежности.

Реализация языка Go (представление смежного связанного списка)

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

В этом коде мы определяем Edge структура для представления ребер иAdjacencyList Структура для представления связанного списка смежности.TransposeGraph Функция принимаетAdjacencyList type и возвращает представление связанного списка смежности транспонированного графа.существоватьmain функции мы создаем пример графика, вычисляем и печатаем его транспонированный график.