The data structures and algorithms of FIG.

Traversing Graph

  • Depth-first traversal
    is somewhat similar to a preorder traversal, traversing from one of the vertices, the vertices are visited on the accessed cook mark, then iterate through all neighboring any vertices of this vertex and not a visited vertex, and cook mark has been accessed, then to the point as a new starting point to continue a depth-first search.
    This method combines the techniques of recursive traversal and two data structures stack, since this method will cause an infinite loop, it is necessary to add a variable to determine whether the point has been traversed completed.
class Node:
    def __init__(self):
        self.val = 0
        self.next = None

head = [Node()] * 9
run = [0] * 9

def dfs(current):
    run[current] = 1
    print("[%d] " % current, end='')
    ptr = head[current].next
    while ptr != None:
        if run[ptr.val] == 0:  # 该顶点未遍历
            dfs(ptr.val)
        ptr = ptr.next

# 声明图的边线数组
data = [
    [1, 2], [2, 1], [1, 3], [3, 1],
    [2, 4], [4, 2], [2, 5], [5, 2],
    [3, 6], [6, 3], [3, 7], [7, 3],
    [4, 8], [8, 4], [5, 8], [8, 5],
    [6, 8], [8, 6], [7, 8], [8, 7]
]

for i in range(1, 9):
    run[i] = 0
    head[i] = Node()
    head[i].val = i  # 给各个链表头设置初值
    head[i].next = None
    ptr = head[i]
    for j in range(20):  # 20条边线
        if data[j][0] == i:  # 如果起点和链表头相等,就把顶点加入链表
            newnode = Node()
            newnode.val = data[j][1]
            newnode.next = None
            while True:  # 这样写有什么优势?
                ptr.next = newnode  # 加入新节点
                ptr = ptr.next
                if ptr.next == None:
                    break

print("图的邻接表内容:")
for i in range(1, 9):
    ptr = head[i]
    print("顶点 %d ==> " % i, end='')
    ptr = ptr.next
    while ptr != None:
        print(" [%d] " % ptr.val, end='')
        ptr = ptr.next
    print()

print("深度优先遍历的顶点:")
dfs(1)
print()
  • Breadth-first traversal
    use recursion queue and skills. Traversing from one of the vertices, the vertices are visited cook the accessed symbols, then iterate through arbitrary and not all adjacent vertices of this vertex visited vertex, and cook mark visited, then the starting point to continue the breadth-first traversal.
MAXSIZE = 10  # 定义队列最大容量

front = -1  # 指向队列的前端
rear = -1   # 执行队列的后端

class Node:
    def __init__(self, x):
        self.val = x
        self.next = None

class GraphLink:
    def __init__(self):
        self.first = None
        self.last = None
    
    def my_print(self):
        current = self.first
        while current != None:
            print(" [%d] " % current.val, end='')
            current = current.next
        print()
    
    def insert(self, x):
        newnode = Node(x)
        if self.first == None:
            self.first = newnode
            self.last = newnode
        else:
            self.last.next = newnode
            self.last = newnode

# 入队
def enqueue(value):
    global MAXSIZE
    global rear
    global queue
    if rear >= MAXSIZE:
        return
    rear += 1
    queue[rear] = value

# 出队
def dequeue():
    global front
    global queue
    if front == rear:
        return -1
    front += 1
    return queue[front]

# 广度优先搜索
def bfs(current):
    global front
    global rear
    global Head
    global run
    enqueue(current)
    run[current] = 1
    print(" [%d] " % current, end='')
    while front != rear:  # 判断当前队列是否为空
        current = dequeue()
        tempnode = Head[current].first  # 先记录当前顶点的位置
        while tempnode != None:
            if run[tempnode.val] == 0:
                enqueue(tempnode.val)
                run[tempnode.val] = 1
                print(" [%d] " % tempnode.val, end='')
            tempnode = tempnode.next

# 声明图的边线数组
data = [[0]*2 for row in range(20)]
data = [
    [1, 2], [2, 1], [1, 3], [3, 1],
    [2, 4], [4, 2], [2, 5], [5, 2],
    [3, 6], [6, 3], [3, 7], [7, 3],
    [4, 8], [8, 4], [5, 8], [8, 5],
    [6, 8], [8, 6], [7, 8], [8, 7]
]
run = [0] * 9  # 记录个顶点是否遍历过
queue = [0] * MAXSIZE
Head = [GraphLink] * 9

print('图的邻接表内容:')
for i in range(1, 9):  # 共有8个顶点
    run[i] = 0
    print("%d ==> " %i, end='')
    Head[i] = GraphLink()
    for j in range(20):
        if data[j][0] == i:
            datanum = data[j][1]
            Head[i].insert(datanum)
    Head[i].my_print()

print("广度优先遍历的顶点:")
bfs(1)
print()

Minimum spanning tree (Minimum Cost Spanning Tree, MST)

