Изменение списка шаблонов

#swift

#быстрый

Вопрос:

У меня есть следующее определение списка

  class List<T> {
        var value: T
        var next: List<T>?

       func printList()
        {
          var currentValue = value 
          var nextNode = next
           print(currentValue)

          while (nextNode != nil)
          {

            currentValue = nextNode!.value
            print(currentValue)
            if(nextNode!.next == nil)
            {
              break;
            }
             nextNode = nextNode!.next

          }
        }
     }
 

и я написал расширение, чтобы перевернуть список следующим образом :

 
extension List {
        func reverse() {

        var firstNode = self
         var previousNode: List<T>? = nil
        var currentNode = firstNode
        var nextNode = firstNode.next
        while nextNode != nil {
            currentNode.next = previousNode
            previousNode = currentNode
            currentNode = nextNode!
            nextNode = currentNode.next
        }
        currentNode.next = previousNode
        firstNode = currentNode



        }
    } 

 

Однако, когда я тестировал с помощью примерного списка: var mylist = List<Int>(value:1,next :List<Int>(value:2,next:List<Int>(value:3 , next :nil)))
когда я переворачиваю его и печатаю, он просто выводит «1 ноль».Есть идеи, почему обратная функция работает не так, как ожидалось?

Ответ №1:

Давайте пройдемся по коду. Я добавил инициализатор, который вы пропустили:

 init(value:T, next:List<T>?) {
    self.value = value
    self.next = next
}
 

И создал переменную f для хранения списка, который вы используете:

 let f = List<Int>(value: 1, next: List(value: 2, next: List(value: 3, next: nil)))
 

так что f теперь {value: 1, next:{value: 2, next:{value:3, next:nil}}}

Теперь давайте посмотрим, что происходит, когда мы вызываем reverse() :

 var firstNode = self
var previousNode: List<T>? = nil
var currentNode = firstNode
var nextNode = firstNode.next
 

Хорошо, итак:

  • firstNode является ли весь список
  • previousNode равно нулю
  • currentNode снова весь список
  • nextNode является хвостом списка (т.е. {value: 2, next:{value:3, next:nil}} ).
     while nextNode != nil {
        currentNode.next = previousNode
        previousNode = currentNode
        currentNode = nextNode!
        nextNode = currentNode.next
    }
     

Итак, после одной итерации:

  • currentNode.next получит nil, что означает currentNode , что теперь просто {value: 1, next:nil}
  • previousNode получит currentNode , поэтому снова, {value: 1, next:nil}
  • currentNode станет {value: 2, next:{value:3, next:nil}}
  • nextNode получит хвост этого, т.е. {value:3, next:nil}

После второй итерации:

  • currentNode.next получит previousNode , который {value: 1, next:nil}
  • previousNode получит currentNode , так что это {значение: 2, next:{значение: 1, next:nil}}
  • currentNode становится {value 3:, next: nil}
  • nextNode снова получает хвост, то есть ноль.

Цикл останавливается в этой точке, потому nextNode что равен нулю. Следующие две строки:

     currentNode.next = previousNode
    firstNode = currentNode
 

Итак, теперь currentNode.next становится {значение: 2, следующее:{значение: 1, следующее: ноль}} и firstNode является {value 3:, next: nil} . Итак, вам вроде как удалось изменить элементы, но:

 f.reverse()
f.printList()
 

по-прежнему только печатается 1 . Что дает ?!

Если вы посмотрите reverse() , вы увидите, что ничто из того, что делает этот код, не изменяет value поле любого из задействованных списков. Изменяется только next поле, и значение next of f было установлено nil на этой первой итерации по списку, когда currentNode.next было установлено значение nil. Поэтому, когда вы печатаете f , printList() выводится только 1 , а затем останавливается.

Чтобы решить проблему, вам необходимо обратиться к value полям каждого из вложенных списков, а не только к next .