在 python 中的两个双向链表之间传递值

Passing values between two doubly linked lists in python

我想将我的双向链表的值传递到一个新的空双向链表中,这样我就可以在不更改核心链表的情况下对 DLL 中的节点进行排序和删除。

这是它的样子:

dllToBeSorted = DoublyLinkedList()
dllToBeSorted = newDoublyLinkedList      #contents of newDoublyLinkedList here: 0 3 0 4 1 1 2 3
dllToBeSorted.sortList()
dllToBeSorted.removeDuplicates()
dllToBeSorted.display()                  #contents of dllToBeSorted here: 0 1 2 3 4 
newDoublyLinkedList.display()            #contents of newDoublyLinkedList here: 0 1 2 3 4 

但是当我尝试显示值时,两个 DLL 是相同的。我不知道为什么会这样,因为这个方法适用于普通变量(字符串、整数等等),但由于某种原因,它改变了我的两个 DLL。

我将整个可执行代码放在下面:

class Node:
    def __init__(self, data):
        self.item = data
        self.next = None
        self.prev = None

class DoublyLinkedList:
    def __init__(self):
        self.head = None
        self.start_node = None

    def insertToEmptyList(self, data):
        if self.start_node is None:
            new_node = Node(data)
            self.start_node = new_node

    def insertToEnd(self, data):
        if self.start_node is None:
            new_node = Node(data)
            self.start_node = new_node
            return
        n = self.start_node
        while n.next is not None:
            n = n.next
        new_node = Node(data)
        n.next = new_node
        new_node.prev = n

    def display(self):
        if self.start_node is None:
            print(" ")
            return
        else:
            n = self.start_node
            while n is not None:
                print(n.item, end=" ")
                n = n.next
            print("\n")

    def searchNode(self, data):
        if self.start_node is None:
            print("0")
            return
        else:
            n = self.start_node
            counter = 0
            while n is not None:
                if n.item == data:
                    counter += 1
                n = n.next
            print(counter)

    def sortList(self):
        if self.start_node is not None:
            n = self.start_node
            while n.next is not None:
                index = n.next
                while index is not None:
                    if n.item > index.item:
                        temp = n.item
                        n.item = index.item
                        index.item = temp
                    index = index.next
                n = n.next

    def removeDuplicates(self):
        if self.start_node is not None:
            n = self.start_node
            while n is not None:
                index = n.next
                while index is not None:
                    if n.item == index.item:
                        temp = index
                        index.prev.next = index.next
                        if index.next is not None:
                            index.next.prev = index.prev
                        temp = None
                    index = index.next
                n = n.next

newDoublyLinkedList = DoublyLinkedList()
newDoublyLinkedList.insertToEnd(0)
newDoublyLinkedList.insertToEnd(3)
newDoublyLinkedList.insertToEnd(0)
newDoublyLinkedList.insertToEnd(4)
newDoublyLinkedList.insertToEnd(1)
newDoublyLinkedList.insertToEnd(1)
newDoublyLinkedList.insertToEnd(2)
newDoublyLinkedList.insertToEnd(3)
    
dllToBeSorted = DoublyLinkedList()
dllToBeSorted = newDoublyLinkedList      #contents of newDoublyLinkedList here: 0 3 0 4 1 1 2 3
dllToBeSorted.sortList()
dllToBeSorted.removeDuplicates()
dllToBeSorted.display()                  #contents of dllToBeSorted here: 0 1 2 3 4 
newDoublyLinkedList.display()            #contents of newDoublyLinkedList here: 0 1 2 3 4 

这是因为您正在处理指向同一数据结构 (https://www.geeksforgeeks.org/copy-python-deep-copy-shallow-copy/) 的 2 个不同变量。 在 DoublyLinkedList 中覆盖 copy 应该可以解决问题。

def __copy__(self):
    newList = DoublyLinkedList()
    # add all data from self to newList
    return newList

因此您的代码将变为:

dllToBeSorted = DoublyLinkedList()
dllToBeSorted = newDoublyLinkedList.copy()      #contents of newDoublyLinkedList here: 0 3 0 4 1 1 2 3
dllToBeSorted.sortList()
dllToBeSorted.removeDuplicates()
dllToBeSorted.display()                  #contents of dllToBeSorted here: 0 1 2 3 4 
newDoublyLinkedList.display()            #contents of newDoublyLinkedList here: 0 1 2 3 4 

要理解您的问题,您必须理解这个小例子。

my_data = [1,2,3]

def my_func(data):
    data.append(100)
    return data

print("You sent: ", my_data)

# Calling my function to add an element to the list and returning the result
result_data = my_func(my_data)

print("I changed it to: ", result_data)
print("Your original input: ", my_data)

我们没想到作为参数传递的列表会被修改,但它被修改了。详细答案可以阅读this article

所以基本上您是在幕后对原始 lists/items 执行所有排序操作,并且您的显示功能会获得相同的输出。

您可以使用 python 列表复制功能(或为您的 class 创建一个实现)

为了使我的示例按预期工作,您可以使用

调用函数 my_func
# result_data = my_func(my_data) Old way
result_data = my_func( my_data.copy() )

我建议采用不同的方法。

制作双向链表:

  • 循环,包括一个哨兵节点。这个哨兵节点可以通过从 Node.
  • 继承 DoublyLinkedList 来实例化
  • 可迭代,无需重复代码即可轻松迭代、打印、搜索
  • 使用本机排序作为解决方案(这是值得商榷的,但至少它会比冒泡排序更快)。
  • 排序时
  • 到return一个列表,而不是就地排序
  • 使用带有可选参数的构造函数来填充列表

Node 构造函数为其 prev/next 属性采用可选参数,并为其提供一个 isolate 方法,使其与邻居分离,缩小差距,因此这些邻居成为彼此的邻居。

看看这种方法给您的代码带来了什么:

class Node:
    def __init__(self, data=None, prev=None, nxt=None):  # optional arguments
        self.item = data
        # Avoid that any next/prev becomes None. Should always reference a Node
        self.next = nxt or self  # default to referring to itself
        self.prev = prev or self
        # Make consistent
        self.next.prev = self
        self.prev.next = self

    # Method to detach the node from its neighbors
    def isolate(self):
        self.prev.next = self.next
        self.next.prev = self.prev
        self.next = self.prev = self


# Subclassing makes the list a sentinel node.
#   It does not count as a data node, but its next attribute will
#   reference the first node (if any, else itself), and its prev
#   attribute will reference the last node (if any, else itself)
class DoublyLinkedList(Node):  
    def __init__(self, *values): 
        super().__init__()
        for data in values:
            self.insertToEnd(data)

    def insertToFront(self, data):
        Node(data, self, self.next)

    def insertToEnd(self, data):
        Node(data, self.prev, self)

    def __iter__(self):  # This is very useful to have!!
        node = self.next
        while node is not self:
            yield node.item
            node = node.next

    def __repr__(self):
        return " ".join(map(repr, self))
    
    def display(self):  # Not really needed, as 
        print(self)  # ... the list is printable

    def search(self, data):
        # Return the index of first occurrence, -1 if not found:
        return next((i for i, item in enumerate(self) if item == data), -1)

    def sorted(self):
        return DoublyLinkedList(*sorted(self))

    def removeDuplicates(self):
        node = self.next
        while node.next is not self:
            if node.item == node.next.item:
                node.next.isolate()
            else:
                node = node.next

myList = DoublyLinkedList(0, 3, 0, 4, 1, 1, 2 ,3)
print(myList)

mySorted = myList.sorted()
mySorted.removeDuplicates()
print(mySorted)  # 1 2 3 4