A spanning tree graph (spanning tree) is in communication with minimal side to all vertices in the graph, without causing circuit (Cycle) tree structure.
weighted graph / network

  • Greed rules (Greedy Rule)
    1. Prim algorithm
      P's method. Of a weighted graph G = (V, E), set V = {1,2, ..., n }, is assumed that U = {1}, that is, U and V is a set of two vertices.
      Then find the set difference from the set UV generated in a vertex x, x can form the vertex of the U-sides of the minimum cost of a set point, and will not cause circuit. Then transfer the vertex set U x is added, the same procedure is repeatedly executed until the set U set equal to V (V = U) so far.
    2. Kruskal's algorithm
      K's method. The size of each side by the weights in ascending order, followed by the establishment of minimum cost spanning from the beginning edge of the lowest weights, if the added edge will cause the loop is do not give up, until the addition of the n-1 sides so far.
VERTS = 6

class Edge:
    def __init__(self):
        self.start = 0
        self.to = 0
        self.find = 0
        self.val = 0
        self.next = None

v = [0] * (VERTS+1)

def findmincost(head):
    minval = 100
    ptr = head
    while ptr != None:
        if ptr.val < minval and ptr.find == 0:
            minval = ptr.val
            retptr = ptr
        ptr = ptr.next
    retptr.find = 1
    return retptr

def mintree(head):
    global VERTS
    result = 0
    ptr = head
    for i in range(VERTS):
        v[i] = 0
    while ptr != None:
        mceptr = findmincost(head)
        v[mceptr.start] = v[mceptr.start] + 1
        v[mceptr.to] = v[mceptr.to] + 1
        if v[mceptr.start] > 1 and v[mceptr.to] > 1:
            v[mceptr.start] -= 1
            v[mceptr.to] -= 1
            result = 1
        else:
            result = 0
        if result == 0:
            print("起始顶点 [%d] -> 终止顶点 [%d] -> 路径长度 [%d]" % (mceptr.start, mceptr.to, mceptr.val))
        ptr = ptr.next

data = [
    [1, 2, 6], [1, 6, 12], [1, 5, 10],
    [2, 3, 3], [2, 4, 5], [2, 6, 8],
    [3, 4, 7], [4, 6, 11], [4, 5, 9],
    [5, 6, 16]
]

# 建立图的链表
head = None
for i in range(10):
    for j in range(1, VERTS+1):
        if data[i][0] == j:
            newnode = Edge()
            newnode.start = data[i][0]
            newnode.to = data[i][1]
            newnode.val = data[i][2]
            newnode.find = 0
            newnode.next = None
            if head == None:
                head = newnode
                head.next = None
                ptr = head
            else:
                ptr.next = newnode
                ptr = ptr.next
print('------------------------------------')
print('建立最小成本生成树:')
print('------------------------------------')
mintree(head)

Dijkstra method Fig.

Each vertex of a minimum cost required for communication with the network computing MST, but any two vertices communication path tree is not necessarily a path with the least cost.

  • Dijkstra's algorithm and the A * algorithm
    Dijkstra's algorithm - the actual weight
SIZE = 7
NUMBER = 6
INFINITE = 99999

Graph_Matrix = [[0] * SIZE for row in range(SIZE)]  # 图的数组
distance = [0] * SIZE  # 路径长度数组

def build_graph_matrix(path_cost):
    for i in range(1, SIZE):
        for j in range(1, SIZE):
            if i == j:  # 自己到自己的距离
                Graph_Matrix[i][j] = 0
            else:
                Graph_Matrix[i][j] = INFINITE
    # 存入图的边
    i = 0
    while i < SIZE:
        start_point = path_cost[i][0]  # 起点
        end_point = path_cost[i][1]  # 终点
        Graph_Matrix[start_point][end_point] = path_cost[i][2]  # 权值
        i += 1

# 单点对全部顶点的最短距离
def shortest_path(vertex1, vertex_total):
    shortest_vertex = 1  # 记录最短距离的顶点
    goal = [0] * SIZE  # 记录该点是否被选取
    for i in range(1, vertex_total + 1):
        goal[i] = 0
        distance[i] = Graph_Matrix[vertex1][i]
    goal[vertex1] = 1
    distance[vertex1] = 0

    for i in range(1, vertex_total):
        shortest_distance = INFINITE
        for j in range(1, vertex_total + 1):
            if goal[j] == 0 and shortest_distance > distance[j]:
                shortest_distance = distance[j]
                shortest_vertex = j
        
        goal[shortest_vertex] = 1
        # 计算开始顶点到各顶点的最短距离
        for j in range(vertex_total+1):
            if goal[j] == 0 and distance[shortest_vertex] + Graph_Matrix[shortest_vertex][j] < distance[j]:
                distance[j] = distance[shortest_vertex] + Graph_Matrix[shortest_vertex][j]

# global path_cost
path_cost = [
    [1, 2, 29], [2, 3, 30], [2, 4, 35],
    [3, 5, 28], [3, 6, 87], [4, 5, 42],
    [4, 6, 75], [5, 6, 97],
]
build_graph_matrix(path_cost)
shortest_path(1, NUMBER)
print('------------------------------')
print('顶点 1 到各顶点最短距离的最终结果:')
print('------------------------------')
for i in range(1, SIZE):
    print('顶点 1 到顶点 %d 的最短距离为 %d ' % (i, distance[i]))

