Проблема с точным удалением узлов в LinkedList

#java

#java

Вопрос:

Я написал следующий класс для создания LinkedList с отдельными значениями поверх заданного шаблона кода.

.
.

 public class LinkedElement<T> {

    private T name;
    private LinkedElement<T> link;

    public LinkedElement(T value) {
        this.name = value;
    }

    /**
     * Returns the value of the i-th linked element, assuming the current element to
     * be at index 0.
     * 
     * @param i 0-based index of the element whose value to return.
     * @return the i-th element's value, or {@code null} if there is no element with
     *         that index.
     */
    public T get(int i) {
        int iterator = i;

        if (iterator == 0) {
            return this.name;
        }
        if (this.link == null) {
            iterator = 0;
            return null;
        }
        if (iterator > 0) {
            iterator = iterator - 1;
            return this.link.get(iterator);
        }

        return null;

    }

    /**
     * Adds a new linked element holding the given value at the end of the linked
     * elements.
     * 
     * @param newVal the new value.
     */
    public void add(T newVal) {
        if (this.link == null) {
            this.link = new LinkedElement(newVal);
        } else {
            this.link.add(newVal);
        }

    }

    **/**
     * Removes the i-th element from the linked elements. If {@code i == 0}, this
     * will effectively remove the head element. Thus, this method returns the
     * linked element that is the new head element.
     * 
     * @param i index of the element to remove.
     * @return the new head element.
     */
    public LinkedElement<T> remove(int i) {
        // Store i as changeable iterator
        int iterator = i;
        // Store current head element;
        LinkedElement<T> tempNode = this;
        // If head element itself is to be removed
        if (iterator == 0) {
            if (this.link != null) {
                this.name = this.link.name;
                this.link = this.link.link;
            }
            if (this.link == null) {
                this.name = null;
                this.link = null;
            }
            return this;
            // If the element is further down in the linkedlist
            // iterate through list and invoke "remove" at the desired position inside
            // the list
        }
        if (iterator > 0) {
            iterator = iterator - 1;
            return this.link.remove(iterator);
        }
        return null;**

    }

}
 

Метод «удалить», похоже, работает нормально, когда я удаляю только один элемент и распечатываю элементы один за другим. Проблема начинается, когда я объявляю новый элемент заголовка с помощью метода remove (который возвращает новый элемент заголовка в соответствующем списке)

 public static void main(String[] args) {
    // An example
    LinkedElement<String> headElement = new LinkedElement<String>("Yo!");
    headElement.add("LA");
    headElement.add("is");
    headElement.add("about");
    headElement.add("to");
    headElement.add("witness");
    headElement.add("another");
    headElement.add("sunny");
    headElement.add("day!");

    System.out.println(headElement.get(7));          // prints "sunny"
    headElement = headElement.remove(6);  // removes "another"
    headElement = headElement.remove(0);  // removes "Yo!"
    System.out.println(headElement.get(0));          // prints "sunny"

}
 

Ожидаемый результат должен быть:

  • солнечный
  • солнечный

но я получаю

  • солнечный
  • null

Вопрос обновлен, потому что я плохо сформулировал себя.

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

1. То, что вы получаете, — это обычное поведение связанного списка. Когда вы удаляете элемент, все переупорядочивается. Вот как это должно работать.

2. Вы уверены, что хотите, чтобы ваш LinkedList работал таким образом? Основная причина, по которой следует использовать a LinkedList , заключается в том, что вы хотите, чтобы содержимое списка сдвигалось после каждого вызова remove . Однако вы можете добавить другой метод удаления, который удаляет несколько элементов за один вызов, но это противоречит всей цели a LinkedList .

3. Я обновил вопрос гораздо более релевантным тестовым кодом и более точно описал мою проблему. Пожалуйста, извините меня за то, что я плохо сформулировал себя ранее.

4. Что происходит со всеми словами перед «sunny», потому что вы удаляете только «another», и все они исчезают??

5. голосование против также, поскольку оно больше похоже на копирование-вставку, но поскольку я не видел никаких предыдущих ответов remove на этот вопрос, также предоставляется один. Похожие ответы на вопрос можно найти даже здесь, но контекст не совсем тот, даже если решение аналогично

Ответ №1:

потому что ваш элемент заголовка после удаления (0):

 LinkedElement<String> headElement = new LinkedElement<String>("what's");//0
headElement.add("up!");//1
headElement.add("That's");//2
headElement.add("Mitch");//3
headElement.add("Jones!");//4
 

и затем вы удаляете (2) из результата выше: который является «That’s»; // с индексом 2
, так что вы получаете:

 LinkedElement<String> headElement = new LinkedElement<String>("what's");//0
headElement.add("up!");//1
headElement.add("Mitch");//2
headElement.add("Jones!");//3
 

Попробуйте напечатать после удаления (0), и вы сможете получить то, что происходит!

Ответ №2:

Попробуйте это:

 public LinkedElement<T> remove(int i) {
        int iterator = i;
        // Store current head element;
        LinkedElement<T> tempNode = this;
        // If head element itself is to be removed
        if (iterator == 0) {
            if (tempNode.link != null) {
                tempNode.name = tempNode.link.name;
                tempNode.link = tempNode.link.link;
            }
            if (tempNode.link == null) {
                tempNode.name = null;
                tempNode.link = null;
            }
            return tempNode;
            // If the element is further down in the linkedlist
            // iterate through list and invoke "remove" at the desired position inside
            // the list
        }
        if (iterator > 0) {
            iterator = iterator - 2;
            return tempNode.link.remove(iterator);
        }
        return tempNode;
    }
 

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

