Метод LinkedList remove (int from, int to)

Поскольку узел определяется в основном своими связями (следующий и предыдущий), удаление набора узлов в основном аналогично удалению только одного узла. У вас есть цепочка -1-2-3-4-5- и вы удаляете некоторые звенья: -1 2-3-4 5-.

public LinkedList<Elem<E>> remove(int from, int to) 
{
    Elem<E> left = head;      
    for (int i=0; i < from; i++) 
    {
        left = left.next;

    }
    Elem<E> right = left;
    for(int i = 0; i< to - from; i++){
      right = right.next;
    }
    // removing the elements from the list;
    left.next = right;
    right.previous = left;
    size -= to - from;

    //left to right are still linked, so just shove them into
    //a new linkedlist and return.
    LinkedList<Elem<E>> ret = new LinkedList<Elem<E>>();
    ret.head = left;
    ret.tail = right;
    return ret;
}

Тестовый класс:

import junit.framework.Assert;
import junit.framework.TestCase;
import junit.framework.TestSuite;

public class TestAll extends TestCase {

    public static void testRemoveStart() {

 List<Integer> l1, l2;

 l1 = new LinkedList<Integer>();

 for (int i=0; i<10; i++) {
     l1.add(i);
 }

 l2 = l1.remove(0, 4);

 Assert.assertEquals(5, l2.size());

 for (int i=0; i<5; i++) {
     Assert.assertEquals(new Integer(i), l2.get(i));
 }

 Assert.assertEquals(5, l1.size());

 for (int i=0; i<5; i++) {
     Assert.assertEquals(new Integer(i+5), l1.get(i));
 }

    }

    public static void testRemoveMiddle() {

 List<Integer> l1, l2;

 l1 = new LinkedList<Integer>();

 for (int i=0; i<10; i++) {
     l1.add(i);
 }

 l2 = l1.remove(3, 7);

 Assert.assertEquals(5, l2.size());

 for (int i=0; i<5; i++) {
     Assert.assertEquals(new Integer(i+3), l2.get(i));
 }

 Assert.assertEquals(5, l1.size());

 for (int i=0; i<3; i++) {
     Assert.assertEquals(new Integer(i), l1.get(i));
 }

 for (int i=3; i<5; i++) {
     Assert.assertEquals(new Integer(i+5), l1.get(i));
 }

    }

    public static void testRemoveLast() {

 List<Integer> l1, l2;

 l1 = new LinkedList<Integer>();

 for (int i=0; i<10; i++) {
     l1.add(i);
 }

 l2 = l1.remove(5, 9);

 Assert.assertEquals(5, l2.size());

 for (int i=0; i<5; i++) {
     Assert.assertEquals(new Integer(i+5), l2.get(i));
 }

 Assert.assertEquals(5, l1.size());

 for (int i=0; i<5; i++) {
     Assert.assertEquals(new Integer(i), l1.get(i));
 }

    }

    public static void testRemoveOne() {

 List<Integer> l1, l2;

 l1 = new LinkedList<Integer>();

 for (int i=0; i<10; i++) {
     l1.add(i);
 }

 l2 = l1.remove(5, 5);

 Assert.assertEquals(1, l2.size());

 Assert.assertEquals(new Integer(5), l2.get(0));

 Assert.assertEquals(9, l1.size());

 for (int i=0; i<5; i++) {
     Assert.assertEquals(new Integer(i), l1.get(i));
 }

 for (int i=5; i<9; i++) {
     Assert.assertEquals(new Integer(i+1), l1.get(i));
 }

    }

    public static void testExceptions() {

 List<Integer> l;

 l = new LinkedList<Integer>();

 for (int i=0; i<10; i++) {
     l.add(i);
 }

 boolean flag = false;
 try {
     l.remove(-5, -1);
 } catch (IllegalArgumentException e) {
     flag = true;
 } catch (Exception e) {
     ;
 }
 Assert.assertTrue(flag);

 for (int i=0; i<10; i++) {
     Assert.assertEquals(new Integer(i), l.get(i));
 }

 flag = false;
 try {
     l.remove(-1, 5);
 } catch (IllegalArgumentException e) {
     flag = true;
 } catch (Exception e) {
     ;
 }
 Assert.assertTrue(flag);

 for (int i=0; i<10; i++) {
     Assert.assertEquals(new Integer(i), l.get(i));
 }

 flag = false;
 try {
     l.remove(0, 10);
 } catch (IllegalArgumentException e) {
     flag = true;
 } catch (Exception e) {
     ;
 }
 Assert.assertTrue(flag);

 for (int i=0; i<10; i++) {
     Assert.assertEquals(new Integer(i), l.get(i));
 }

 flag = false;
 try {
     l.remove(5, 4);
 } catch (IllegalArgumentException e) {
     flag = true;
 } catch (Exception e) {
     ;
 }
 Assert.assertTrue(flag);

 for (int i=0; i<10; i++) {
     Assert.assertEquals(new Integer(i), l.get(i));
 }

    }


