简体   繁体   English

将两个链表中的公共元素插入到第三个链表中

[英]Inserting the common elements from two linked lists in a third linked list

I had been working on a program to take common elements from two linked lists and append those elements into a third linked list.我一直在开发一个程序,以从两个链表中获取公共元素,并将 append 这些元素放入第三个链表中。 I was able to print out the common elements (nodes) from the two linked lists but i am unable to append those elements in a third linked list.我能够从两个链表中打印出公共元素(节点),但我无法在第三个链表中 append 那些元素。 Any sort of help would really be appreciated: This is the complete code:任何形式的帮助将不胜感激:这是完整的代码:

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

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

    def sortedinsert(self, data):
        current_node = self.head
        if current_node==None:
            new_node = Node(data)
            self.head = new_node
            return
        if current_node.data > data:
            new_node = Node(data)
            new_node.next = current_node
            self.head = new_node
            return
        while current_node.next is not None:
            if current_node.next.data > data:
                break
            current_node = current_node.next
        new_node = Node(data)
        new_node.next = current_node.next
        current_node.next = new_node
        return

    def delete(self, item):
        current_node = self.head
        if current_node and current_node.data == item:
            self.head = current_node.next
            current_node = None
            return
        previous_node = None
        while current_node and current_node.data != item:
            previous_node = current_node
            current_node = current_node.next
        if current_node is None:
            return
        previous_node.next = current_node.next
        current_node = None

    def deletebefore(self, value):
        current_node = self.head
        previous_node = None

        if current_node.data == value:
            print("There is no previous character")
            return

        while current_node.next.data != value:
            previous_node = current_node
            current_node = current_node.next
            if current_node.next == None:
                print("Given character not found")
                return

        if previous_node == None and current_node.next.data == value:
            self.head = current_node.next
            current_node = None
            return

        if current_node.next.data == value and previous_node:
            previous_node.next = current_node.next
            current_node = None

    def update(self, prev_value, new_value):
        new_value=Node(new_value)
        current_node = self.head
        while current_node.data != prev_value:
            current_node = current_node.next
        if current_node.data == prev_value:
            current_node.data = new_value.data
            return

    def isempty(self,l1,l2,l3):
        current_node = self.head
        if current_node is None:
            print("List is empty")

        else:
            print("List is not Empty")

    def getsize(self):
        items = []
        present_node = self.head
        while present_node is not None:
            items.append(present_node.data)
            present_node = present_node.next
        print(len(items))

    def getfirst(self):
        current_node = self.head
        if current_node:
            print(current_node.data)

    def intersection(self,l1,l2):
        if l1==None and l2==None:
            print("Linked lists are empty")
        current_node = l1.head
        current_node2 = l2.head
        current_node3=self.head
        while current_node2!=None:
            if current_node2.data==current_node.data:
                if current_node3 is None:
                    current_node3=current_node2
                    if current_node2.next==None:
                        return
                    else:
                        current_node2=current_node2.next
                        current_node=current_node.next
                else:
                    while current_node3!=None:
                        current_node3=current_node3.next
                    current_node3=current_node2
                    current_node2=current_node2.next
                    current_node=current_node.next

            else:
                current_node=current_node.next
                if current_node==None:
                    current_node=l1.head
                    current_node2=current_node2.next

    def display(self):
        current_node=self.head
        while current_node!=None:
            print(current_node.data)
            current_node=current_node.next
def main():
    l1 = LinkedList()
    l2 = LinkedList()
    l3 = LinkedList()
    l1.sortedinsert(19)
    l1.sortedinsert(16)
    l2.sortedinsert(19)
    l2.sortedinsert(15)
    l2.sortedinsert(16)
    l3.intersection(l1,l2)

main()

Below is the part of the program that involves intersection of two lists:以下是涉及两个列表交集的程序部分:

def intersection(self,l1,l2):
        if l1==None and l2==None:
            print("Linked lists are empty")
        current_node = l1.head
        current_node2 = l2.head
        current_node3=self.head
        while current_node2!=None:
            if current_node2.data==current_node.data:
                if current_node3 is None:
                    current_node3=current_node2
                    if current_node2.next==None:
                        return
                    else:
                        current_node2=current_node2.next
                        current_node=current_node.next
                else:
                    while current_node3!=None:
                        current_node3=current_node3.next
                    current_node3=current_node2
                    current_node2=current_node2.next
                    current_node=current_node.next

            else:
                current_node=current_node.next
                if current_node==None:
                    current_node=l1.head
                    current_node2=current_node2.next

 
