#java #sorting #recursion #linked-list
#java #сортировка #рекурсия #linked-list
Вопрос:
У меня есть метод сортировки упорядоченной вставки, который сортирует элемент в связанном списке в порядке возрастания по мере его добавления.
//getData() returns the data in that Node
//getLink() returns the link to the next Node
//setLink() sets the link of the Node
//top is the reference to the first node
public void ordInsert(int newItem) {
IntNode prev = null;
IntNode next = top;
while(next!=null amp;amp; next.getData()<newItem){
prev = next;
next = next.getLink();
}
IntNode newNode = new IntNode(newItem,next);
if(prev==null)
top = newNode;
else
prev.setLink(newNode);
}
Я пытаюсь создать метод, который сортирует весь список, используя этот метод упорядоченной сортировки.
Вот что я пробовал
public void inSort(){
IntNode next = top;
if(next != null){
ordInsert(next.getData());
top.setLink(next.getLink());
inSort();
}
return;
}
Прямо сейчас это просто бесконечный рекурсивный метод, который приводит к сбою моей программы.
Мне нужно знать, что я делаю не так и как это сделать, а не код.
Input: 3000 400 40 120 70
Expected Output : 40 70 120 400 3000
Комментарии:
1. Вы не можете просто использовать
SortedSet
или просто вызватьList.sort()
?2. Не могли бы вы предоставить больше контекста? На данный момент
ordInsert
вызываетIntNode
конструктор либо с указанием next наIntNode
, либо с beingnull
. Как выглядит конструктор? ВinSort
вы повторно вставляете узлы, я правильно читаю? Узлы где-то удаляются или это действительно расширяет список? Также вы, похоже, выполняете сбросtop
, который должен неизменно указывать на начало этого списка.3. @jgb Конструктор IntNode устанавливает данные в
Node
и ссылку на следующий узел. Да, вinSort
Я повторно вставляю узлы.inSort
Метод заключается в том, чтобы взять все данные из связанного списка и переупорядочить их в порядке возрастания
Ответ №1:
Отслеживание бесконечной рекурсии
Проблема, с которой вы столкнулись сейчас, заключается в том, что узел, сортируемый в списке, не удаляется.
Давайте посмотрим на приведенный вами пример ввода:
Input: 3000 400 40 120 70
В начале top
указывает на 3000
узел. В inSort
, next
устанавливается в точку, где top
указывает, и 3000
является значением, которое нужно вставить.
При вызове ordInsert
начальное условие
while(next!=null amp;amp; next.getData()<newItem)
никогда не является истинным, потому что next.getData()
всегда равно newItem
(это тот самый объект, который вы пытаетесь повторно вставить!). Как следствие, top
узел воссоздается и вставляется вверху и top
, следовательно, устанавливается на точку там. Таким образом, список теперь:
3000 3000 400 40 120 70
с top
указанием на первый элемент.
Поскольку next
это ссылка на тот же объект, что и top
, top
ссылка s теперь устанавливается на 3000
следующий за ней. И вы оказываетесь в той же ситуации, что и раньше, только списку предшествует другой элемент.
Повторный вызов inSort()
будет повторять этот процесс бесконечно, чтобы получить результат
3000 3000 ... 3000 400 40 120 70
Проблемы
- Вставляемые элементы не удаляются, что приводит к расширению списка
- Сброс
top
ininSort
делает недействительной предпосылку для цикла while вordInsert
.
Предлагаемое решение
Метод ordInsert
работает только в том случае, если список, в который вставляется новый элемент, уже отсортирован. Итак, стратегия должна быть:
1. Detach element at index 0
2. Sort remaining list
3. insert detached element into sorted list
Таким образом, сначала сохраните ссылку на начало списка, затем переместите top
маркер к следующему элементу и установите отдельный (предыдущий верхний) элемент, на который будет указывать null
. Это не отменит предпосылку цикла while, поскольку top
все еще ссылается на начало списка (элемент с индексом 0 был удален из списка).
Затем выполните вызов inSort()
теперь сокращенного списка. После успешного вызова используйте ordInsert()
для вставки отдельного элемента. Лучше заставить его работать с IntNode
, чем создавать совершенно новый элемент.
Чтобы рекурсия сработала, подтвердите, что top
ссылается на начало списка (сокращенный [после отсоединения] или расширенный [после повторной вставки]), чтобы для любого шага рекурсии состояние программы было допустимым. И следите за базовым вариантом, когда top == null
.
Комментарии:
1. Есть идея. Но все еще немного запутался в том, как это сделать. Не могли бы вы помочь с идеей о том, как это сделать?
Ответ №2:
В inSort
условие остановки является if(next == null)
. next
является top
и top
является заголовком списка (не последним узлом). Следовательно, рекурсия никогда не останавливается.
Кроме того, вместо сортировки существующего связанного списка вы вставляете новые данные, код бесконечно дублирует узлы.