    /**
     * Runs the test suite using the textual runner.
     */

    public static void main( String[] args ) {
 TestSuite suite = new TestSuite();
 suite.addTestSuite( TestAll.class );
 junit.textui.TestRunner.run( suite );
    }

}

Ниже приведены ошибки, которые я получаю:

5 неудачных тестов: TestAll testRemoveStart testRemoveMiddle testRemoveLast testRemoveOne testExceptions File: C:\Users\Mikros0ft\Google Drive\Semester 2\ITI1121\Assignment 4\3\TestAll.java [строка: 30] Ошибка: junit.framework.AssertionFailedError: ожидаемо: ‹5> но было: ‹4> Файл: C:\Users\Mikros0ft\Google Drive\Semester 2\ITI1121\Assignment 4\3\TestAll.java [строка: 56] Ошибка: junit.framework.AssertionFailedError: ожидаемо:‹ 5> но было:‹10> Файл: C:\Users\Mikros0ft\Google Drive\Semester 2\ITI1121\Assignment 4\3\TestAll.java [строка: 86] Ошибка: junit.framework.AssertionFailedError: ожидаемо:‹5 > но было:‹14> Файл: C:\Users\Mikros0ft\Google Drive\Semester 2\ITI1121\Assignment 4\3\TestAll.java [строка: 112] Ошибка: junit.framework.AssertionFailedError: ожидаемо:‹1> но было:‹10> Файл: C:\Users\Mikros0ft\Google Drive\Semester 2\ITI1121\Assignment 4\3\TestAll.java [строка: 146] Ошибка: junit.framework.AssertionFailedError: null


person mikros0ft    schedule 09.04.2013    source источник
comment
В основном это тот же принцип, за исключением того, что после обнаружения первой точки удаления вы повторяете еще to - from - 1 узлов, а затем выполняете такое же переназначение узлов, как и в исходном методе удаления.   -  person Perception    schedule 10.04.2013


Ответы (2)


Поскольку узел определяется в основном своими связями (следующий и предыдущий), удаление набора узлов в основном аналогично удалению только одного узла. У вас есть цепочка -1-2-3-4-5- и вы удаляете некоторые звенья: -1 2-3-4 5-.

public LinkedList<Elem<E>> remove(int from, int to) 
{
    Elem<E> left = head;      
    for (int i=0; i < from; i++) 
    {
        left = left.next;

    }
    Elem<E> right = left;
    for(int i = 0; i< to - from; i++){
      right = right.next;
    }
    // removing the elements from the list;
    left.next = right;
    right.previous = left;
    size -= ((to - from)+1);

    //left to right are still linked, so just shove them into
    //a new linkedlist and return.
    LinkedList<E> ret = new LinkedList<E>();
    ret.head = left;
    ret.tail = right;
    return ret;
}
person Jainathan Leung    schedule 09.04.2013
comment
это похоже на то, что это сработает. Единственная проблема в том, что я не слежу за хвостом. - person mikros0ft; 10.04.2013
comment
ну, слева по-прежнему хранится свой следующий, у которого все еще есть свой следующий и т. д. По сути, идея состоит в том, что даже если вы удаляете эти узлы из основного связанного списка, они сами по себе являются другим связанным списком, и это все, что вам нужно вернуть. - person Jainathan Leung; 10.04.2013
comment
Итак, вот что у меня есть в конце метода: LinkedList<E> ret = new LinkedList<E>(); ret.head = left; ret.size=to+from; return ret; По какой-то причине он не соответствует моим ожидаемым результатам. - person mikros0ft; 10.04.2013
comment
как не совпадает? Является ли исходный массив, из которого элементы были удалены, правильным, или извлеченный связанный список каким-то образом испорчен? - person Jainathan Leung; 10.04.2013
comment
Упс, я отредактировал ваш ответ вместо того, чтобы отредактировать свой вопрос. Прости за это. В любом случае, я опубликовал свой тестовый пример и результаты, которые я получил. Спасибо! - person mikros0ft; 10.04.2013
comment
ret.size должен быть (to - from+1), не так ли? Если я извлекаю элементы с 3 по 7 включительно, то я испускаю 3, 4, 5, 6, 7. - person Jainathan Leung; 10.04.2013

Предполагая, что from и to оба включительно, замените это

Elem<E> right = left.next.next;

by

Elem<E> right = left.next;
for (int i = 0; i <= to - from; i++)
    right = right.next

size тоже меняется.

size -= to - from + 1

Все остальное остается прежним.

person r.v    schedule 09.04.2013