数据结构-----图及其操作

 有向图

MAX = 999999999999999999999999999999999999999999999999999999


class Node:
    # 指向这个点
    first_in = None
    # 从这个点出发,指向其他点
    first_out = None
    name = ""
    # 是否被搜索
    isSearch = False
    # 最早开始时间
    ei = 0
    # 最晚开始时间
    li = 0

    # 用在求最短路径中,表示以这个点为结尾的最短路径

    def __init__(self, name):
        self.name = name
        self.path = []
        self.paths = {}

    # 打印路径和权重,单源
    def print_min_path(self):
        for p in self.path:
            print(p.name, end="---->")
        print(self.name)

    # 打印路径和权重,多源
    def print_min_paths(self, D):
        print("起始点是", self.name)
        for k, v in self.paths.items():
            print("终点是", k.name, end="")
            if D[self][k] != MAX:
                print("\t权重:", D[self][k], end="\t\t")
            for i in v:
                print(i.name, end="")
                if v.index(i) < len(v) - 1:
                    print(end="-->")
            print("")


class Line:
    # 头域
    headvex = None
    # 尾域
    tailvex = None
    # 头域相同的下一条弧
    hlink = None
    # 尾域相同的下一条弧
    tlink = None
    info = ""
    weight = 0

    def __init__(self, tailvex, headvex, weight=0):
        self.tailvex = tailvex
        self.headvex = headvex
        self.weight = weight

    def print(self):
        print(self.tailvex.name + "---->" + self.headvex.name)


class Tree:
    # 当前树的根节点
    root = None
    # 左孩子
    l_child = None
    # 兄弟
    next_sibling = None

    def search(self):
        if self.root != None:
            print(self.root.name, "---")
        if self.l_child != None:
            self.l_child.search()
        else:
            return
        tree = self.l_child.next_sibling
        while tree != None:
            tree.search()
            tree = tree.next_sibling


def search_tree(tree):
    tree.search()
    tree = tree.next_sibling
    while tree != None:
        tree.search()
        tree = tree.next_sibling


