#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
.