【问题标题】:Error in merging sorted linked lists to one sorted linked list in python在python中将排序的链表合并到一个排序的链表时出错
【发布时间】:2019-07-21 09:15:14
【问题描述】:

我有以下代码。我创建了 2 个链表(l1l2),我想将它们组合到一个排序的链表中。我为此使用递归函数merge_lists,但出现错误。

class Node(object):
    def __init__(self):
        self.data = None # contains the data
        self.next = None # contains the reference to the next node


class LinkedList:
    def __init__(self):
        self.cur_node = None

    def add_node(self, data):
        new_node = Node() # create a new node
        new_node.data = data
        new_node.next = self.cur_node # link the new node to the 'previous' node.
        self.cur_node = new_node #  set the current node to the new one.

    def list_print(self):
        node = self.cur_node # cant point to ll!
        while node:
            print (node.data)
            node = node.next

def merge_lists(h1, h2):
        if h1 is None:
            return h2
        if h2 is None:
            return h1

        if (h1.data < h2.data):
            h1.next = merge_lists(h1.next, h2)
            return h1
        else:
            h2.next = merge_lists(h2.next, h1)
            return h2



l1 = LinkedList()
l1.add_node(1)
l1.add_node(5)
l1.add_node(7)

ll.list_print()

l2= LinkedList()
l2.add_node(2)
l2.add_node(6)
l2.add_node(8)
l2.list_print()

merge_lists(l1, l2)

这是我得到的错误:

7
5
1
8
6
2

---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-59-5032e795cb05> in <module>()
     49 l2.list_print()
     50 
---> 51 merge_lists(l1, l2)

<ipython-input-59-5032e795cb05> in merge_lists(h1, h2)
     27             return h1
     28 
---> 29         if (h1.data < h2.data):
     30             h1.next = merge_lists(h1.next, h2)
     31             return h1

AttributeError: 'str' object has no attribute 'data'

【问题讨论】:

  • 另外,merge_lists 在 LinkedList 类之外,我假设

标签: python sorting linked-list


【解决方案1】:

我再次回顾了这个任务,得到了以下递归函数。

class List1(object):
    ...
    ...
    def merge_lists(self, h1, h2):
      if h1!= None and h2 != None:   # l2 != None works in case of any node of the 1st list is smaller then any node of the 2nd list
          if h2.data > h1.data:
              cur = self
              while h2 and h2.data > h1.data:
                  self.add_node(cur, h2.data)
                  cur = cur.next
                  h2 = h2.next
          if h1.next is None:
              h1.next = h2  # works in case of any node of the 1st list is bigger then any node of the 2nd list
          else:
              h1.merge_lists(h1.next, h2)
# end of class

l1 = List1()
l1.add_node(l1, 1)
l1.add_node(l1, 5)
l1.add_node(l1, 7)
l1.list_print()
print()

l2 = List1()
l2.add_node(l2, 2)
l2.add_node(l2, 6)
l2.add_node(l2, 8)
l2.add_node(l2, 15)
l2.add_node(l2, 20)
l2.list_print()
print()

l1.merge_lists(l1.next, l2.next)  # Test
l1.list_print()

确实,它比非递归短约三倍,而且确实更优雅。运行时,它会更改第一个参数指定的列表。该课程取自我之前的示例。该函数针对以下情况进行测试:第一个列表比第二个列表长,当它更短时,当它的任何节点大于第二个列表的任何节点时,反之亦然。

UPD - 按升序排序的递归合并列表:

class List1(object):
...
...
    def merge_lists_ascend(self, h1, h2):
      if h1!= None and h2 != None:
          if h2.data < h1.data:  # '<' for ascending ordered lists
              cur = self
              while h2 and h2.data < h1.data:  # '<' for ascending ordered lists
                  self.add_node(cur, h2.data)
                  cur = cur.next
                  h2 = h2.next
          if h1.next is None:
              h1.next = h2
          else:
              h1.merge_lists_ascend(h1.next, h2)
# end of class

l11 = List1()
l11.add_node(l11, 7)
l11.add_node(l11, 5)
l11.add_node(l11, 1)
l11.list_print()
print()

l21 = List1()
l21.add_node(l21, 20)
l21.add_node(l21, 16)
l21.add_node(l21, 8)
l21.add_node(l21, 6)
l21.add_node(l21, 2)
l21.list_print()
print()