class array_box:
    node_list = []
    line_list = []

    # 根据节点名获得节点
    def get_a_node_by_name(self, name):
        for n in self.node_list:
            if n.name == name:
                return n
        return None

    # 创建一个有向图
    def creat_a_array_box(self, node_list, line_list):

        # 如果没有节点,就返回空
        if node_list == None or len(node_list) == 0:
            return None

        self.node_list = self.node_list + node_list
        self.node_list = list(set(self.node_list))
        self.line_list = self.line_list + line_list
        self.line_list = list(set(self.line_list))

        for line in line_list:
            headvex = line.headvex

            tailvex = line.tailvex

            line.hlink = headvex.first_in
            line.tlink = tailvex.first_out

            headvex.first_in = line
            tailvex.first_out = line
        return self

    def shendu_search(self, search_index=0):
        isPrint = False
        # 创建一个列表,存放结果数据
        node_list = []

        begin = search_index

        # 初始化查询变量
        for node in self.node_list:
            if isPrint:
                print(node.name, end="-------")
            node.isSearch = False
        if isPrint:
            print()
            print("以上设定否值")
        # 查询每个节点
        print(self.node_list[begin].name + "-----")
        if not self.node_list[begin].isSearch:
            node_list = node_list + self.DFS(self.node_list[begin])
            begin = (begin + 1) % len(self.node_list)
        while begin != search_index:
            if not self.node_list[begin].isSearch:
                if isPrint:
                    print(self.node_list[begin].name, "-----")
                node_list = node_list + self.DFS(self.node_list[begin])
            begin = (begin + 1) % len(self.node_list)
        if isPrint:
            print()
            print("以上正在搜索")
        return node_list

    def DFS(self, node):
        # 创建一个列表,存放结果数据
        node_list = []

        if node == None or node.isSearch:
            return node_list
        node_list.append(node)
        node.isSearch = True
        # 得到node第一个邻接点
        f, l = self.FirstAdjVex(node)
        while f != None:
            node_list = node_list + self.DFS(f)
            f = self.NextAdjVex(node, f)
        return node_list

    def NextAdjVex(self, node, vex):
        # 得到从node出发的第一条弧
        root_out = node.first_out

        # 如果node不是vex邻接顶点,就返回None
        if root_out.headvex.name != vex.name:
            return None
        # 最先用sv表示node的邻接点,然后用他表示最后一个邻接点
        sv = vex
        while True:
            # 得到sv的下一个邻接点end
            end, l = self.FirstAdjVex(sv)
            # 如果end不为空,即sv有邻接点将end赋值给sv
            if not end == None:
                sv = end
            else:
                # sv没有邻接点,就退出,此时sv为最后节点
                break
        if sv == vex:
            return None
        return sv

    # node第一个指向的节点
    def FirstAdjVex(self, node):
        if node.first_out != None:
            return node.first_out.headvex, node.first_out
        else:
            return None, None

    def guangdu_search(self, search_index=0):
        isPrint = False
        # 创建一个列表,存放结果数据
        node_list = []

        begin = search_index
        # 初始化查询变量
        for node in self.node_list:
            if isPrint:
                print(node.name, end="-------")
            node.isSearch = False
        if isPrint:
            print()
            print("以上设定否值")
        # 查询每个节点
        # for node in self.node_list:
        #     if not node.isSearch:
        #         if isPrint:
        #             print(node.name, end="-------\n")
        #         node_list = node_list + self.BFS(node)
        if not self.node_list[begin].isSearch:
            node_list = node_list + self.BFS(self.node_list[begin])
            begin = (begin + 1) % len(self.node_list)
        while begin != search_index:
            if isPrint:
                print("循环")
            if not self.node_list[begin].isSearch:
                if isPrint:
                    print("进入")
                node_list = node_list + self.BFS(self.node_list[begin])
            begin = (begin + 1) % len(self.node_list)
        if isPrint:
            print()
            print("以上正在搜索")
        return node_list

    def BFS(self, node):
        isPrint = False
        if isPrint:
            print("开始广度搜索", node.name)
        node_list = []
        if node == None:
            print("节点为空")
            return node_list
        if not node.isSearch:
            # 加入节点
            node_list.append(node)
            # 设置已被搜索
            node.isSearch = True

        if node.first_out != None:
            # adjvex是第一个邻接自adjvex的顶点
            adjVex = node.first_out.headvex
            # node_list = node_list + self.BFS(adjVex)
            if not adjVex.isSearch:
                node_list.append(adjVex)
                adjVex.isSearch = True
            adjVex, l = self.NearAdjVex(node, node.first_out.headvex)
        else:
            adjVex = None

        while adjVex != None:
            if not adjVex.isSearch:
                node_list.append(adjVex)
                adjVex.isSearch = True
            # node_list = node_list + self.BFS(adjVex)
            adjVex, l = self.NearAdjVex(node, adjVex)
        # print("递归之前", len(node_list), "---", node.name)
        for n in node_list:
            # print(n.name, "开始递归")
            node_list = node_list + self.BFS(n)
        # print("递归结束", len(node_list), "---", node.name)
        return node_list

    # vex是node的邻接点,返回node另一个邻接点
    def NearAdjVex(self, node, vex):
        # isAdj是node和vex是不是邻接点,line是node和vex之间的弧
        isAdj, line = self.isAdj(node, vex)
        # print(node.name, "=====", vex.name, "------", isAdj, end="他们的弧")
        # line.print()
        if isAdj:
            line = line.tlink
            if line != None:
                return line.headvex, line
            else:
                return None, None
        else:
            return None, None

    def isAdj(self, n1, n2):

        # 初始化变量
        isAdj = False

        if n1 == None or n2 == None:
            return isAdj, None
        # line是节点n1第一条发出的弧,然后是其他从n1发出的弧
        line = n1.first_out

        # 当line不为空
        while line != None:
            # 如果line的头域是n2,就说明n1邻接到n2保存退出
            if line.headvex == n2:
                isAdj = True
                # print(n1.name, "=====", n2.name, "------", isAdj)
                # line.print()
                return isAdj, line
            # line等于从n1发射出的其他弧
            line = line.tlink
        return isAdj, None

    def creat_a_deep_tree(self, start_index):
        if start_index < 0 or start_index >= len(self.node_list):
            print("节点不在此图中")
            return None
        root_tree = Tree()
        begin = start_index
        # 初始化查询变量
        for n in self.node_list:
            n.isSearch = False
        # 搜索第一个节点node
        node = self.node_list[begin]
        root_tree = self.DFS_tree(node)
        begin = (begin + 1) % len(self.node_list)
        next_tree = root_tree
        # 搜索其他节点,并把树作为根节点的兄弟
        while begin != start_index:
            n = self.node_list[begin]
            if n.isSearch == False:
                print("将要生成树", n.name)
                tree = self.DFS_tree(n)
                next_tree.next_sibling = tree
                next_tree = tree
            begin = (begin + 1) % len(self.node_list)
        return root_tree

    # 生成以node为根节点的树
    def DFS_tree(self, node):
        # print("节点", node.name)
        root_tree = Tree()
        first = True
        # 把当前节点node加入根树root_tree
        root_tree.root = node
        node.isSearch = True
        next_tree = None
        # 得到当前节点第一个邻接点next_node
        next_node, l = self.FirstAdjVex(node)
        if next_node == None:
            return root_tree
        while next_node != None:
            if next_node.isSearch:
                # print(next_node.name, "跳过")
                next_node, l = self.NearAdjVex(node, next_node)
                continue
            tree = self.DFS_tree(next_node)
            # 生成以next_node为根节点的树next_tree,加入为root_tree的左孩子
            if first:
                first = False
                root_tree.l_child = tree
            else:
                # 得到node的其他邻接点,各自生成树,加入为next_tree的兄弟
                # print(next_tree.root.name, "兄弟", tree.root.name)
                next_tree.next_sibling = tree
            next_tree = tree
            next_node, l = self.NearAdjVex(node, next_node)
        return root_tree

    # 试图用栈实现图拓扑排序
    def get_a_TuoPuPaiXu_tree(self):
        stack = []
        result = []
        # 记录各个节点的入度
        degree_list = {}
        # 得到顶点集合
        node_list = self.node_list[:]
        # # 得到弧集合
        # line_list = self.line_list
        # 遍历节点列表
        for n in node_list:
            # 得到当前节点的入度
            n_degree = self.get_node_in_degree(n)
            # 如果入度为0.就入栈
            if n_degree == 0:
                stack.append(n)
            # 把各个节点的入度放入集合中
            degree_list[n] = n_degree

        while len(stack) > 0:
            # 得到栈顶数据,这个数据入度为0
            now_node = stack.pop()
            # 把当前数据加入返回结果中
            result.append(now_node)
            # 得到now_node第一个邻接点
            p, l = self.FirstAdjVex(now_node)
            while p != None:
                # 把p的入度减1
                degree_list[p] -= 1
                # 判断是否入栈
                if degree_list[p] == 0:
                    stack.append(p)
                # 得到now_node另一个邻接点
                p, l = self.NearAdjVex(now_node, p)
        return result

    # 得到一个节点的入度
    def get_node_in_degree(self, node):
        if node.first_in == None:
            return 0
        count = 0
        # 第一个指向node的弧
        line = node.first_in
        while line != None:
            count += 1
            line = line.hlink
        return count

    # 生成一个有向无环图,求得每个点的最早开始时间(每个点都有最早开始时间ei)
    def creat_a_AOE_box(self):
        # 创建一个栈stack,存放入度为零的点
        stack = []
        # 创建一个栈result,用来存放结果
        result = []
        # 创建一个字典degree_list,存放各个顶点的入度
        degree_list = {}
        # 得到顶点集合
        node_list = self.node_list[:]
        # 初始化每个节点的入度,并把入度为0的加入stack
        for n in node_list:
            degree = self.get_node_in_degree(n)
            if degree == 0:
                stack.append(n)
            degree_list[n] = degree
        # 循环遍历stack,直至栈为空
        while len(stack) > 0:
            #     得到栈顶元素now_node,这个顶点入度为0
            now_node = stack.pop()
            #     把当前元素加入result中
            result.append(now_node)
            p, line = self.FirstAdjVex(now_node)
            #     遍历now_node的邻接点p,把入度减一
            while p != None:
                degree_list[p] -= 1
                #         如果出现入度为0的,加入result
                if degree_list[p] == 0:
                    stack.append(p)
                #         得到p与now_node之间的弧,得到其权重weight
                weight = line.weight
                #         权重加now_node的最早开始时间ei得到now_ei
                now_ei = now_node.ei + weight
                #         如果now_ei大于p的最早开始时间ei,就把p的最早开始时间ei变为较大者now_ei
                if now_ei > p.ei:
                    p.ei = now_ei
                p, line = self.NearAdjVex(now_node, p)
        return result

    def get_critical_path(self, box):
        # 创建一个返回栈result
        result = []
        # box是一个栈,栈顶元素是汇点,栈底元素是源点
        # 得到汇点hui_node
        hui_node = box[-1]
        # 初始化最迟开始时间
        for b in box:
            b.li = hui_node.ei
        # 讲box复制到一个栈node_stack中
        node_stack = box[:]
        # 弹出栈顶元素hui_box的复制品
        result.append(node_stack.pop())
        # 当栈node_stack不为空,遍历
        while len(node_stack) > 0:
            # 得到栈顶元素, now_node
            now_node = node_stack.pop()
            result.append(now_node)
            #     得到now_node的邻接点p,和弧line
            p, line = self.FirstAdjVex(now_node)
            #
            #     当p不为空一直循环
            while p != None:
                #         得到line的权重weight
                weight = line.weight
                #         根据p的li和weight计算出新的最迟开始时间new_li
                new_li = p.li - weight
                #         如果new_li<now_node.li就把now_node.li设置为较小的那个
                if new_li < now_node.li:
                    now_node.li = new_li
                #         p=now_node的另一个邻接点,新的弧line,是now_node指向p的弧
                p, line = self.NearAdjVex(now_node, p)
        # 遍历node_stack,把ei与li相等的加入result中
        # for node_stack
        result = result[::-1]
        critical_path = []
        for r in result:
            if r.ei == r.li:
                critical_path.append(r)
        return critical_path

    def min_path_by_Dijkstra(self, start_index=0):
        # 创建一个字典D,存放每个点的路径长度
        D = {}
        # 创建一个列表final,保存自由的点
        final = []
        # 创建一个列表result_list,保存所有路径点
        result_list = []
        # 把所有点都加入fianl列表,并初始化
        final = self.node_list[::]
        # 得到开始点root_node
        root_node = final[start_index]
        for f in final:
            D[f] = self.get_weight_by_near_node(root_node, f)
            if D[f] < MAX:
                f.path.append(root_node)
        # 设置开始点root_node
        final.remove(root_node)
        result_list.append(root_node)
        D[root_node] = 0
        # 遍历final循环所有点
        while len(final) > 0:

            min = MAX
            v = None
            # 找到路径长度最短的点node
            for f in final:
                if D[f] < min:
                    min = D[f]
                    v = f
            # final移除node,result_list加入这个点
            if v == None:
                break
            final.remove(v)
            result_list.append(v)
            # 遍历final所有
            for f in final:
                # 如果f的路径比node的路径+这两个点之间的权重大,就更新路径与权重
                if D[f] > min + self.get_weight_by_near_node(v, f):
                    D[f] = min + self.get_weight_by_near_node(v, f)
                    f.path = v.path[::]
                    if v != root_node:
                        f.path.append(v)
            # break
        return result_list, D

    # 得到两个邻接点之间的权重
    def get_weight_by_near_node(self, node1, node2):
        # 如果两个点不是邻接点,返回无限大
        isAdj, line = self.isAdj(node1, node2)
        if not isAdj:
            return MAX
        # line是node1指向node的弧,如果弧存在,就返回之间的权重
        node, line = self.FirstAdjVex(node1)
        while node != None:
            if node == node2:
                return line.weight
            node, line = self.NearAdjVex(node1, node)
        return self.get_weight_by_near_node(node2, node1)

    def min_path_by_Floyd(self):
        # 初始化每条路径间的距离
        D = {}
        # 初始化路径
        node_list = self.node_list[::]
        for node in node_list:
            # node是起点
            D[node] = {}
            for n in node_list:
                # n是终点
                if n != node:
                    # 初始化从node到n的路径
                    node.paths[n] = []
                # 把node到n的距离保存起来
                D[node][n] = self.get_weight_by_near_node(node, n)
                if D[node][n] < MAX:
                    # 如果node到n之间有弧
                    # 把路径加入node
                    node.paths[n].append(n)
        for u in node_list:
            for v in node_list:
                for w in node_list:
                    # 如果从v到w之间的距离,比从v到u再到w远
                    if D[v][w] > D[v][u] + D[u][w]:
                        # 设置最短路径长度
                        D[v][w] = D[v][u] + D[u][w]
                        # 设置路径顶点信息
                        v.paths[w] = v.paths[u][::]
                        v.paths[w].append(w)
        return node_list, D

