【数据结构与算法】task6 图

参考:https://github.com/TheAlgorithms/Python/tree/master/graphs

实现有向图、无向图、有权图、无权图的邻接矩阵和邻接表表示方法

参考:https://blog.csdn.net/qq_35295155/article/details/78639997

https://blog.csdn.net/fly_hawk/article/details/78513257

图类:


class Graph_Matrix:
    """
    Adjacency Matrix
    """
    def __init__(self, vertices=[], matrix=[]):
        """

        :param vertices:a dict with vertex id and index of matrix , such as {vertex:index}
        :param matrix: a matrix
        """
        self.matrix = matrix
        self.edges_dict = {}  # {(tail, head):weight}
        self.edges_array = []  # (tail, head, weight)
        self.vertices = vertices
        self.num_edges = 0

        # if provide adjacency matrix then create the edges list
        if len(matrix) > 0:
            if len(vertices) != len(matrix):
                raise IndexError
            self.edges = self.getAllEdges()
            self.num_edges = len(self.edges)

        # if do not provide a adjacency matrix, but provide the vertices list, build a matrix with 0
        elif len(vertices) > 0:
            self.matrix = [[0 for col in range(len(vertices))] for row in range(len(vertices))]

        self.num_vertices = len(self.matrix)

    def isOutRange(self, x):
        try:
            if x >= self.num_vertices or x <= 0:
                raise IndexError
        except IndexError:
            print("节点下标出界")

    def isEmpty(self):
        if self.num_vertices == 0:
            self.num_vertices = len(self.matrix)
        return self.num_vertices == 0

    def add_vertex(self, key):
        if key not in self.vertices:
            self.vertices[key] = len(self.vertices) + 1

        # add a vertex mean add a row and a column
        # add a column for every row
        for i in range(self.getVerticesNumbers()):
            self.matrix[i].append(0)

        self.num_vertices += 1

        nRow = [0] * self.num_vertices
        self.matrix.append(nRow)

    def getVertex(self, key):
        pass

    def add_edges_from_list(self, edges_list):  # edges_list : [(tail, head, weight),()]
        for i in range(len(edges_list)):
            self.add_edge(edges_list[i][0], edges_list[i][1], edges_list[i][2], )

    def add_edge(self, tail, head, cost=0):
        # if self.vertices.index(tail) >= 0:
        #   self.addVertex(tail)
        if tail not in self.vertices:
            self.add_vertex(tail)
        # if self.vertices.index(head) >= 0:
        #   self.addVertex(head)
        if head not in self.vertices:
            self.add_vertex(head)

        # for directory matrix
        self.matrix[self.vertices.index(tail)][self.vertices.index(head)] = cost
        # for non-directory matrix
        # self.matrix[self.vertices.index(fromV)][self.vertices.index(toV)] = \
        #   self.matrix[self.vertices.index(toV)][self.vertices.index(fromV)] = cost

        self.edges_dict[(tail, head)] = cost
        self.edges_array.append((tail, head, cost))
        self.num_edges = len(self.edges_dict)

    def getEdges(self, V):
        pass

    def getVerticesNumbers(self):
        if self.num_vertices == 0:
            self.num_vertices = len(self.matrix)
        return self.num_vertices

    def getAllVertices(self):
        return self.vertices

    def getAllEdges(self):
        for i in range(len(self.matrix)):
            for j in range(len(self.matrix)):
                if 0 < self.matrix[i][j] < float('inf'):
                    self.edges_dict[self.vertices[i], self.vertices[j]] = self.matrix[i][j]
                    self.edges_array.append([self.vertices[i], self.vertices[j], self.matrix[i][j]])

        return self.edges_array

    def __repr__(self):
        return str(''.join(str(i) for i in self.matrix))

    def to_do_vertex(self, i):
        print('vertex: %s' % (self.vertices[i]))

    def to_do_edge(self, w, k):
        print('edge tail: %s, edge head: %s, weight: %s' % (self.vertices[w], self.vertices[k], str(self.matrix[w][k])))