1. Я обновил вопрос гораздо более релевантным тестовым кодом и более точно описал мою проблему. Пожалуйста, извините меня за то, что я плохо сформулировал себя ранее.

Ответ №3:

Может попробовать следующее

 public class LinkedElement<T> {

    private T value;

    private LinkedElement<T> linkToNextElement;

    public LinkedElement(T element) {
        value = element;
        linkToNextElement = null;

    }

    public static void main(String args[]) {
        LinkedElement<String> head = new LinkedElement("a");
        head.add("b");
        head.add("c");
        head.add("d");
        head.add("e");
        LinkedElement<String> newHead = head;
        for (int i = 0; i <= 6; i  ) {
            System.out.println("list["   i   "]="   head.get(i));
        }
        System.out.println("Head: value=" newHead.value "n");
        
        System.out.println("###remove(1)###");
        newHead =  head.remove(1);
        for (int i = 0; i <= 6; i  ) {
            System.out.println("list["   i   "]="   head.get(i));
        }
        System.out.println("Head: value=" newHead.value "n");
        
        System.out.println("###remove(3)###");
        newHead =head.remove(3);
        for (int i = 0; i <= 6; i  ) {
            System.out.println("list["   i   "]="   head.get(i));
        }
        System.out.println("Head: value=" newHead.value "n");
        
        System.out.println("###remove(0)###");
        newHead =head.remove(0);
        for (int i = 0; i <= 6; i  ) {
            System.out.println("list["   i   "]="   head.get(i));
        }
        System.out.println("Head: value=" newHead.value "n");
        
        System.out.println("###remove(0)###");
        newHead =head.remove(0);
        for (int i = 0; i <= 6; i  ) {
            System.out.println("list["   i   "]="   head.get(i));
        }
        System.out.println("Head: value=" newHead.value "n");
        
        System.out.println("###remove(i)###");
        newHead =head.remove(7);
        for (int i = 0; i <= 6; i  ) {
            System.out.println("list["   i   "]="   head.get(i));
        }
        System.out.println("Head: value=" newHead.value "n");
        
        System.out.println("###remove(0)###");
        newHead =head.remove(0);
        for (int i = 0; i <= 6; i  ) {
            System.out.println("list["   i   "]="   head.get(i));
        }
        //empty List
        if(newHead == null)
        {
            System.out.println("Head: value= NULL : no value for emplty list" );
        }
    }

    /**
     * Returns the value of the i-th linked element, assuming the current element to
     * be at index 0.
     * 
     * @param i 0-based index of the element whose value to return.
     * @return the i-th element's value, or {@code null} if there is no element with
     *         that index.
     */
    public T get(int i) {
        int counter = 0;
        LinkedElement<T> currElement = this;
        if (i == 0) {
            return value;
        }
        while (counter < i) {
            if (currElement.linkToNextElement != null) {
                currElement = currElement.linkToNextElement;
            } else {
                return null;
            }
            counter  ;
        }
        return currElement.value;
    }

    /**
     * Adds a new linked element holding the given value at the end of the linked
     * elements.
     * 
     * @param newVal the new value.
     */
    public void add(T newVal) {
        if (linkToNextElement == null) {
            linkToNextElement = new LinkedElement<T>(newVal);
        } else {
            linkToNextElement.add(newVal);
        }
    }

    /**
     * Removes the i-th element from the linked elements. If {@code i == 0}, this
     * will effectively remove the head element. Thus, this method returns the
     * linked element that is the new head element.
     * 
     * @param i index of the element to remove.
     * @return the new head element.
     */
    public LinkedElement<T> remove(int i) {
        int counter = 0;
        LinkedElement<T> currElement = this;
        LinkedElement<T> prevElement = null;
        LinkedElement<T> nextElement = null;
        if (i == 0) {
            if (currElement.linkToNextElement != null) {
                nextElement = currElement.linkToNextElement;
                value = nextElement.value;
                if (nextElement.linkToNextElement != null) {
                    linkToNextElement = nextElement.linkToNextElement;
                } else {
                    linkToNextElement = null;
                }
                // ;
                return nextElement;

            } else {
                value = null;
                linkToNextElement = null;

            }
            return linkToNextElement;
        }
        while (counter < i) {
            if (currElement.linkToNextElement != null) {
                prevElement = currElement;
                currElement = currElement.linkToNextElement;
            } else {
                return this;
            }
            counter  ;
        }
        if (currElement.linkToNextElement != null) {
            nextElement = currElement.linkToNextElement;
            prevElement.linkToNextElement = nextElement;
        }
        // last element
        else {
            prevElement.linkToNextElement = null;

        }
        return this;
    }
}
 

Вывод

 list[0]=a
list[1]=b
list[2]=c
list[3]=d
list[4]=e
list[5]=null
list[6]=null
Head: value=a

###remove(1)###
list[0]=a
list[1]=c
list[2]=d
list[3]=e
list[4]=null
list[5]=null
list[6]=null
Head: value=a

###remove(3)###
list[0]=a
list[1]=c
list[2]=d
list[3]=null
list[4]=null
list[5]=null
list[6]=null
Head: value=a

###remove(0)###
list[0]=c
list[1]=d
list[2]=null
list[3]=null
list[4]=null
list[5]=null
list[6]=null
Head: value=c

###remove(0)###
list[0]=d
list[1]=null
list[2]=null
list[3]=null
list[4]=null
list[5]=null
list[6]=null
Head: value=d

###remove(7)###
list[0]=d
list[1]=null
list[2]=null
list[3]=null
list[4]=null
list[5]=null
list[6]=null
Head: value=d

###remove(0)###
list[0]=null
list[1]=null
list[2]=null
list[3]=null
list[4]=null
list[5]=null
list[6]=null
Head: value= NULL : no value for empty list