无向图

class Node:
    name = ""
    isSearch = False
    first_edge = None

    def __init__(self, name):
        self.name = name


class Line:
    # 这条弧是否被搜索
    mark = False
    # 一个顶点
    ivex = None
    # ivex依附的另一条弧
    ilink = None
    # 另一个顶点
    jvex = None
    # jvex依附的另一条边
    jlink = None
    # 权重
    weight = 0

    def __init__(self, ivex, jvex, weight=0):
        self.ivex = ivex
        self.jvex = jvex
        self.weight = weight

    def print(self):
        print(self.ivex.name, "----------", self.jvex.name)


class Tree:
    # 当前树的根节点
    root = None
    # 左孩子
    l_child = None
    # 兄弟
    next_sibling = None

    def search(self):
        if self.root != None:
            print(self.root.name, "---")
        if self.l_child != None:
            self.l_child.search()
        else:
            return
        tree = self.l_child.next_sibling
        while tree != None:
            tree.search()
            tree = tree.next_sibling


class Binary_Tree:
    isRead = False
    root = None
    child = []

    def print(self):
        # 前序遍历
        if self.root != None:
            print(self.root.name, end="---")
        if self.child == None or len(self.child) == 0:
            return
        for c in self.child:
            c.print()


def search_tree(tree):
    tree.search()
    tree = tree.next_sibling
    while tree != None:
        tree.search()
        tree = tree.next_sibling