无向图的邻接矩阵表示方法:

def create_undirected_matrix(my_graph):
    nodes = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']

    matrix = [[0, 1, 1, 1, 1, 1, 0, 0],  # a
              [0, 0, 1, 0, 1, 0, 0, 0],  # b
              [0, 0, 0, 1, 0, 0, 0, 0],  # c
              [0, 0, 0, 0, 1, 0, 0, 0],  # d
              [0, 0, 0, 0, 0, 1, 0, 0],  # e
              [0, 0, 1, 0, 0, 0, 1, 1],  # f
              [0, 0, 0, 0, 0, 1, 0, 1],  # g
              [0, 0, 0, 0, 0, 1, 1, 0]]  # h

    my_graph = Graph_Matrix(nodes, matrix)
    print(my_graph)
    return my_graph

显示无向图:

def draw_undircted_graph(my_graph):
    G = nx.Graph()  # 建立一个空的无向图G
    for node in my_graph.vertices:
        G.add_node(str(node))
    for edge in my_graph.edges:
        G.add_edge(str(edge[0]), str(edge[1]))

    print("nodes:", G.nodes())  # 输出全部的节点: [1, 2, 3]
    print("edges:", G.edges())  # 输出全部的边:[(2, 3)]
    print("number of edges:", G.number_of_edges())  # 输出边的数量:1
    nx.draw(G, with_labels=True)
    plt.savefig("undirected_graph.png")
    plt.show()

有向图的邻接矩阵表示方法:

def create_directed_matrix(my_graph):
    nodes = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']
    inf = float('inf')
    matrix = [[0, 2, 1, 3, 9, 4, inf, inf],  # a
              [inf, 0, 4, inf, 3, inf, inf, inf],  # b
              [inf, inf, 0, 8, inf, inf, inf, inf],  # c
              [inf, inf, inf, 0, 7, inf, inf, inf],  # d
              [inf, inf, inf, inf, 0, 5, inf, inf],  # e
              [inf, inf, 2, inf, inf, 0, 2, 2],  # f
              [inf, inf, inf, inf, inf, 1, 0, 6],  # g
              [inf, inf, inf, inf, inf, 9, 8, 0]]  # h

    my_graph = Graph_Matrix(nodes, matrix)
    print(my_graph)
    return my_graph

显示有向图:


def draw_directed_graph(my_graph):
    G = nx.DiGraph()  # 建立一个空的无向图G
    for node in my_graph.vertices:
        G.add_node(str(node))
    G.add_weighted_edges_from(my_graph.edges_array)

    print("nodes:", G.nodes())  # 输出全部的节点
    print("edges:", G.edges())  # 输出全部的边
    print("number of edges:", G.number_of_edges())  # 输出边的数量
    nx.draw(G, with_labels=True)
    plt.savefig("directed_graph.png")
    plt.show()

 

实现图的深度优先搜索、广度优先搜索

参考:https://www.cnblogs.com/yupeng/p/3414736.html

https://github.com/wangzheng0822/algo/blob/master/python/31_bfs_dfs/bfs_dfs.py

https://blog.csdn.net/m0_37324740/article/details/80842499

https://blog.csdn.net/chuangshishen0/article/details/78461706

#!/usr/bin/python
# -*- coding: utf-8 -*-

