图算法 广度优先和深度优先递归与非递归

  • 图算法 广度优先和深度优先递归与非递归

  • 测试

package mm

import "testing"

func TestAdjacencyLists_Adjacent(t *testing.T) {
	l := NewAdjacencyLists(10)
	l.InsertEdge(&Vertex{index: 0},&Vertex{index: 1})
	l.InsertEdge(&Vertex{index: 0},&Vertex{index: 2})
	l.InsertEdge(&Vertex{index: 1},&Vertex{index: 3})
	l.InsertEdge(&Vertex{index: 1},&Vertex{index: 4})
	l.InsertEdge(&Vertex{index: 2},&Vertex{index: 5})
	l.InsertEdge(&Vertex{index: 2},&Vertex{index: 6})
	l.InsertEdge(&Vertex{index: 3},&Vertex{index: 7})
	l.InsertEdge(&Vertex{index: 4},&Vertex{index: 7})
	l.InsertEdge(&Vertex{index: 5},&Vertex{index: 7})
	l.InsertEdge(&Vertex{index: 6},&Vertex{index: 7})
	l.InsertEdge(&Vertex{index: 6},&Vertex{index: 7})
	l.InsertEdge(&Vertex{index: 0},&Vertex{index: 8})
	l.InsertEdge(&Vertex{index: 0},&Vertex{index: 9})

	l.Print()
	t.Log(l.dfs())
	t.Log(l.dfsRecursion())
	t.Log(l.bfs())
}
  • 深度优先算法递归实现
    • 从顶点v开始,依次对顶点v的邻接链表顶点做深度优先搜索
    • [0 1 3 7 4 5 2 6 8 9]
func dfsRecursion(l *AdjacencyLists) []int {
	var fRecv func(v *Vertex)
	visited := make([]bool, len(l.vertexes))
	var res []int
	fRecv = func(v *Vertex) {
		if !visited[v.index] {
			res = append(res, v.index)
			visited[v.index] = true
		}
		for v.next != nil {
			if !visited[v.next.index] {
				fRecv(l.vertexes[v.next.index])
			}
			v = v.next
		}
	}
	fRecv(l.vertexes[0])
	return res
}
  • 深度优先算法非递归实现
    • 1.随便把一个顶点推入栈中
    • 2.从栈中弹出一个顶点或链表v,如果未访问,加入访问数组
    • 3.从顶点v当前的邻接表(头结点不一定是v)依次选取一个未访问的顶点w1、w2,对w1进行深度优先搜索,如果w2存在,先把w2入栈,再把以w1为头结点的顶点入栈。
    • 4.当最终搜索到一个顶点u,且u的邻接表中的顶点全部被访问过,就从栈中取出一个链表继续上述步骤2,直到栈为空,搜索结束
    • [0 1 3 7 4 5 2 6 8 9]
func dfs(l *AdjacencyLists) []int {
	var result []int
	var fStack func(index int)
	s := stack()
	fStack = func(index int) {
		visited := make([]bool, len(l.vertexes))
		s.stackPush(l.vertexes[index])
		for !s.stackEmpty() {
			temp, _ := s.stackPop()
			if !visited[temp.index] {
				result = append(result, temp.index)
				visited[temp.index] = true
			}
			temp1 := temp.next
			for temp1 != nil {
				if !visited[temp1.index] {
					if temp1.next != nil {
						s.stackPush(temp1.next) // 链表先入栈
					}
					s.stackPush(l.vertexes[temp1.index]) // 头结点入栈
					break
				}
				temp1 = temp1.next
			}
		}
	}
	fStack(0)
	return result
}
  • 广度优先算法
    • 顶点v入队列
    • 2.从队列弹出一个顶点w。依次访问w的所有节点wt,如果wt未访问,将其加入访问数组result,将其头结点链加入队列
    • 3.重复2
    • [0 1 2 8 9 3 4 5 6 7]
func bfs(l *AdjacencyLists) []int {
	var result []int
	var fQueue func(index int)
	q := queue()
	fQueue = func(index int) {
		visited := make([]bool, len(l.vertexes))
		q.addq(l.vertexes[index])
		for !q.emptyq() {
			temp, _ := q.deleteq()
			for temp != nil {
				if !visited[temp.index] {
					result = append(result, temp.index)
					visited[temp.index] = true
					q.addq(l.vertexes[temp.index])
				}
				temp = temp.next
			}
		}
	}
	fQueue(0)
	return result
}
type stackArr struct {
	stackArr []*Vertex
}

