Извлечение первых n элементов из односвязного списка

#java #linked-list #singly-linked-list

#java #связанный список #односвязный список

Вопрос:

Я пытаюсь написать метод, который принимает целое число n и возвращает новый список, содержащий первые n элементов его текущего объекта List, в том же порядке, в котором они отображаются в текущем списке.

Решение, которое у меня есть, представлено ниже:

 public List firstNelements(int n) {
    List newList = newList();
    Node travel = head, last = null, newNode;
    int counter = 0;
    while (counter < n amp;amp; travel != null) {
        newNode = new Node();
        newNode.data = travel.data;

        if (last == null)
            last = newList.head = newNode;
        else last = last.next = newNode;

        counter  ;
        travel = travel.next;
    }
    return newList;
}
  

Я понимаю, что метод начинается с объявления нового списка. Оттуда он объявляет узел «travel», который используется для итерации по всему текущему списку. Кроме того, я считаю, что «последний» используется только для отслеживания последнего узла в текущем объекте.

Я также понимаю первую часть цикла while; однако я не понимаю, почему условное

 if (last == null)
            last = newList.head = newNode;
        else last = last.next = newNode;
  

присутствует. Узел «last» равен нулю при первом выполнении кода, поэтому на первой итерации я предполагаю, что мы устанавливаем newNode в начало нового списка. Но почему мы также обновляем last? Означает ли это, что «последний» отслеживает последний узел в новом списке? Я также понятия не имею, что здесь делает оператор «else».

Я проследил список {1, 2, 3} с n = 2. Однако я все еще не могу в этом разобраться. Остальная часть цикла while (после этого условия) имеет смысл для меня.

Ответ №1:

Объект, с которым вам приходится работать, похоже, представляет собой связанный список, т. Е. Каждый node имеет ссылку на следующий node в списке. Один узел является специальным и вызывается head . Это позволяет выполнять итерации по всем элементам от начала head до конца (когда .next есть null ). Во время первой итерации это head должно быть установлено так, чтобы в списке было что-то, что можно повторить позже. Когда last это null цикл while выполняется в первый раз. Если это не первый цикл, то устанавливается только .next указатель на last узел, рассмотренный в предыдущем цикле, для обеспечения надлежащей связи между элементами.

Это домашнее задание? Возможно, Java LinkedList делает что-то подобное внутри. Если это не домашнее задание, лучшим подходом было бы использовать существующие решения из Java Collection framework и, например, subList метод.

Комментарии:

1. Да, это должно быть идентично индивидуальной настройке last = newNode и last.next = newNode . Лучше всего подключить к программе отладчик Java, доступный во всех IDE, таких как Netbeans, Eclipse, IntelliJ community, который быстро упростит разработку.

Ответ №2:

 if (last == null) {
    last = newList.head = newNode;
} else {
    last = last.next = newNode;
}
  
  • Если значение last равно нулю, установите newList.head в newNode , а затем last в newNode .

  • Если значение last не равно null, установите last.next в newNode , а затем last в newNode .

Каждая итерация создает newNode = new Node() и присваивает newNode.data travel.data .

Допустим, итерация 1 создает Node1, а итерация 2 создает Node2.

В возвращаемой структуре Node1.next должен быть Node2.

Когда мы находимся на итерации 2, мы уже обработали Node1, не зная, что было дальше (т. Е. Node1.next имеет значение null). Итак, откуда Node1 знает, что «Node1.next» должен быть «Node2»?

Вот что делает это условие.

Комментарии:

1. «В возвращаемой структуре Node1.next должен быть Node2.next» — Разве Node1.next не должен быть Node2, а не Node2.next?

2. @stackofhay42 да! Спасибо — исправлено. Также уточнен порядок назначения в списке маркеров.