class Graph(object):

    def __init__(self,*args,**kwargs):
        self.node_neighbors = {}
        self.visited = {}

    def add_nodes(self,nodelist):

        for node in nodelist:
            self.add_node(node)

    def add_node(self,node):
        if not node in self.nodes():
            self.node_neighbors[node] = []

    def add_edge(self,edge):
        u,v = edge
        if(v not in self.node_neighbors[u]) and ( u not in self.node_neighbors[v]):
            self.node_neighbors[u].append(v)

            if(u!=v):
                self.node_neighbors[v].append(u)

    def nodes(self):
        return self.node_neighbors.keys()

    def depth_first_search(self,root=None):
        order = []
        def dfs(node):
            self.visited[node] = True
            order.append(node)
            for n in self.node_neighbors[node]:
                if not n in self.visited:
                    dfs(n)


        if root:
            dfs(root)

        for node in self.nodes():
            if not node in self.visited:
                dfs(node)

        print order
        return order

    def breadth_first_search(self,root=None):
        queue = []
        order = []
        def bfs():
            while len(queue)> 0:
                node  = queue.pop(0)

                self.visited[node] = True
                for n in self.node_neighbors[node]:
                    if (not n in self.visited) and (not n in queue):
                        queue.append(n)
                        order.append(n)

        if root:
            queue.append(root)
            order.append(root)
            bfs()

        for node in self.nodes():
            if not node in self.visited:
                queue.append(node)
                order.append(node)
                bfs()
        print order

        return order


if __name__ == '__main__':
    g = Graph()
g.add_nodes([i+1 for i in range(8)])
g.add_edge((1, 2))
g.add_edge((1, 3))
g.add_edge((2, 4))
g.add_edge((2, 5))
g.add_edge((4, 8))
g.add_edge((5, 8))
g.add_edge((3, 6))
g.add_edge((3, 7))
g.add_edge((6, 7))
print "nodes:", g.nodes()

order = g.breadth_first_search(1)
order = g.depth_first_search(1)

实现 Dijkstra 算法

参考:https://blog.csdn.net/u011285477/article/details/74931201

http://www.cnblogs.com/mayunting/p/10426705.html

迪杰斯特拉(Dijkstra)算法主要是针对没有负值的有向图,求解其中的单一起点到单一终点的最短路径算法。

【数据结构与算法】task6 图_第1张图片

# -*- coding: utf-8 -*-  
## 表示无穷大  
INF_val = 9999  
  
class Dijkstra_Path():  
    def __init__(self, node_map):  
        self.node_map = node_map  
        self.node_length = len(node_map)  
        self.used_node_list = []  
        self.collected_node_dict = {}  
      
    def __call__(self, from_node, to_node):  
        self.from_node = from_node  
        self.to_node = to_node  
        self._init_dijkstra()  
        return self._format_path()  
  
    def _init_dijkstra(self):  
        ## Add from_node to used_node_list  
        self.used_node_list.append(self.from_node)  
        for index1 in range(self.node_length):  
            self.collected_node_dict[index1] = [INF_val, -1]  
    
        self.collected_node_dict[self.from_node] = [0, -1] # from_node don't have pre_node  
        for index1, weight_val in enumerate(self.node_map[self.from_node]):  
            if weight_val:  
                self.collected_node_dict[index1] = [weight_val, self.from_node] # [weight_val, pre_node]  
          
        self._foreach_dijkstra()  
      
    def _foreach_dijkstra(self):  
        while(len(self.used_node_list) < self.node_length - 1):  
            min_key = -1  
            min_val = INF_val  
            for key, val in self.collected_node_dict.items(): # 遍历已有权值节点  
                if val[0] < min_val and key not in self.used_node_list:  
                    min_key = key  
                    min_val = val[0]  
  
            ## 把最小的值加入到used_node_list          
            if min_key != -1:  
                self.used_node_list.append(min_key)  
  
            for index1, weight_val in enumerate(self.node_map[min_key]):  
                ## 对刚加入到used_node_list中的节点的相邻点进行遍历比较  
                if weight_val > 0 and self.collected_node_dict[index1][0] > weight_val + min_val:  
                    self.collected_node_dict[index1][0] = weight_val + min_val # update weight_val  
                    self.collected_node_dict[index1][1] = min_key  
  
  
    def _format_path(self):  
        node_list = []  
        temp_node = self.to_node  
        node_list.append((temp_node, self.collected_node_dict[temp_node][0]))  
        while self.collected_node_dict[temp_node][1] != -1:  
          temp_node = self.collected_node_dict[temp_node][1]  
          node_list.append((temp_node, self.collected_node_dict[temp_node][0]))  
        node_list.reverse()  
        return node_list  
  