func stack() *stackArr {
	return &stackArr{}
}
func (l *stackArr) stackEmpty() bool {
	return len(l.stackArr) == 0
}
func (l *stackArr) stackClear() {
	l.stackArr = nil
}
func (l *stackArr) stackPush(v *Vertex) {
	l.stackArr = append(l.stackArr, v)
}
func (l *stackArr) stackPop() (v *Vertex, ok bool) {
	if l.stackEmpty() {
		return
	}
	v = l.stackArr[len(l.stackArr)-1]
	l.stackArr = l.stackArr[:len(l.stackArr)-1]
	return v, true
}
  • 队列
type queueArr struct {
	queueArr []*Vertex
}
func queue() *queueArr {
	return &queueArr{}
}
func (l *queueArr) deleteq() (v *Vertex, ok bool) {
	if l.emptyq() {
		return
	}
	v = l.queueArr[0]
	l.queueArr = l.queueArr[1:]
	return v, true
}
func (l *queueArr) addq(v *Vertex) {
	l.queueArr = append(l.queueArr, v)
}
func (l *queueArr) emptyq() bool {
	return len(l.queueArr) == 0
}
func (l *queueArr) clearq() {
	l.queueArr = nil
}
  • 图的基本操作
package mm
import "fmt"
type Vertex struct {
	index int
	next  *Vertex
}

type AdjacencyLists struct {
	vertexes []*Vertex
}

func NewAdjacencyLists(size int) *AdjacencyLists {
	return &AdjacencyLists{
		vertexes: make([]*Vertex, size),
	}
}

// InsertVertex 向图中插入没有关联边的新顶点v
func (l *AdjacencyLists) InsertVertex(v *Vertex) {
	l.vertexes[v.index] = v
}

// DeleteVertex 删除图中的顶点v及其关联的所有边
func (l *AdjacencyLists) DeleteVertex(v *Vertex) {
	list := l.vertexes[v.index]
	for list.next != nil {
		temp := l.vertexes[list.next.index]
		for temp.next != nil {
			if temp.next.index == v.index {
				temp.next = temp.next.next
			} else {
				temp = temp.next
			}
		}
		list = list.next
	}
	l.vertexes[v.index] = nil
}

// DeleteEdge 删除图中边(v1,v2),顶点v1,v2不删除
func (l *AdjacencyLists) DeleteEdge(v1, v2 *Vertex) {
	temp1 := l.vertexes[v1.index]
	for temp1.next != nil {
		if temp1.next.index == v2.index {
			temp1.next = temp1.next.next
		} else {
			temp1 = temp1.next
		}
	}
	temp2 := l.vertexes[v2.index]
	for temp2.next != nil {
		if temp2.next.index == v1.index {
			temp2.next = temp2.next.next
		} else {
			temp2 = temp2.next
		}
	}
}

func (l *AdjacencyLists) IsEmpty() bool {
	result := true
	for _, v := range l.vertexes {
		if v != nil {
			result = false
			break
		}
	}
	return result
}

// Adjacent 顶点v的所有邻接节点
func (l *AdjacencyLists) Adjacent(v *Vertex) []*Vertex {
	return l.vertexes
}

func (l *AdjacencyLists) Print() {
	fmt.Println("--------------------------------")
	for k, v := range l.vertexes {
		fmt.Printf("%d: ", k)
		for v != nil {
			if v.next != nil {
				fmt.Printf("%d=>", v.index)
			} else {
				fmt.Printf("%d", v.index)
			}
			v = v.next
		}
		fmt.Println()
	}
	fmt.Println("--------------------------------")
}

// InsertEdge 向图的顶点v1和v2之间插入一条边
func (l *AdjacencyLists) InsertEdge(v1, v2 *Vertex) {
	temp1 := l.vertexes[v1.index]
	if temp1 == nil {
		l.vertexes[v1.index] = &Vertex{index: v1.index}
		temp1 = l.vertexes[v1.index]
	}
	for temp1.next != nil {
		if temp1.next.index == v2.index { // 不添加重复节点
			return
		}
		temp1 = temp1.next
	}
	temp1.next = v2

	temp2 := l.vertexes[v2.index]
	if temp2 == nil {
		l.vertexes[v2.index] = &Vertex{index: v2.index}
		temp2 = l.vertexes[v2.index]
	}
	for temp2.next != nil {
		if temp2.next.index == v1.index { // 不添加重复节点
			return
		}
		temp2 = temp2.next
	}
	temp2.next = v1
}

参考 数据结构(c语言版)

上一篇:python爬虫实例大全


下一篇:细数 C++ 那些比起 C语言 更爽的特性