Реализация метода вставки в связанный список в python - PullRequest
1 голос
/ 02 марта 2020

Попытка создать метод для односвязного списка и попытка понять, почему этот тестовый пример терпит неудачу. Во втором классе SLinkedList у меня есть метод insert, он принимает аргумент pos, который является целым числом. Теперь в моем тестовом примере, когда я добавляю середину к позиции 4, он перестает ссылаться на любые дальнейшие узлы на связанный список, что означает, что узел, содержащий середину данных, не имеет ссылки на узел, содержащий 77. Я запутался, почему это происходит? Я запрограммировал это так, что когда current_pos == pos мы устанавливаем следующий из наших current (new_node) в current.getNext () (77). Разве я не назначил следующее из 2 на среднее, а следующее на среднее - 77?

class SLinkedListNode:
    # an instance of this class is a node in a Single Linked List
    # a node has a reference to data and reference to next
    def __init__(self,initData,initNext):
        self.data = initData
        self.next = initNext

    def getNext(self):
        return self.next

    def getData(self):
        return self.data

    def setData(self,newData):
        self.data = newData

    def setNext(self,newNext):
        self.next = newNext


class SLinkedList:
    # an instance of this class is a Singly-Linked List object
    # it has reference to the first node in the list
    def __init__(self):
        self.head = None
        self.size = 0

    def add(self,item):
        # adds an item at the start of the list
        new_node = SLinkedListNode(item,None)
        new_node.setNext(self.head)
        self.head = new_node
        self.size = self.size + 1

    def append(self,item):
        # adds an item at the end of the list
        new_node = SLinkedListNode(item,None)
        current = self.head # Start the traversal
        if self.size == 0: # check if list is empty
            self.add(item)
        else:
            while (current.getNext()!=None):
                current= current.getNext() # traversing the list
            current.setNext(new_node)
            self.size = self.size +1


    def insert(self,pos,item):
        # inserts the item at pos
        # pos should be a positive number (or zero) of type int
        assert type(pos)==int,'Error:pos is not an integer'
        assert pos>=0,'Error:pos must be positive'
        current=self.head
        new_node= SLinkedListNode(item,None)    
        if pos==0:
            self.add(item)
        elif pos==self.size:
            self.append(item)
        else:
            current_pos=0
            while(current.getNext()!=None):


                if (pos-1)==current_pos:
                    print(current.getData())
                    current.setNext(new_node)

                if pos==current_pos:
                    print(current.getData())

                    new_node.setNext(current.getNext())    
                current=current.getNext()


                current_pos+=1
            self.size+=1



   # 1--> 2--->inserteditem---> 3-->4---> 5---> 6             





        # TO DO: write assert statement that tests if pos is int
        # TO DO: write assert statement that tests that pos is not negative
        # TO DO: COMPLETE THE METHOD 



    def remove(self,item):
        # remove the node containing the item from the list
        if self.size == 0:
            raise Exception('List is Empty')
        current = self.head
        previous = None
        found = False
        while current != None and not found:
            if current.getData() == item:
                found = True
            else:
                previous = current
                current = current.getNext()
        if not found:
            raise Exception('Item not in list')
        else:
            if previous == None: # the item is in the first node of the list
                self.head = current.getNext()
            else: # item is not in the first node
                previous.setNext(current.getNext())
            self.size = self.size -1

    def index(self,item):
        # finds the location of the item in the list
        if self.size == 0:
            raise Exception('List is empty')
        position = 0
        found = False
        current = self.head
        while current != None and not found:
            if current.getData() == item:
                found = True
            else:
                current = current.getNext()
                position = position + 1
        if found:
            return position
        else:
            return 'Item not found'

    def pop(self):
        # removes the node from the end of the list and returns the item 
        if self.size == 0:
            raise Exception('List is empty')
        current = self.head
        previous = None
        while current.getNext() != None:
            previous = current
            current = current.getNext()
        if previous == None:
            self.head = None
        else:
            previous.setNext(None)
        self.size = self.size -1
        return current.getData()

    def __str__(self):
        # returns a string representation of the list
        current = self.head
        string = ''
        while current != None:
            string = string + str(current.getData())+'->'
            current = current.getNext()
        return string

    def getSize(self):
        return self.size


def main():
    # Testing Singly-Linked List
    slist = SLinkedList()
    slist.add(2)
    slist.add(4)
    slist.add('A')
    slist.append(77)
    slist.append(6)
    slist.append('Z')
    print('Original List:', slist.getSize(), 'elements')
    print(slist)
    print()
    slist.insert(0,'start')
    print('After inserting the word start at position 0:', slist.getSize(), 'elements')
    print(slist)
    print()
    slist.insert(7,'end')
    print('After inserting the word end at position 7:', slist.getSize(), 'elements')
    print(slist)
    print()
    slist.insert(4,'middle')
    print('After inserting middle at position 4:', slist.getSize(), 'elements')
    print(slist)

if __name__=="__main__":
    main()

1 Ответ

1 голос
/ 02 марта 2020

Посмотрите на этот фрагмент кода из вашего insert -метода:

else:
    current_pos=0
    while(current.getNext()!=None):
        if (pos-1)==current_pos:
            print(current.getData())
            current.setNext(new_node)

        if pos==current_pos:
            new_node.setNext(current.getNext())    

        current=current.getNext()
        current_pos+=1

Как только выполнено первое if -обусловление, вы устанавливаете свой новый узел как следующий текущий узел узел. Имейте в виду, этот новый узел не имеет ссылки на остальную часть списка. Второй оператор if не будет выполняться во время этой итерации, поэтому следующая строка, которую нужно выполнить, - current=current.getNext(), которая устанавливает current в качестве вашего нового узла, по-прежнему без ссылки на остальную часть списка . Следовательно, в следующей итерации while l oop current.getNext() оценивается как None, и ваша итерация заканчивается тут же, эффективно удаляя все узлы после вашего нового узла из списка.

Исправить для этого удалите второй if и установите следующий узел нового узла в предыдущем операторе if. Таким образом, вы сохраните ссылку на остальную часть списка.


Что касается примечания, get - и set -методы очень непыты c, вы можете получить доступ и измените эти атрибуты напрямую, например, используя current.next = whatever. Кроме того, while -l oop итерирование по всему списку кажется довольно неэффективным для задачи вставки, поскольку вы точно знаете индекс для вставки нового узла. Кроме того, ваш insert -метод сломается для позиций, превышающих длину списка, вы можете добавить еще одну проверку для этого

...