#java #insert #linked-list
#java #вставить #связанный список
Вопрос:
У меня есть простой связанный список. Узел содержит строку (значение) и значение int (количество).
В linkedlist при вставке мне нужно вставить новый узел в алфавитном порядке. Если в списке есть узел с таким же значением, то я просто увеличиваю количество узлов.
Я думаю, что мой метод действительно облажался.
public void addToList(Node node){
//check if list is empty, if so insert at head
if(count == 0 ){
head = node;
head.setNext(null);
count ;
}
else{
Node temp = head;
for(int i=0; i<count; i ){
//if value is greater, insert after
if(node.getItem().getValue().compareTo(temp.getItem().getValue()) > 0){
node.setNext(temp.getNext());
temp.setNext(node);
}
//if value is equal just increment the counter
else if(node.getItem().getValue().compareTo(temp.getItem().getValue()) == 0){
temp.getItem().setCount(temp.getItem().getCount() 1);
}
//else insert before
else{
node.setNext(temp);
}
}
}
}
Итак, это вставка всех моих строк, но не в алфавитном порядке. Вы видите какую-либо ошибку?
public Node findIsertionPoint(Node head, Node node){
if( head == null)
return null;
Node curr = head;
while( curr != null){
if( curr.getValue().compareTo(node.getValue()) == 0)
return curr;
else if( curr.getNext() == null || curr.getNext().getValue().compareTo(node.getValue()) > 0)
return curr;
else
curr = curr.getNext();
}
return null;
}
public void insert(Node node){
Node newNode = node;
Node insertPoint = this.findIsertionPoint(this.head, node);
if( insertPoint == null)
this.head = newNode;
else{
if( insertPoint.getValue().compareTo(node.getValue()) == 0)
insertPoint.getItem().incrementCount();
else{
newNode.setNext(insertPoint.getNext());
insertPoint.setNext(newNode);
}
}
count ;
}
Комментарии:
1. @user69: Я вижу, что вы адаптировали мой псевдокод к Java. Пока хорошая работа, но по какой-то причине вы все еще не учитываете логику вставки перед,
head
когдаhead
это не такnull
, а вставленное значение меньше, чемhead
значение ‘s . Пожалуйста, посмотрите на мой псевдокод еще раз. Если вы этого не понимаете, спросите. Есть причина, по которой все здесь есть.
Ответ №1:
В вашем коде есть несколько ошибок:
- Вставка в / перед
head
на самом деле должна происходить в двух разных сценариях:- Если список пуст,
head
становитсяnode
- Если список не пуст, но
node
меньше первого элемента,head
также становитсяnode
- В любом случае,
node
ссылки на то, на чтоhead
указывалось раньше (null
или на реальный узел), иhead
теперь указывают наnode
.
- В любом случае,
- Если список пуст,
- Если вы не вставляете перед
head
, то вы, должно быть, вставляете после некоторого узла. Нам просто нужно найти, где находится это место. Возможны два сценария:node.getValue() > temp.getValue()
, иnode.getValue() < temp.getNext().getValue()
node.getValue() > temp.getValue()
иtemp.getNext() == null
- В любом случае,
node
вставляется междуtemp
иtemp.getNext()
- В любом случае,
Я предлагаю инкапсулировать поиск точки после вставки в его собственную функцию. То есть, учитывая список и значение, он должен возвращать узел. Если этот узел имеет то же значение, что и значение поиска, то просто увеличьте; в противном случае вставьте после. В качестве особого случая, верните null
, чтобы указать, что точка вставки находится перед head
.
В псевдокоде это будет выглядеть следующим образом:
FUNCTION findInsertionPoint(Node head, V value) RETURNS Node
// return null if value needs to be inserted before head
IF head == null OR value < head.getValue()
RETURN null;
// otherwise, either return a node with the given value,
// or return a node after which value should be inserted
Node curr = head;
REPEAT
IF curr.value == value
RETURN curr;
ELSEIF curr.getNext() == null OR curr.getNext().getValue() > value
RETURN curr;
ELSE
curr = curr.getNext();
PROCEDURE insert(V value) {
Node newNode = NEW Node(value);
Node insertPoint = findInsertionPoint(this.head, value);
IF insertPoint == null // insert before head
newNode.setNext(this.head);
this.head = newNode;
ELSE
IF insertPoint.getValue() == value
insertPoint.incrementCounter();
ELSE // insert after insertPoint
newNode.setNext(insertPoint.getNext());
insertPoint.setNext(newNode);
Обновление: я вижу, что вы перевели мой псевдокод на Java, но по какой-то причине вы опустили коды, которые касаются вставки перед, head
когда head
значение не является пустым. В частности, вы необъяснимым образом опустили эту часть:
IF head == null OR value < head.getValue()
// ^^^^^^^^^^^^^^^^^^^^^^^^^^
и эта часть:
IF insertPoint == null
newNode.setNext(this.head); // <<<<<<<<<<<
this.head = newNode;
Оба они необходимы; это то, что позволяет "A"
вставлять перед head
in [ "B", "C", "D" ]
.
Вам нужно понять, почему они важны, и действительно спросите себя, почему вы решили их удалить. Объясните нам, мне, себе, почему вы это сделали; осознайте ошибку и извлеките из нее урок.
Комментарии:
1. Эй, ты был прав …. на самом деле я пропустил одну строку кода…. не уверен, зачем я это сделал, не обращал внимания.
2. @user69: получите максимальную отдачу от псевдокода, а именно узнайте: (i) как обращаться ко всем «разным» сценариям и посмотреть, можно ли их упростить всего до нескольких (ii) как инкапсулировать вспомогательную логику, тестируемую и повторно используемую саму по себе.
Ответ №2:
Для этого вместо разработки с нуля моего собственного отсортированного списка я бы реализовал интерфейс Queue или расширил уже существующий PriorityQueue (или любую другую отсортированную коллекцию, которая может подойти лучше). Я бы определил класс Node как реализацию сопоставимого интерфейса или создал бы экземпляр моей очереди с помощью экземпляра Comparator и переопределил метод добавления PriorityQueue, чтобы добавить новый узел, только если другого объекта еще нет в очереди, увеличивая счетчик в противном случае. При использовании java > 5.0 для безопасности типов я бы использовал generic, чтобы разрешить только объекты Node в очереди.
Ответ №3:
Я думаю, вы хотите использовать одну из реализаций Multiset из коллекций Google.
Мультимножество работает аналогично набору, но допускает дубликаты (и подсчитывает их!). Посмотрите на TreeMultiset:
Мультимножество, которое поддерживает порядок расположения своих элементов либо в соответствии с их естественным порядком, либо с явным компаратором.
Комментарии:
1. Нет, я хочу создать свой собственный связанный список
2. @user69514: не самая лучшая идея.. Но в любом случае, если вы хотите поддерживать его самостоятельно, тогда используйте стандарт,
Map
где каждаяkey
является одной из ваших строк иvalue
является счетчиком.LinkedList
вероятно, это худший выбор для поддержания структуры данных, которую вы описали.3. это домашнее задание, он должен написать свою собственную реализацию списка, вот так просто.
Ответ №4:
Не видя полного кода, трудно выполнять отладку. Я думаю, проблема в том, что вы задаете
Node temp = head;
перед циклом, но вам нужно переназначить temp
while при переходе по списку к текущему элементу. В этом случае вы продолжаете сравнивать с head
.
Ответ №5:
- Вы позаботились о случае, когда
list
изначально пусто. Вы также должны позаботиться об особом случае, когда новый узел находится в начале списка. Если ваш список являетсяB->C->D
и вы вставляетеA
. - Полезно установить
node.next
значениеnull
(если еще не сделано). Так что, если узел будет вставлен в конце, у нас будетnull
следующий из последних узлов. - Вам необходимо обновить temp, чтобы перейти к следующему узлу, если вставка невозможна. Таким образом, вам не хватает
temp = temp.next;
Ответ №6:
Поскольку это домашнее задание, я не собираюсь давать вам никакого исходного кода. Я вижу одну большую проблему с кодом:
Предположим, в вашем списке уже есть два разных элемента, и вы вставляете новый элемент. В вашем коде вы проверяете, node
больше head
, и если да, то вставляете его сразу после, игнорируя остальные элементы в списке.
Ваш код делает что-то вроде этого. Есть некоторые недостающие детали, которые вы можете заполнить самостоятельно.
-
Если список пуст, установите
head = node
,head->next = NULL
и готово. -
В противном случае, если
node->value < head->value
, установитеnode->next = head, head = node
. -
В противном случае, если
node->value == head->value
,head->count
; -
В противном случае установите
tmp = head
. Покаtmp->next->value < node->value
, установитеtmp=tmp->next
. (проверьте наличие нулей!). -
Если
tmp->next == NULL
, (т. е. вы достигли конца списка), то установитеtmp->next = node
, и все готово. -
В противном случае, если
tmp->next->value == node->value
(т. е. вы достигли узла с тем же значением)tmp->next->count
. -
В противном случае, если
node->next = tmp->next, tmp->next = node
, и выйти