Efficiency is not high, because looking at each vertex distance to the starting point of the process, regardless of which one point, have to calculate the actual distance between the starting point and each vertex in order to obtain a final judgment: in the end which one vertex distance from the nearest starting point . That is the algorithm has the right to look for ways to bring value to weight the shortest path between the map, simply use the breadth-first find, completely ignored a lot of useful information, this search algorithm will consume a lot of system resources, including CPU time and memory space.
A * algorithm - the actual weight and Inferred weight
combined with the Pathfinder process estimated to reach the end from the beginning to the "actual weight" and each vertex of each vertex "guess the weight" (heuristic cost) two factors that can effectively reduce the unnecessary seek operations and improve efficiency.

  • Distance evaluation function
    1. Manhattan distance (Manhattan distance): D = | x1 - x2 | + | y1 - y2 |
    2. Chebyshev distance (Chebysev distance): D = max (| x1 - x2 |, | y1 - y2 |)
    3. Euclidean geometry plane the linear distance (Euclidean distance): D = ((x1 - x2) ^ 2 + (y1 - y2) ^ 2) ^ 1/2
  • A * algorithm main steps
    1. First, determine each vertex to the end "speculation weights." "Estimated weight" may be the straight-line distance (the value after rounding) between each vertex and end points, calculating a function of linear distance, the above-described one can be used.
    2. Weights were calculated from the start point of each vertex can arrive weight, which is calculated from the starting point to the "actual weight" of the vertex, the vertex plus reach the end of the "weight estimation." After the calculation is complete, select the weight of the smallest point, and the point marked as completed look.
    3. Is then calculated from the vertex to the right look finished weight of each vertex, and which is selected from a smallest weight vertices, and then look for its vertices marked completed. And so on. . . , The same calculation process is repeated until the reach the final destination.

When the A * algorithm can be applied to prior or estimated distance of each vertex to the end of the case, if unable to obtain information from each vertex to reach the destination end, you can not use the A * algorithm. Efficiency is not always better than Dijkstra's algorithm, when the distance between the "guess the weight" and the actual distance is large difference between the two vertices, A * algorithm search efficiency may be even worse than Dijkstra's algorithm, or even misleading direction, causing can not be the final answer to the shortest path.
However, if the error between the actual distance from the presumed weight set and two vertices not actually look much larger than the efficiency of the A * algorithm Dijkstra's algorithm.
A * algorithm is often used to chase the game character design and fast break points.

Floyd algorithm
Dijkstra algorithm is obtained only from a point to another vertex, if the shortest distance between any two points in FIG even in all the required points, you must use Floyd algorithm.

SIZE = 7
NUMBER = 6
INFINITE = 99999

Graph_Matrix = [[0] * SIZE for row in range(SIZE)]  # 图的数组
distance = [[0] * SIZE for row in range(SIZE)]  # 路径长度数组

def build_graph_matrix(path_cost):
    for i in range(1, SIZE):
        for j in range(1, SIZE):
            if i == j:
                Graph_Matrix[i][j] = 0
            else:
                Graph_Matrix[i][j] = INFINITE

    # 图的边
    i = 0
    while i < SIZE:
        start_point = path_cost[i][0]
        end_point = path_cost[i][1]
        Graph_Matrix[start_point][end_point] = path_cost[i][2]
        i += 1

def shortest_path(vertex_total):
    # 初始化图的长度数组
    for i in range(1, vertex_total+1):
        for j in range(i, vertex_total+1):
            distance[i][j] = Graph_Matrix[i][j]
            distance[j][i] = Graph_Matrix[i][j]

    # 使用 Floyd 算法找出所有顶点两两之间的最短距离
    for k in range(1, vertex_total+1):
        for i in range(1, vertex_total+1):
            for j in range(1, vertex_total+1):
                if distance[i][k] + distance[k][j] < distance[i][j]:
                    distance[i][j] = distance[i][k] + distance[k][j]

path_cost = [
    [1, 2, 20], [2, 3, 30], [2, 4, 25],
    [3, 5, 28], [4, 5, 32], [4, 6, 95],
    [5, 6, 67]
]

build_graph_matrix(path_cost)
print('=================================================')
print('所有顶点两两之间的最短距离:')
print('=================================================')
shortest_path(NUMBER)
print('        顶点1   顶点2  顶点3  顶点4   顶点5  顶点6')
for i in range(1, NUMBER+1):
    print('顶点 %d' %i, end='')
    for j in range(1, NUMBER+1):
        print('%6d ' % distance[i][j], end='')
    print()

Topological sorting steps:

  1. Without any starting point forerunner looking figure
  2. The output of this vertex, and delete all the edges of this vertex
  3. Repeating the above steps, all process vertices

Guess you like

Origin www.cnblogs.com/catyuang/p/11760507.html