2017-07-09 3 views
1

Ich arbeite an einem Problem mit der Partitionierung von verknüpften Listen mit Python. Das Ziel besteht darin, eine verkettete Liste in zwei Segmente aufzuteilen, wobei das erste Segment Werte kleiner als x und das zweite Werte gleich oder größer als x sind.Warum wird diese Python-Objekteigenschaft nicht dauerhaft überschrieben?

Ich bin verwirrt rechts an der ersten Zeile der Partitionsfunktion:

current = ll.tail = ll.head 

Warum den Wert von ll.tail nicht diese Linie dauerhaft überschrieben werden? Ich dachte, Python sei eine Sprache, in der Objekte als Referenz weitergegeben werden. ll, ll.head und ll.tail sind alle Objekte, so meine Erwartung ist, dass diese Linie Gebrauch verursachen würde den Wert bei ll.tail gespeichert zu verlieren.

ll.tail speichert einen Wert, der für die Ausgabe der Funktion notwendig ist, und es ist immer noch in der Ausgabe der Funktion vorhanden (und die Ausgabe ist korrekt), aber ich verstehe nicht, wie.

Partition.py:

from LinkedList import LinkedList 


def partition(ll, x): 
    current = ll.tail = ll.head 

    while current: 
     nextNode = current.next 
     current.next = None 
     if current.value < x: 
      current.next = ll.head 
      ll.head = current 
     else: 
      ll.tail.next = current 
      ll.tail = current 
     current = nextNode 

    # Error check in case all nodes are less than x 
    if ll.tail.next is not None: 
     ll.tail.next = None 


ll = LinkedList() 
ll.generate(10, 0, 99) 
print(ll) 
partition(ll, ll.head.value) 
print(ll) 

LinkedList.py:

from random import randint 


class LinkedListNode: 

    def __init__(self, value, nextNode=None, prevNode=None): 
     self.value = value 
     self.next = nextNode 
     self.prev = prevNode 

    def __str__(self): 
     return str(self.value) 


class LinkedList: 

    def __init__(self, values=None): 
     self.head = None 
     self.tail = None 
     if values is not None: 
      self.add_multiple(values) 

    def __iter__(self): 
     current = self.head 
     while current: 
      yield current 
      current = current.next 

    def __str__(self): 
     values = [str(x) for x in self] 
     return ' -> '.join(values) 

    def __len__(self): 
     result = 0 
     node = self.head 
     while node: 
      result += 1 
      node = node.next 
     return result 

    def add(self, value): 
     if self.head is None: 
      self.tail = self.head = LinkedListNode(value) 
     else: 
      self.tail.next = LinkedListNode(value) 
      self.tail = self.tail.next 
     return self.tail 

    def add_to_beginning(self, value): 
     if self.head is None: 
      self.tail = self.head = LinkedListNode(value) 
     else: 
      self.head = LinkedListNode(value, self.head) 
     return self.head 

    def add_multiple(self, values): 
     for v in values: 
      self.add(v) 

    def generate(self, n, min_value, max_value): 
     self.head = self.tail = None 
     for i in range(n): 
      self.add(randint(min_value, max_value)) 
     return self 
+1

Was ist das Ergebnis/Verhalten, das Sie erwarten? Was ist das tatsächliche Ergebnis/Verhalten, das du bekommst? Ihr Fehler ist nicht klar. Sie sollten auch ein [mcve] erstellen, das Ihr Problem veranschaulicht. –

+1

'll.tail' wird in der Schleife dem aktuellen Ende der Liste zugewiesen. Nicht sicher, welches Problem Sie haben. Wie bei jedem Wert wird '> = x' am Ende der Liste hinzugefügt und' ll.tail' wird diesem neuen Ende zugewiesen. – AChampion

+0

Wenn ich die Zeile "current = ll.tail = ll.head" in "current = ll.head" ändere, wird dies zu einer Endlosschleife. Warum?? Ich verstehe nicht, warum es wichtig ist, dass wir den Schwanz und den Kopf auf denselben Knoten setzen. Die skizzierte Lösung erwähnt dies überhaupt nicht. – Florence

Antwort

1

Die Linie, die Sie denken, ein Problem hat, ist nicht Ihr Problem. Dieser Code zeigt, warum:

def checker(ll): 
    current = ll.tail = ll.head 
    print(current) 
    print(ll.tail) 
    print(ll.head) 
    return 
ll = LinkedList() 
ll.generate(10,0,99) 
print(ll) 
checker(ll) 
print(ll.tail) 
print(ll.head) 
print("Some other interesting behavior:") 
ll.head.value = -1 
print(ll.head) 
print(ll.tail) 
ll.head = -2 
print(ll.head) 
print(ll.tail) 

Ihren eigenen Code verwenden für die LL gibt:

73 -> 39 -> 14 -> 5 -> 47 -> 29 -> 14 -> 66 -> 70 -> 9 
73 
73 
73 
73 
73 
Some other interesting behavior: 
-1 
-1 
-2 
-1 

so die verknüpfte Liste, die Sie übergeben wird, wenn innerhalb einer Funktion geändert ändern. Beachten Sie auch das Verhalten am Ende: ll.tail zeigt jetzt auf wo ll.head zeigte, nicht ll.head selbst. Dies unterscheidet sich von den Zeigerreferenzen von C. Diese

bedeutet, dass Ihr Algorithmus ist nicht zu tun, was Sie erwarten. besonders würde ich mich darauf konzentrieren, wann die Schleife endet und die Reihenfolge des Austausches erfüllt ist (im Allgemeinen scheinen das die meisten Fehler bei LL-Aktivitäten zu sein).

Allgemeine Debugging-Techniken wie Komponententests eine Potentialfunktion (oder erwartete Fehlerursache) sind wirklich wichtig Programmierkenntnisse. Wenn Sie denken, dass etwas nicht funktioniert (oder funktioniert), dann testen Sie es. Es wird den Umfang Ihrer Fehlersuche eingrenzen und anderen helfen, Ihre Frage schneller zu beantworten, wenn Sie es nicht selbst herausfinden können.

Verwandte Themen