【问题标题】:'NoneType' object has no attribute 'next''NoneType' 对象没有属性 'next'
【发布时间】:2019-08-21 14:04:48
【问题描述】:

我正在尝试使用 python 在单链表中实现快速排序。在我的 quicksort_recur() 中,newhead 是 Node() 类型,没有值,但 newhead 不会在 partition() 中更新其值

class Node(object):

    def __init__(self, data):
        super(Node, self).__init__()
        self.data = data
        self.next=None

class Linkedlist(object):

    def __init__(self):
        self.head = None


    #Returns the last node of the list 
    def get_tail(self, node):
        while node.next:
            node = node.next
        return node
    #Partitions the list taking the last element as the pivot 
    def  partition(self,head,end,newhead,newend):
        pivot=end
        prev=None
        curr=head
        tail=pivot

        # During partition, both the head and end of the list might change
        # which is updated in the newHead and newEnd variables        
        while curr is not pivot:
            if curr.data<pivot.data:
                # First node that has a value less than the pivot - becomes the new head 

                if newhead is None:
                    newhead=curr

                prev=curr
                curr=curr.next
            else:
                #If cur node is greater than pivot
                #Move cur node to next of tail, and change tail 

                if prev:
                    prev.next=curr.next
                temp=curr.next
                curr.next=None
                tail.next=curr
                tail=curr
                curr=temp
        # If the pivot data is the smallest element in the current list, 
        # pivot becomes the head 
        if newhead is None:
            newhead=pivot


        newend=tail

        return pivot

    #here the sorting happens exclusive of the end node 
    def quicksort_recur(self,head,end):
        lists=Linkedlist()
        if head is None or head is end:
            return head

        newhead=Node(None)

        newend=Node(None)

        #Partition the list, newHead and newEnd will be updated by the partition function 

        pivot=lists.partition(head,end,newhead,newend)
        # If pivot is the smallest element - no need to recur for the left part

        if newhead is not  pivot:
            #Set the node before the pivot node as NULL
            temp=newhead

            while temp.next is not pivot:
                temp=temp.next
            temp.next=None
            #Recur for the list before pivot 
            newhead=lists.quicksort_recur(newhead,temp)
            #Change next of last node of the left half to pivot
            temp=lists.get_tail(newhead)
            temp.next=pivot
        #Recur for the list after the pivot element 
        pivot.next=lists.quicksort_recur(pivot.next,newend)

        return newhead
    # The main function for quick sort. This is a wrapper over recursive 
    # function quickSortRecur() 
    def quick_sort(self,head):
        lists=Linkedlist()
        tail=lists.get_tail(head)
        head=lists.quicksort_recur(head,tail)
        return

lists=Linkedlist()

lists.head=Node(10)
l1=Node(11)
l2=Node(12)
l3=Node(13)

lists.head.next=l1
l1.next=l2
l2.next=l3

lists.quick_sort(lists.head)

10Traceback(最近一次调用最后一次): 文件“C:\Users\Didarul Amin\Desktop\ML algo code\practice_linked_list.py”,第 160 行,在

11
12
13
sort
    lists.quick_sort(lists.head)
  File "C:\Users\Didarul Amin\Desktop\ML algo code\practice_linked_list.py", line 130, in quick_sort
    head=lists.quicksort_recur(head,tail)
  File "C:\Users\Didarul Amin\Desktop\ML algo code\practice_linked_list.py", line 116, in quicksort_recur
    temp=temp.next
AttributeError: 'NoneType' object has no attribute 'next'
[Finished in 0.1s with exit code 1]

