【问题标题】:How to order a list of tuples based on a relationship between the elements of said tuple如何根据元组的元素之间的关系对元组列表进行排序
【发布时间】:2021-08-18 05:40:55
【问题描述】:

我有以下元组列表(其中每个数字代表一个人)

relation = [(0,6),(1,2),(1,4),(1,6),(3,0),(3,4),(5,1),(7,0),(7,1)] 

元组(a,b) 表示个体a 比个体b 更老。

我需要找到一种方法来从最年长到最年轻的个体排序,但我不知道该怎么做。我认为我应该使用树来解决这个问题,但我不太确定。

感谢您的四个答案和帮助!

【问题讨论】:

  • 到目前为止你尝试了什么?

标签: python list tree tuples


【解决方案1】:

你一直在思考正确的方向。实际上,您可以通过将输入建模为图形来解决问题。完成后,可以使用拓扑排序来解决问题。

from collections import defaultdict, deque

def find_order(relation):

    # make graph
    young_to_old = defaultdict(set)
    persons = set()
    for older, younger in relation:
        young_to_old[younger].add(older)
        persons.add(younger)
        persons.add(older)

    # persons w/o an older person
    without_older = deque([p for p in persons if p not in young_to_old])

    # complementary data structure for faster lookups
    old_to_young = defaultdict(set)
    for younger, olders in young_to_old.items():
        for o in olders:
            old_to_young[o].add(younger)

    # topological sort
    result = []
    while without_older:
         p = without_older.popleft()
         result.append(p)
         for y in old_to_young[p]:
              young_to_old[y].remove(p)
              if not young_to_old[y]:
                   without_older.append(y)

    # check for cycle, no solution 
    if len(result) < len(young_to_old):
         return []

    return result

然后根据您的输入:

find_order(relation)
[3, 5, 7, 0, 1, 2, 4, 6]

【讨论】:

    【解决方案2】:

    这是topological sorting的案例。

    例如,您可以使用深度优先遍历来执行此排序:

    def topsort(relation):
        # Create node list
        nodes = {node: [] for pair in relation for node in pair}
    
        # Create edges in reversed direction, as adjacency list
        for older, younger in relation:
            nodes[younger].append(older)
    
        result = []
    
        def visit(node):
            olders = nodes[node]
            if olders == 2:  # Already visited
                return
            if olders == 1:  # Is on the current path
                raise ValueError("cycle detected")
            nodes[node] = 1
            for older in olders:
                visit(older)
            nodes[node] = 2
            result.append(node)
            
        # Start depth first traversal
        for node in nodes:
            visit(node)
    
        return result
    
    relation = [(0,6),(1,2),(1,4),(1,6),(3,0),(3,4),(5,1),(7,0),(7,1)]
    print(topsort(relation))  # [3, 7, 0, 5, 1, 6, 2, 4]
    

    请注意,可能有多种解决方案。例如,对于这个示例输入,不知道第 5 个人是否比第 7 个人大,因此您可以对它们进行排序。

    【讨论】:

    • 非常感谢您的回答!这真的很有帮助。我一直在阅读您的代码,我想我理解它,但我不知道如何修改它以使其打印所有可能的订单(按照您最后编写的示例,一个订单将是5 比 7 大,另一个是 7 比 5 大)
    • 那将是一个不同的问题,并且需要不同的算法。如果您绘制图表,您可以看到存在几个未定义顺序的对。这可以导致许多可能的解决方案。您需要使用递归。试一试,如果找不到解决方案,请专门提出一个新问题。
    猜你喜欢
    • 2022-01-24
    • 1970-01-01
    • 2011-05-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-03-11
    • 2020-12-17
    • 2020-08-02
    相关资源
    最近更新 更多