nber1994



leetcode-图

June 18, 2019

leetcode-图

表示方式

package main

import (
	"fmt"
)

func main() {

	g := graph{}
	n1, n2, n3, n4, n5 := node{1}, node{2}, node{3}, node{4}, node{5}

	g.addNode(&n1)
	g.addNode(&n2)
	g.addNode(&n3)
	g.addNode(&n4)
	g.addNode(&n5)

	g.addEdge(&n1, &n2)
	g.addEdge(&n1, &n5)
	g.addEdge(&n2, &n3)
	g.addEdge(&n2, &n4)
	g.addEdge(&n2, &n5)
	g.addEdge(&n3, &n4)
	g.addEdge(&n4, &n5)

	g.string()
	g.BFS()
	g.DFS()
}

type node struct {
	val int
}

type graph struct {
	nodes []*node
	//使用邻接表来存储关系
	edges map[node][]*node
}

func (g *graph) addNode(n *node) {
	g.nodes = append(g.nodes, n)
}

func (g *graph) addEdge(u, v *node) {
	if g.edges == nil {
		g.edges = map[node][]*node{}
	}
	g.edges[*u] = append(g.edges[*u], v)
	g.edges[*v] = append(g.edges[*v], u)
}

func (g *graph) string() {
	str := ""
	for _, v := range g.nodes {
		str += v.string() + "->"
		for _, val := range g.edges[*v] {
			str += val.string() + " "
		}
		str += "\n"
	}
	fmt.Println(str)
}

func (n *node) string() string {
	return fmt.Sprintf("%s", n.val)
}

//bfs遍历
func (g *graph) BFS() {
	//将第一个节点加入到队列中
	head := g.nodes[0]
	queue := []*node{head}
	visitedMap := map[*node]bool{}
	visitedMap[head] = true
	for len(queue) > 0 {
		//模拟出队列
		item := queue[len(queue)-1]
		queue = queue[:len(queue)-1]
		for _, v := range g.edges[*item] {
			if boolean, exist := visitedMap[v]; exist && boolean {
				continue
			}
			queue = append([]*node{v}, queue...)
			visitedMap[v] = true
		}
		//这个地方可以进行一些操作,例如拷贝等
		fmt.Println(item.val)
	}
}

//dfs遍历
func (g *graph) DFS() {
	//将第一个节点加入到栈中
	head := g.nodes[0]
	stack := []*node{head}
	visitMap := map[*node]bool{}
	visitMap[head] = true
	for len(stack) > 0 {
		item := stack[0]
		stack = stack[1:]
		for _, v := range g.edges[*item] {
			if boolean, exist := visitMap[v]; exist && boolean {
				continue
			}
			stack = append([]*node{v}, stack...)
			visitMap[v] = true
		}
		fmt.Println(item.val)
	}
}

type Node struct {
	val   int
	edges []*Node
}

//深度拷贝无向图
//dfs深度遍历, 同时维护一个新旧node的map表来拷贝edges
func cloneGraph(head *Node) *Node {
	nodeMap := map[*Node]*Node{}
	visitMap := map[*Node]bool{}
	nodeMap[head] = true
	nodeMap[head] = &Node{
		head.val,
		[]*Node{},
	}
	stack := []int{}
	for len(stack) > 0 {
		item := stack[0]
		stack = stack[1:]
		for _, v := range item.edeges {
			if boolean, exist := visitMap[v]; boolean && exist {
				continue
			}
			//入栈并且复制节点
			stack = append([]*Node{v}, stack...)
			nodeMap[v] = &Node{
				v.val,
				[]*Node{},
			}
			item.edges = append(item.edges, nodeMap[v])
			visitMap[v] = true
		}
	}
	return nodeMap[head]
}

//判断是否有环
dfs遍历时如果存在两次访问一个点时则有环