'''

【问题讨论】:

  • 您是否将有效的头部传递给 quick_sort() ?如果是 noneType 则 get_tail 将在这一行报错 while node.next:
  • 请检查编辑并确保它反映了您的实际代码。
  • 发布有关产生异常的代码的问题时,请始终包含完整的 Traceback - 复制并粘贴它,然后将其格式化为代码(选择它并输入 ctrl-k
  • 您还没有向我们展示使用这些类的代码 - 请阅读minimal reproducible example
  • 您是否尝试过Catch the error 并检查/打印除套件中的相关数据?结果如何?事情是否如你所愿?

标签: python python-3.x quicksort singly-linked-list


【解决方案1】:

替代示例。分区代码创建 3 个列表,elements pivot,在列表上递归!= pivot,然后将它们连接起来。添加了 push_back() 函数。缺少 pop_back()、push_front()、pop_front()。用于简化代码的虚拟节点。合并排序会更快。

class Node(object):

    def __init__(self, data):
        super(Node, self).__init__()
        self.data = data
        self.next=None

class Linkedlist(object):

    def __init__(self):
        self.head = None
        self.tail = None

    def push_back(self, data):
        new = Node(data)
        if(self.tail is None):
            self.head = self.tail = new
        else:
            self.tail.next = new
            self.tail = new

    def show(self, head, tail):
        arr = []
        if(head is None):
            print(arr)
            return
        while(True):
            if(head.data is not None):
                arr.append(head.data)
            if(head is tail):
                break
            head = head.next
        print(arr)

    def quicksort(self,head,tail):
        if(head is tail):               # if single node return
            return head,tail
        hlt = Node(None)                # head, tail < pivot list
        tlt = hlt
        heq = Node(None)                # head, tail = pivot list
        teq = heq
        hgt = Node(None)                # head, tail > pivot list
        tgt = hgt
        pivot = head
        curr  = head
        end   = tail.next
        while(curr is not end):
            if(curr.data < pivot.data):
                tlt.next = curr
                tlt = curr
            elif(curr.data == pivot.data):
                teq.next = curr
                teq = curr
            else:
                tgt.next = curr
                tgt = curr
            curr = curr.next
#       self.show(hlt,tlt)              # display partitioned lists
#       self.show(heq,teq)
#       self.show(hgt,tgt)
#       print()
        heq = heq.next                  # at least 1 node (should release node)
        if(hlt is tlt):                 # if none < pivot
            hlt = heq                   #  (should release node)
            tlt = heq
        else:                           # else recurse on list < pivot
            hlt = hlt.next              #  (should release node)
            hlt,tlt = self.quicksort(hlt,tlt)
            tlt.next = heq
        if(hgt is tgt):                 # if none > pivot
            hgt = teq                   #  (should release node)
            tgt = teq
        else:                           # else recurse on list > pivot
            hgt = hgt.next              #  (should release node)
            hgt,tgt = self.quicksort(hgt,tgt)
            teq.next = hgt
        return(hlt,tgt)

    def sort(self):
        if (self == None):              # if null reference return
            return
        if (self.head == None):         # if empty list return
            return
        self.head,self.tail = self.quicksort(self.head,self.tail)
        self.tail.next = None
        return

lists=Linkedlist()
lists.push_back(27)
lists.push_back(35)
lists.push_back(23)
lists.push_back(22)
lists.push_back(38)
lists.push_back(26)
lists.push_back(31)
lists.push_back(24)
lists.push_back(37)
lists.push_back(25)
lists.push_back(33)
lists.push_back(32)
lists.push_back(28)
lists.push_back(36)
lists.push_back(21)
lists.push_back(34)
lists.sort()
lists.show(lists.head, lists.tail)

【讨论】:

    【解决方案2】:
    newhead=Node(None)
    

    这是问题的根本原因。

    您正在将 newhead 创建为 Nonetype。

    【讨论】:

    • 在我的答案示例代码中,我创建了数据设置为“无”的虚拟节点(例如我的代码中的hlt = Node(None)),这不会影响使用该虚拟的“下一个”成员节点。试图超越“next”为 None 的列表末尾会导致问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-02
    • 2014-07-05
    • 2018-05-05
    • 2013-02-11
    • 2018-12-01
    • 2017-08-02
    相关资源
    最近更新 更多