def set_node_map(node_map, node, node_list):  
    for x, y, val in node_list:  
        node_map[node.index(x)][node.index(y)] = node_map[node.index(y)][node.index(x)] = val  
  
      
if __name__ == "__main__":  
    node = ['A', 'B', 'C', 'D', 'E', 'F', 'G']  
    node_list = [('A', 'F', 9), ('A', 'B', 10), ('A', 'G', 15), ('B', 'F', 2),  
                 ('G', 'F', 3), ('G', 'E', 12), ('G', 'C', 10), ('C', 'E', 1),  
                 ('E', 'D', 7)]  
    
    ## init node_map to 0  
    node_map = [[0 for val in range(len(node))] for val in range(len(node))]  
    
    ## set node_map  
    set_node_map(node_map, node, node_list)  
    
    ## select one node to obj node, e.g. A --> D(node[0] --> node[3])  
    from_node = node.index('A')  
    to_node = node.index('D')  
    dijkstrapath = Dijkstra_Path(node_map)  
    path = dijkstrapath(from_node, to_node)  
    print(path)

输出结果:

 

A* 算法

参考:https://www.jianshu.com/p/e414fd4a7ed7

https://github.com/TheAlgorithms/Python/blob/master/graphs/a_star.py

https://blog.csdn.net/zhulichen/article/details/78786493

class Node:
    def __int__(self):
        self.unable = False
        self.distanceFromDes = -1  # 距离终点的距离
        self.distanceFromOri = -1  # 距离起点的距离
        self.allDistance = -1
        self.added = False
        self.closed = False
        self.parent = None
        self.x = -1
        self.y = -1


def GenerateMap(m, n):
    map = list()
    for j in range(m):
        nodeRow = list()
        map.append(nodeRow)
        for i in range(n):
            node = Node()
            node.y = j
            node.x = i
            node.unable = False
            node.distanceFromDes = -1  # 距离终点的距离
            node.distanceFromOri = -1  # 距离起点的距离
            node.allDistance = -1
            node.added = False
            node.closed = False
            node.parent = None
            nodeRow.append(node)
    return map


def SetUnableMapNode(map, ls=()):  # 要求一个坐标队列,里边的点上的Node的unable == True
    for index in ls:
        map[index[0]][index[1]].unable = True
    return map


def GetDistanceFromDes(map, mapSize, desIndex):  # map二维数组,mapsize(m,n),desIndex终点坐标
    for ls in map:
        for node in ls:
            node.added = False
    desNode = map[desIndex[0]][desIndex[1]]
    desNode.distanceFromDes = 0
    addedList = list()  # 已经加入的队列,已有值distanceFromDes
    needList = list()  # 待加入的队列,需要评估值distanceFromDes
    addedList.append(desNode)
    desNode.added = True
    while(len(addedList) != 0):  # 当地图上所有可以遍历的点还没全确定
        while(len(addedList) != 0):  # 当一个大循环中,addedList还没被needList取代
            # 从addedList中选出来的一个点,找needList中的needNode
            mainNode = addedList.pop(0)
            mainDistanceFromDes = mainNode.distanceFromDes
            y = mainNode.y
            x = mainNode.x
            for needNodey in (y + 1, y, y - 1):
                if needNodey < 0 or needNodey >= mapSize[0]:
                    continue
                for needNodex in (x + 1, x, x - 1):
                    if needNodex < 0 or needNodex >= mapSize[1]:
                        continue
                    needNode = map[needNodey][needNodex]  # 坐标不出界
                    if needNode.unable == True or needNode.added == True:
                        continue  # 坐标也满足add的要求
                    yOffset = needNodey - y
                    xOffset = needNodex - x
                    allOffset = yOffset + xOffset
                    if allOffset == 1 or allOffset == -1:
                        distanceFromDes = mainDistanceFromDes + 1
                    elif allOffset == -2 or allOffset == 0 or allOffset == 2:
                        distanceFromDes = mainDistanceFromDes + 1.4
                    else:
                        print("error in needNode's distanceFromDes")
                    
                    if needNode in needList:  # 设置needNode的距离,要求最小
                        if distanceFromDes < needNode.distanceFromDes:
                            needNode.distanceFromDes = distanceFromDes
                    else:  # needNode 不在needList中 distanceFromDes一定是-1
                        needNode.distanceFromDes = distanceFromDes
                        needList.append(needNode)
                    #print(needNode.y,needNode.x,needNode.distanceFromDes)
        # needList 已满 addedList已空
        addedList = needList
        for node in addedList:
            node.added = True
        needList = list()
    return map