class unarray_box:
    node_list = []

    def creat_a_unarray_box(self, node_list, line_list):

        if node_list == None or len(node_list) <= 0:
            return None

        self.node_list = self.node_list + node_list
        self.node_list = list(set(node_list))

        for line in line_list:
            ivex = line.ivex
            jvex = line.jvex

            line.ilink = ivex.first_edge
            line.jlink = ivex.first_edge

            ivex.first_edge = line
            jvex.first_edge = line

        return self

    def get_a_node_by_name(self, name):
        for n in self.node_list:
            if n.name == name:
                return n
        return None

    # 返回这条弧上另一个节点
    def get_next_node(self, node, line):
        if node == None or line == None:
            return None
        if line.ivex == node:
            return line.jvex
        elif line.jvex == node:
            return line.ivex
        else:
            return None

    # 返回与这条弧相邻的另一个弧上的另一个节点
    def get_near_node(self, node, line):
        near_line = None
        if line.ivex == node:
            near_line = line.ilink
        elif line.jvex == node:
            near_line = line.jlink
        node = self.get_next_node(node, near_line)
        return node, near_line

    def shendu_search(self, search_indext=0):
        node_list = []
        # 初始化搜索变量
        for n in self.node_list:
            n.isSearch = False
        # 设置起始搜索索引
        begin = search_indext

        # 深度搜索第一个节点
        node_list = node_list + self.DFS(self.node_list[begin])

        # 索引指向下一个节点
        begin = (begin + 1) % len(self.node_list)

        # 循环搜索所有节点
        while begin != search_indext:
            node = self.node_list[begin]
            if not node.isSearch:
                print("在shendu_search,循环遍历", node.name)
                node_list = node_list + self.DFS(node)
            begin = (begin + 1) % len(self.node_list)
        return node_list

    def DFS(self, node):
        node_list = []
        if node.isSearch:
            return node_list
        # 先把节点node添加到返回集合node_list
        node_list.append(node)
        # 然后把节点node设置为已经被搜索
        node.isSearch = True
        # 得到节点node的第一条发射弧first_line
        first_line = node.first_edge
        # 然后得到节点node的下一条节点next_node,递归节点next_node,一直访问到尾部
        next_node = self.get_next_node(node, first_line)
        if next_node != None:
            node_list = node_list + self.DFS(next_node)
        # 得到当前节点的下一个邻接点near_node和之间的弧near_line
        near_node, near_line = self.get_near_node(node, first_line)
        # 递归这个near_node
        while near_node != None:
            node_list = node_list + self.DFS(near_node)
            near_node, near_line = self.get_near_node(near_node, near_line)
        return node_list

    def guangdu_search(self, search_index=0):
        node_list = []
        # 得到开始搜索的索引begin
        begin = search_index
        # 得到要搜索的节点node
        node = self.node_list[begin]
        # 广度搜索此节点node
        node_list = node_list + self.BFS(node)
        begin = (begin + 1) % len(self.node_list)
        # 循环遍历搜索其他节点
        while begin != search_index:
            node = self.node_list[begin]
            if not node.isSearch:
                print("guangdu_search,循环遍历", node.name)
                node_list = node_list + self.BFS(node)
            begin = (begin + 1) % len(self.node_list)

        return node_list

    def BFS(self, node):
        node_list = []
        if node.isSearch == False:
            node_list.append(node)
            node.isSearch = True
        # 得到节点node的第一个发出弧first_line
        first_line = node.first_edge
        # 得到第一个邻接点next_node
        next_node = self.get_next_node(node, first_line)

        if next_node.isSearch:
            return node_list
        # 把节点加入列表
        node_list.append(next_node)
        next_node.isSearch = True
        # 循环遍历,得到其他邻接点near_node和其之间的弧near_line
        near_node = node
        near_line = first_line
        while near_node != None:
            # 统统加入列表node_list
            if near_node.isSearch == False:
                node_list.append(near_node)
                near_node.isSearch = True
            near_node, near_line = self.get_near_node(node, near_line)

        # 遍历列表node_list统统进行广度搜索

        for n in node_list:
            node_list = node_list + self.BFS(n)
        return node_list

    def get_all_near(self, node):
        node_list = []
        # 得到节点的第一条弧near_line
        near_line = node.first_edge

        near_node = node

        # 循环,根据near_line和near_node得到所有的相近的节点
        while near_node != None:
            node_list.append(near_node)
            near_node, near_line = self.get_near_node(node, near_line)
        return node_list

    def creat_a_deep_tree(self, start_node=0):
        if start_node < 0 or start_node >= len(self.node_list):
            print("节点不在此图中")
            return None
        for n in self.node_list:
            n.isSearch = False
        # 创建一个树root_tree
        root_tree = Tree()
        # 提取出第一个节点node
        node = self.node_list[start_node]
        # save_node是循环中当前遍历的节点,初始化为根节点
        save_node = node
        # 遍历根节点
        root_tree = self.DFS_tree(node)
        begin = start_node
        begin = (begin + 1) % len(self.node_list)
        # 焦点树save_tree
        save_tree = root_tree
        while begin != start_node:
            save_node = self.node_list[begin]
            # print(save_node.name, "---------- while begin != start_node:")
            if save_node.isSearch == False:
                print(save_node.name, "将要被生成树")
                tree = self.DFS_tree(save_node)
                save_tree.next_sibling = tree
                save_tree = tree
            begin = (begin + 1) % len(self.node_list)
        return root_tree

    # 创建一个树,树的根节点为node
    def DFS_tree(self, node):
        # print(node.name, "----DFS_tree", node.isSearch)
        # 创建根树root_tree
        root_tree = Tree()
        # 把当前节点添加为根节点root_tree.root
        root_tree.root = node
        node.isSearch = True
        # 得到当前节点的第一条出发弧start_line
        start_line = node.first_edge
        # 得到第一个邻接点next_node
        next_node = self.get_next_node(node, start_line)
        # 得到第一个邻接点的第一条出发弧next_line
        if next_node == None:
            return root_tree

        next_line = next_node.first_edge
        next_line = start_line
        # 如果邻接点不为空
        first = True
        save_tree = None
        while next_node != None:
            if next_node.isSearch:
                next_node, next_line = self.get_near_node(node, next_line)
                continue
            tree = self.DFS_tree(next_node)
            if first:
                # 把以邻接点next_node为根节点的树作为当前根树root_tree的左孩子
                first = False
                root_tree.l_child = tree
            else:
                save_tree.next_sibling = tree
            save_tree = tree
            # 找到next_node其他邻接点,把以其他邻接点为根节点的树加入当前根树左孩子的兄弟
            next_node, next_line = self.get_near_node(node, next_line)
        return root_tree

    def creat_prime_tree(self, line_list, node_list, root_index=0):
        # 树根
        root_tree = Binary_Tree()
        # 树根上的小树集合
        tree_nodes = []
        # 自由的小树
        free_nodes = []
        # 树上的边
        tree_lines = []
        # 自由的边
        free_lines = line_list
        # 把顶点转换为树加入到树根
        free_nodes = self.init_free_nodes(node_list)

        # 得到根节点
        node = free_nodes[root_index]
        # 把根节点加入树列表
        free_nodes.remove(node)
        tree_nodes.append(node)
        root_tree = node
        # print("-------------------")
        count = 0
        while len(free_lines) > 0 and count >= 0:
            # print("-------------")
            # print("free_nodes自由的小树", len(free_nodes))
            # print("tree_nodes树根上的小树集合", len(tree_nodes))
            # print("free_lines自由的边", len(free_lines))
            # print("tree_lines树根的边", len(tree_lines))
            # 得到需要的权重最小的弧
            line = self.get_a_min_link_line(free_lines, tree_nodes, free_nodes)
            # 加入树的弧
            if line != None:
                tree_lines.append(line)
            # 把弧加入树
            # if line != None:
            #     line.print()

            self.add_a_child_for_tree(tree_nodes, free_nodes, line)
            # print("树根上的小树集合", end="-----")
            # tree_nodes[0].print()
            #
            # print()
            count += 1
        return root_tree

    def init_free_nodes(self, node_list):
        free_nodes = []
        for node in node_list:
            tree = Binary_Tree()
            tree.root = node
            free_nodes.append(tree)
        return free_nodes

    # 得到一个连接两个集合的边
    def get_a_min_link_line(self, free_lines, tree_nodes, free_nodes):
        line_list = []
        if len(free_lines) == 0:
            return line_list
        for line in free_lines:
            if self.node_is_in_list(tree_nodes, line.ivex) and self.node_is_in_list(free_nodes, line.jvex):
                line_list.append(line)
            elif self.node_is_in_list(tree_nodes, line.jvex) and self.node_is_in_list(free_nodes, line.ivex):
                line_list.append(line)

        min_line = None
        if len(line_list) > 0:
            min_line = line_list[0]
        for line in line_list:
            if min_line.weight > line.weight:
                min_line = line
        if min_line != None:
            free_lines.remove(min_line)
        #     print("得到一个最短弧")
        # else:
        #     print("没有得到最短弧")
        return min_line

    def add_a_child_for_tree(self, tree_nodes, free_nodes, line):
        if line == None:
            return
        father_node = None
        for n in tree_nodes:
            if line.ivex == n.root or line.jvex == n.root:
                # print("得到一个爸爸", n.root.name)
                father_node = n
                break
        # 得到弧上的另一个点
        next_node = self.get_next_node(father_node.root, line)
        child_node = self.get_a_tree_node(free_nodes, next_node)
        if father_node == None or child_node == None:
            print("连接失败")
            return
        tree_nodes.append(child_node)
        child_node.child = []
        father_node.child.append(child_node)

    def node_is_in_list(self, node_list, node):
        nodes = []
        for n in node_list:
            nodes.append(n.root)
        is_in = node in nodes
        # print(node.name, "is_in_tree_nodes", is_in)
        return is_in

    def get_a_tree_node(self, node_list, node):
        tree_node = None
        for n in node_list:
            if n.root == node:
                tree_node = n
                break
        return tree_node
发布了75 篇原创文章 · 获赞 9 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/sinat_40387150/article/details/87609186