l11.merge_lists_ascend(l11.next, l21.next)  # Test
l11.list_print()

【讨论】:

  • 谢谢@PeterNazarenko,有没有办法升序而不是降序?
  • 是的,当然。您只需要将比较操作从&gt; 更改为&lt;。我已经更新了我的答案。
【解决方案2】:

您的 merge_lists 函数以接受 2 个节点作为输入的方式实现。所以只需将merge_lists(l1, l2) 更改为merge_lists(l1.cur_node, l2.cur_node)

>>> merge_lists(l1.cur_node, l2.cur_node)    
<__main__.Node object at 0x7faf116dc9e8>
>>> l1.list_print()
7
5
1
8
6
2
>>> 

【讨论】:

  • 感谢@Sunitha,但这不是必需的结果。我想制作 2 个排序的链表 - 一个使用我编写的函数的排序链表。我需要对代码做哪些更改?
【解决方案3】:

对不起,我没有评论的声誉,所以我写的是一个答案。我认为,Sunitha 意味着您需要在函数 merge_lists 定义中而不是在函数调用中使用 .cur_node。在这种情况下,函数参数的类型将是Node,而不是LinkedList,并且您的问题中提到的错误将被消除。但在这种情况下,您也会收到错误,因为函数merge_lists 将返回一个节点,而不是一个列表,例如,list_print() 的调用将不适用于返回的值。您可以使用以下代码克服此错误:

l3=LinkedList()
l3.cur_node=merge_lists(l1.cur_node, l2.cur_node)
l3.list_print()

但是,当然,它仍然不能解决您的主要问题。

UPD
我推荐使用单个类和全局合并功能(如上)的以下解决方案(我认为它稍微简单一些)。

class List1(object):
    def __init__(self, a = 0):
        self.data = a
        self.next = None

    def add_node(self, prev, a):
        q = List1(a)
        q.next = prev.next
        prev.next = q

    def list_print(self):
        q=self.next
        while q != None:
            print(q.data)
            q=q.next
# end of class

def merge_lists2(h1, h2):
    node1 = h1.next
    node2 = h2.next
    list = List1()
    q = list.next
    while node1 or node2:
        if node1 and node2 and node1.data > node2.data:
            if q:
                list.add_node(q, node1.data)  # Add a node to the end of a list
                q = q.next                    # End of a list moves to tne new position
            else:
                list.add_node(list, node1.data)  # Add a node to the beginning of a list (after the leading node)
                q = list.next                    # New end position
            node1 = node1.next
        elif node1 and node2 and node1.data <= node2.data:
            if q:
                list.add_node(q, node2.data)
                q = q.next
            else:
                list.add_node(list, node2.data)
                q = list.next
            node2 = node2.next
        if node1 == None and node2:  # If the 1st list finished first
            while node2:
                if q:
                    list.add_node(q, node2.data)
                    q = q.next
                node2 = node2.next
        if node2 == None and node1:  # If the 2nd list finished first
            while node1:
                if q:
                    list.add_node(q, node1.data)
                    q = q.next
                node1 = node1.next
    return list

l1 = List1()
l1.add_node(l1,1)
l1.add_node(l1,5)
l1.add_node(l1,7)

l1.list_print()
print()

l2 = List1()
l2.add_node(l2,2)
l2.add_node(l2,6)
l2.add_node(l2,8)
l2.add_node(l2,15)  # Extra nodes for testing purpose
l2.add_node(l2,20)

l2.list_print()
print()

l3 = List1()
l3 = merge_lists2(l1, l2)
print()
l3.list_print()

当然,递归解决方案可以更短更有吸引力,但它会更可靠吗?

【讨论】:

  • 谢谢,@PeterNazarenko!如何解决我的主要问题?
  • @Avi 1. 你真的要使用递归函数进行列表合并吗? 2、你真的要把列表数据和操作分成两个类吗?我更新了我的答案。
  • 再次感谢@PeterNazarenko,您的解决方案有效!我认为递归解决方案比传统解决方案更优雅、更短。也许我错了。唯一的问题是我的任务是否有更短或更有效的递归或其他解决方案。
  • @Avi 不,你对递归函数没有错,它们确实更优雅但有时反复无常。
猜你喜欢
  • 2014-04-25
  • 2014-09-18
  • 1970-01-01
  • 2019-02-26
  • 1970-01-01
  • 2020-05-24
  • 2011-01-21
相关资源
最近更新 更多