def main():
    l1 = LinkedList()
    l2 = LinkedList()
    l3 = LinkedList()
    l1.sortedinsert(19)
    l1.sortedinsert(16)
    l2.sortedinsert(19)
    l2.sortedinsert(15)
    l2.sortedinsert(16)
    l3.intersection(l1,l2)

main()

Problem is in intersection() method where you are re-initializing the current_node3.问题在于您正在重新初始化 current_node3 的 intersection() 方法。 Below is the fix for the same以下是相同的修复

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

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

def sortedinsert(self, data):
    current_node = self.head
    if current_node==None:
        new_node = Node(data)
        self.head = new_node
        return
    if current_node.data > data:
        new_node = Node(data)
        new_node.next = current_node
        self.head = new_node
        return
    while current_node.next is not None:
        if current_node.next.data > data:
            break
        current_node = current_node.next
    new_node = Node(data)
    new_node.next = current_node.next
    current_node.next = new_node
    return

def delete(self, item):
    current_node = self.head
    if current_node and current_node.data == item:
        self.head = current_node.next
        current_node = None
        return
    previous_node = None
    while current_node and current_node.data != item:
        previous_node = current_node
        current_node = current_node.next
    if current_node is None:
        return
    previous_node.next = current_node.next
    current_node = None

def deletebefore(self, value):
    current_node = self.head
    previous_node = None

    if current_node.data == value:
        print("There is no previous character")
        return

    while current_node.next.data != value:
        previous_node = current_node
        current_node = current_node.next
        if current_node.next == None:
            print("Given character not found")
            return

    if previous_node == None and current_node.next.data == value:
        self.head = current_node.next
        current_node = None
        return

    if current_node.next.data == value and previous_node:
        previous_node.next = current_node.next
        current_node = None

def update(self, prev_value, new_value):
    new_value=Node(new_value)
    current_node = self.head
    while current_node.data != prev_value:
        current_node = current_node.next
    if current_node.data == prev_value:
        current_node.data = new_value.data
        return

def isempty(self,l1,l2,l3):
    current_node = self.head
    if current_node is None:
        print("List is empty")

    else:
        print("List is not Empty")

def getsize(self):
    items = []
    present_node = self.head
    while present_node is not None:
        items.append(present_node.data)
        present_node = present_node.next
    print(len(items))

def getfirst(self):
    current_node = self.head
    if current_node:
        print(current_node.data)

def intersection(self,l1,l2):
    if l1==None and l2==None:
        print("Linked lists are empty")
    current_node = l1.head
    current_node2 = l2.head
    current_node3=self.head
    while current_node2!=None:
        if current_node2.data==current_node.data:
            if current_node3 is None:
                current_node3=current_node2 # Here is the problem. You are reinitializint the node. So, it no more points to head node
                self.head = current_node2 # Fix : set head to node 3 again
                if current_node2.next==None:
                    return
                else:
                    current_node2=current_node2.next
                    current_node=current_node.next
            else:
                while current_node3!=None:
                    current_node3=current_node3.next
                current_node3=current_node2
                current_node2=current_node2.next
                current_node=current_node.next

        else:
            current_node=current_node.next
            if current_node==None:
                current_node=l1.head
                current_node2=current_node2.next

def display(self):
    current_node=self.head
    while current_node!=None:
        print(current_node.data)
        current_node=current_node.next
def main():
l1 = LinkedList()
l2 = LinkedList()
l3 = LinkedList()
l1.sortedinsert(19)
l1.sortedinsert(16)
l2.sortedinsert(19)
l2.sortedinsert(15)
l2.sortedinsert(16)
l3.intersection(l1,l2)


def intersection(self,l1,l2):
        if l1==None and l2==None:
            print("Linked lists are empty")
        current_node = l1.head
        current_node2 = l2.head
        current_node3=self.head
        while current_node2!=None:
            if current_node2.data==current_node.data:
                if current_node3 is None:
                    current_node3=current_node2 
                    if current_node2.next==None:
                        return
                    else:
                        current_node2=current_node2.next
                        current_node=current_node.next
                else:
                    while current_node3!=None:
                        current_node3=current_node3.next
                    current_node3=current_node2
                    current_node2=current_node2.next
                    current_node=current_node.next

            else:
                current_node=current_node.next
                if current_node==None:
                    current_node=l1.head
                    current_node2=current_node2.next