def GetMinDistanceNodeList(map, mapSize, oriIndex, desIndex):
    for ls in map:
        for node in ls:
            node.added = False
    openedList = list()
    node = map[oriIndex[0]][oriIndex[1]]
    node.distanceFromOri = 0
    node.allDistance = 0
    openedList.append(node)
    node.added = True
    while len(openedList) != 0:
        #print('new turn')
        node = openedList.pop(0)
        node.closed = True
        if node.y == desIndex[0] and node.x == desIndex[1]:
            finalListNeedReverse = list()
            while node != None:
                finalListNeedReverse.append(node)
                node = node.parent
            finalListNeedReverse.reverse()
            return finalListNeedReverse
        neighboursList = list()
        y = node.y
        x = node.x
        parentDistanceFromOri = node.distanceFromOri
        for needNodey in (y + 1, y, y - 1):
            if needNodey < 0 or needNodey >= mapSize[0]:
                continue
            for needNodex in (x + 1, x, x - 1):
                if needNodex < 0 or needNodex >= mapSize[1]:
                    continue
                needNode = map[needNodey][needNodex]  # 坐标不出界
                if needNode.unable == True or needNode.closed == True or needNode.added == True:
                    continue  # 坐标也满足add的要求
                yOffset = needNodey - y
                xOffset = needNodex - x
                allOffset = yOffset + xOffset
                if allOffset == 1 or allOffset == -1:
                    distanceFromOri = parentDistanceFromOri + 1
                elif allOffset == -2 or allOffset == 0 or allOffset == 2:
                    distanceFromOri = parentDistanceFromOri + 1.4
                else:
                    print("error in needNode's distanceFromDes")
                if needNode in neighboursList:  # 设置needNode的距离,要求最小
                    if distanceFromOri < needNode.distanceFromOri:
                        needNode.distanceFromOri = distanceFromOri
                else:  # needNode 不在needList中 distanceFromDes一定是-1
                    needNode.distanceFromOri = distanceFromOri
                    neighboursList.append(needNode)  # 距离计算完成
        for needNode in neighboursList:  # 开始添加至openedList
            needNode.parent = node
            needNode.allDistance = needNode.distanceFromOri + needNode.distanceFromDes
            needNode.added = True
            openedList.append(needNode)
            #print(needNode.x,needNode.y,needNode.allDistance)
        openedList.sort(key=lambda x: x.allDistance)  # 最小距离的排在前边
    print("Cant find any way to the destination!")
    return None


def main():
    TestGetDistanceFromDes()


def TestGetDistanceFromDes():
    m = 27 #设置地图的长
    n = 25 #设置地图的宽
    oriIndex = (0, 0) #设置起点坐标
    desIndex = (23, 24) #设置终点坐标
    map = GenerateMap(m, n) #生成地图节点
    obstacleList = [(1,1),(2,1),(3,1),(4,3),(1,3),(2,3),(3,3),(0,1),(5,1),(5,3)] #设置障碍
    map = SetUnableMapNode(map,obstacleList)  #在地图中添加障碍
    GetDistanceFromDes(map, (m, n),desIndex) #添加终点,并计算节点与终点的距离

    print("Distance From Destination")
    for nodeRow in map:
        for node in nodeRow:
            if node.distanceFromDes != -1:
                print('{:^5.1f}'.format(node.distanceFromDes),end = " ")
            else:
                print('  X  ',end = " ")
        print()
    print()

    TestGetMinDistanceNodeList(map,(m,n),oriIndex,desIndex) #终点距离测试完了,进入下一阶段

def TestGetMinDistanceNodeList(map, mapSize, oriIndex,desIndex):
    finalList = GetMinDistanceNodeList(map, mapSize, oriIndex, desIndex) #添加起点,并生成起点到终点的节点队列

    directions = (('↘','↓','↙'),('→',"S",'←'),('↗','↑','↖'))
    print('How To Go')
    for nodeRow in map:
        for node in nodeRow:
            if node in finalList:
                #print('  *  ',end ='')
                parent = node.parent
                if parent != None:
                    if node.y!=desIndex[0] or node.x!=desIndex[1]:
                        (y,x) = (parent.y - node.y+1,parent.x -node.x+1)
                        print('  '+directions[y][x]+'  ',end = '')
                    else:
                        print('Final',end = '')
                else:
                    print('Start',end ='')
            else:
                if node.allDistance != -1:
                    print('{:^4.1f}'.format(node.allDistance),end = " ")
                else:
                    print('  X  ',end = " ")
        print()
    print()
main()

实现拓扑排序的 Kahn 算法

参考:https://github.com/TheAlgorithms/Python/blob/master/graphs/kahns_algorithm_topo.py

def topologicalSort(l):
    indegree = [0] * len(l)
    queue = []
    topo = []
    cnt = 0

    for key, values in l.items():
        for i in values:
            indegree[i] += 1

    for i in range(len(indegree)):
        if indegree[i] == 0:
            queue.append(i)

    while(queue):
        vertex = queue.pop(0)
        cnt += 1
        topo.append(vertex)
        for x in l[vertex]:
            indegree[x] -= 1
            if indegree[x] == 0:
                queue.append(x)

    if cnt != len(l):
        print("Cycle exists")
    else:
        print(topo)

# Adjacency List of Graph
l = {0:[1,2], 1:[3], 2:[3], 3:[4,5], 4:[], 5:[]}
topologicalSort(l)

实现拓扑排序的 DFS 算法

参考:https://blog.csdn.net/daorenfeixueyuhau/article/details/89878752