def main():
    l1 = LinkedList()
    l2 = LinkedList()
    l3 = LinkedList()
    l1.sortedinsert(19)
    l1.sortedinsert(16)
    l2.sortedinsert(19)
    l2.sortedinsert(15)
    l2.sortedinsert(16)
    l3.intersection(l1,l2)
    node = l1.head

    #Print all 3 linked list
    print('List 1')
    l1.display()

    node = l2.head
    print('List 2')
    l2.display()

    node = l3.head
    print('List 3')
    l3.display()


main()

Modifiying intersect method修改相交方法

def intersection(self,l1,l2):
    if l1==None and l2==None:
        print("Linked lists are empty")
    current_node = l1.head
    current_node2 = l2.head

    while current_node2!=None:
        if current_node2.data==current_node.data:
            self.sortedinsert(current_node2.data)
            current_node2=current_node2.next
            current_node=current_node.next
        else:
            current_node=current_node.next
            if current_node==None:
                current_node=l1.head
                current_node2=current_node2.next

I have made a few changes/optimizations that are applicable if the data being held in a Node are hashable:如果Node中保存的数据是可散列的,我已经进行了一些适用的更改/优化:

  1. Added method __str__ to classes Node and LinkedList and removed method display .将方法__str__添加到类NodeLinkedList并删除方法display You can custom tailor these to your needs, but this a much more flexible way of proceeding.您可以根据自己的需要定制这些,但这是一种更灵活的处理方式。 For instance, what it you wanted to write the output of a linked list to a disk file instead of the terminal?例如,您想将链表的 output 写入磁盘文件而不是终端?
  2. isempty just reports whether the current LinkedList is empty or not and does not print anything. isempty只报告当前 LinkedList 是否为空并且不打印任何内容。
  3. getsize is made more efficient. getsize变得更有效率。
  4. intersection does not require sorted linked lists and is very efficient. intersection不需要排序的链表并且非常有效。 It does, however, require that the data stored in a node be hashable.但是,它确实要求存储在节点中的数据是可散列的。 For example, you cannot store a list in a node but you can store a tuple.例如,您不能在节点中存储list ,但可以存储元组。 A second implementation of intersection will also be presented that does not have that limitation, but it will run more slowly.还将介绍没有该限制的第二个intersection实现,但运行速度会更慢。 I just wanted to present another option.我只是想提出另一种选择。

Generally people want to be able to store items in a list in a FIFO (first in first out) order and if the only reason why you are implementing sorted insertions is for a possible need to do an intersection operation later on, you might want to rethink this.通常,人们希望能够以 FIFO(先进先出)的顺序将项目存储在列表中,如果您实现排序插入的唯一原因是以后可能需要进行交集操作,您可能想要重新考虑这一点。 My purpose was to show you a way that does not require sorted linked lists (but will work with them.).我的目的是向您展示一种不需要排序链接列表的方法(但可以使用它们。)。

The updated code:更新后的代码:

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

    def __str__(self):
        return "Node: " + str(self.data)

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

    def __str__(self):
        s = []
        s.append('LinkedList:\n')
        node = self.head
        while node:
            s.append(' ' * 4)
            s.append(str(node))
            s.append('\n')
            node = node.next
        return ''.join(s)


    def sortedinsert(self, data):
        current_node = self.head
        if current_node==None:
            new_node = Node(data)
            self.head = new_node
            return
        if current_node.data > data:
            new_node = Node(data)
            new_node.next = current_node
            self.head = new_node
            return
        while current_node.next is not None:
            if current_node.next.data > data:
                break
            current_node = current_node.next
        new_node = Node(data)
        new_node.next = current_node.next
        current_node.next = new_node
        return

    def delete(self, item):
        current_node = self.head
        if current_node and current_node.data == item:
            self.head = current_node.next
            current_node = None
            return
        previous_node = None
        while current_node and current_node.data != item:
            previous_node = current_node
            current_node = current_node.next
        if current_node is None:
            return
        previous_node.next = current_node.next
        current_node = None

    def deletebefore(self, value):
        current_node = self.head
        previous_node = None

        if current_node.data == value:
            print("There is no previous character")
            return

        while current_node.next.data != value:
            previous_node = current_node
            current_node = current_node.next
            if current_node.next == None:
                print("Given character not found")
                return

        if previous_node == None and current_node.next.data == value:
            self.head = current_node.next
            current_node = None
            return

        if current_node.next.data == value and previous_node:
            previous_node.next = current_node.next
            current_node = None

    def update(self, prev_value, new_value):
        new_value=Node(new_value)
        current_node = self.head
        while current_node.data != prev_value:
            current_node = current_node.next
        if current_node.data == prev_value:
            current_node.data = new_value.data
            return

    def isempty(self):
        return self.head is None

    def getsize(self):
        present_node = self.head
        count = 0
        while present_node is not None:
            count += 1
            present_node = present_node.next
        return count

    def getfirst(self):
        current_node = self.head
        if current_node:
            print(current_node.data)

    def intersection(self, l1, l2):
        """
        This algorithm only works if the Node holds hashable data items.
        """
        assert l1 and l2 # We assume people are passing us valid lists, which may be empty
        self.head = None # to start out empty
        if l1.isempty() or l2.isempty():
            return
        s1 = set()
        current_node = l1.head
        while current_node != None:
            s1.add(current_node.data)
            current_node = current_node.next
        s2 = set()
        current_node = l2.head
        while current_node != None:
            s2.add(current_node.data)
            current_node = current_node.next
        s_intersection = s1 & s2
        for elem in s_intersection:
            self.sortedinsert(elem)