# f = lambda:map(int, input().split())
# n, m = f()
# g = [[0]*(n+1) for i in [0]*(n+1)]
# for k in range(m):
#     i, j = f()
#     g[i][j] = 1
# 手动输入数据
g = [[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
     [0, 0, 0, 0, 1, 1, 0, 0, 0, 0],
     [0, 0, 0, 0, 0, 1, 0, 0, 0, 0],
     [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
     [0, 0, 0, 0, 0, 1, 1, 0, 0, 0],
     [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
     [0, 0, 0, 0, 0, 0, 0, 0, 1, 0],
     [0, 0, 0, 0, 0, 0, 1, 0, 0, 1],
     [0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
     [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]
 
for i in range(1, len(g)):
    print(g[i])
# 记录拓扑排序顺序
l = []
# 记录出度为0的点
s = []
# 记录已经访问的点
v = []
for i in range(1, len(g)):
    if g[i].__eq__([0, 0, 0, 0, 0, 0, 0, 0, 0, 0]):
        s.append(i)
 
 
# 好像大概是完成了的,但是应该是有问题的
def visit(g, n):
    if n not in v:
        v.append(n)
    for m in range(1, len(g)):
        if g[m][n] and m not in v:
            visit(g, m)
    # 核心之处,代理解
    l.insert(0, n)
 
 
# 对s中的点进行dfs访问
for n in s:
    visit(g, n)
 
print('拓扑排序:')
print(l)
print('访问节点顺序:')
print(v)
print('出度为0节点集合:')
print(s)

leetcode-200 岛屿数量

题目:https://leetcode-cn.com/problems/number-of-islands/description/

参考:https://blog.csdn.net/xiaoxiaoley/article/details/82557634

class Solution(object):
    def numIslands(self, grid):
        """
        :type grid: List[List[str]]
        :rtype: int
        """
        output = 0
        for i in range(len(grid)):
            for j in range(len(grid[0])):
                if grid[i][j]=='1':
                    output += 1
                    self.dfs(grid,i,j)
        return output
    
    def dfs(self,grid,i,j):
        grid[i][j] = '0'
        if i-1>=0 and grid[i-1][j]=='1':
            self.dfs(grid,i-1,j)
        if i+1=0 and grid[i][j-1]=='1':
            self.dfs(grid,i,j-1)
        if j+1

leetcode-36 有效的数独

题目:https://leetcode-cn.com/problems/valid-sudoku/

参考:https://blog.csdn.net/huhehaotechangsha/article/details/80538675

https://blog.csdn.net/linfeng886/article/details/82778890

class Solution:
    def isValidSudoku(self, board):
        """
        :type board: List[List[str]]
        :rtype: bool
        """
        # 思路一:复杂的分条判断   76ms
#         for i in range(9):
#             if 9 - len(set(board[i])) != board[i].count(".") - 1:     # 条件一
#                 return False
            
#             new_list = []                                                       
#             for j in range(9):                                         # 条件二
#                 if board[j][i] != '.' and board[j][i] in new_list:
#                     return False
#                 if board[j][i] != '.' and board[j][i] not in new_list:         
#                     new_list.append(board[j][i])    

        
#         aa,bb = [0,3,6],[0,3,6]
#         for a in aa:                    # 条件三
#             for b in bb:
#                 new_list = []
#                 for i in range(a,a+3):                
#                     for j in range(b,b+3):
#                         if board[i][j] != '.' and board[i][j] in new_list:
#                             return False
#                         if board[i][j] != '.' and board[i][j] not in new_list:         
#                             new_list.append(board[i][j])
        
#         return True

        
    
        # 思路二: 只循环一次完成数据的分类,用存储空间来换取算法的效率(借鉴)。
    
#         dic_row = [{},{},{},{},{},{},{},{},{}]            # 每行的元素以一个字典储存,key是数字,value统一为1.
#         dic_col = [{},{},{},{},{},{},{},{},{}]
#         dic_box = [{},{},{},{},{},{},{},{},{}]

#         for i in range(len(board)):
#             for j in range(len(board)):
#                 num = board[i][j]
#                 if num == ".":
#                     continue
#                 if num not in dic_row[i] and num not in dic_col[j] and num not in dic_box[3*(i//3)+(j//3)]:
#                     dic_row[i][num] = 1
#                     dic_col[j][num] = 1
#                     dic_box[3*(i//3)+(j//3)][num] = 1       # 利用地板除,向下取余。巧妙地将矩阵划分为九块
#                 else:
#                     return False

#         return True
    
    
    
    
        # 思路三: 思路二的另一种实现方式。代码更为简洁(借鉴)
        Cell = [[] for i in range(9)]                   # 没有必要用dict,我们只某个数字关心有没有出现过
        Col =  [[] for i in range(9)]
        Row =  [[] for i in range(9)]
        
        for i,row in enumerate(board):                  # 将一个可遍历的数据对象(如列表、元组或字符串)组合为一个索引序列,同时列出数据和数据下标,一般用在 for 循环当中
            for j,num in enumerate(row):
                if num != '.':
                    k = (i//3)*3 + j//3
                    if num in Row[i] + Col[j] + Cell[k]:    # list的骚操作,将三个list顺序的拼接 
                        return False
                    Row[i].append(num)
                    Col[j].append(num)
                    Cell[k].append(num)
                        
        return True
    

 

你可能感兴趣的:(【数据结构与算法】task6 图)