def main():
    l1 = LinkedList()
    l2 = LinkedList()
    l3 = LinkedList()
    l1.sortedinsert(19)
    l1.sortedinsert(16)
    l2.sortedinsert(19)
    l2.sortedinsert(15)
    l2.sortedinsert(16)
    l3.intersection(l1,l2)
    print(l1)
    print(l1.getsize())
    print(l2)
    print(l3)

main()

Prints:印刷:

LinkedList:
    Node: 16
    Node: 19

2
LinkedList:
    Node: 15
    Node: 16
    Node: 19

LinkedList:
    Node: 16
    Node: 19

Update更新

If you have to store unhashable items in a Node, then the following implementation of intersection can be used:如果您必须在节点中存储不可散列的项目,则可以使用以下交集实现:

def intersection(self, l1, l2):
    assert l1 and l2 # We assume people are passing us valid lists, which may be empty
    self.head = None # to start out empty
    if l1.isempty() or l2.isempty():
        return
    list1 = []
    current_node = l1.head
    while current_node != None:
        list1.append(current_node.data)
        current_node = current_node.next
    list2 = []
    current_node = l2.head
    while current_node != None:
        list2.append(current_node.data)
        current_node = current_node.next
    list_intersection = [elem for elem in list1 if elem in list2]
    for elem in list_intersection:
        self.sortedinsert(elem)

First, you want to make sure that if the linked lists have duplicated values that are in common, for example [1, 2, 2, 3] and [0, 2, 2, 3], that they do not appear in the intersection duplicated, ie the result should be [2, 3].首先,您要确保如果链表有重复的共同值,例如 [1, 2, 2, 3] 和 [0, 2, 2, 3],它们不会出现在交集重复,即结果应该是 [2, 3]。 Second, the intersection should be making copies of nodes in case an update is made to a node in one of the input lists.其次,如果对输入列表之一中的节点进行更新,则交集应该制作节点的副本。 It would also appear that your update method will potentially leave your LinkedList unsorted.看起来您的update方法可能会使您的 LinkedList 未排序。

def intersection(self, l1, l2):
    """
    This assumes both lists are sorted. This assumption may not be true due
    to method update possibly leaving list unsorted.
    """
    assert l1 and l2 # We assume people are passing us valid lists, which may be empty
    self.head = None # to start out empty
    last_node = None
    current_node_1 = l1.head
    current_node_2 = l2.head
    while current_node_1 and current_node_2:
        if current_node_1.data > current_node_2.data:
            current_node_1, current_node_2 = current_node_2, current_node_1 # if one is larger, make it current_node_2
        if current_node_1.data < current_node_2.data:
            current_node_1 = current_node_1.next
            continue
        # must be equal:
        last_data = current_node_1.data
        new_node = Node(last_data)
        if last_node is None:
            self.head = new_node
        else:
            last_node.next = new_node
        last_node = new_node
        while current_node_1 and current_node_1.data == last_data: # in case this value is not unique in the list
            current_node_1 = current_node_1.next
        while current_node_2 and current_node_2.data == last_data: # in case this value is not unique in the list
            current_node_2 = current_node_2.next


def __and__(self, l):
    """
    Usage:
    l1 = LinkedList()
    l2 = LinkedList()
    l3 = l1 & l2 # performs intersection (ideally method intersection would never be invoked explicitly and should be renamed to _intersection)
    """
    assert isinstance(l, LinkedList)
    result = LinkedList()
    result.intersection(self, l)
    return result

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM