简体   繁体   English

通过 ListIterator 反转列表

[英]Reversing a List via ListIterator

I got a task where I have to reverse a List with one or more ListIterators .我有一个任务,我必须用一个或多个ListIterators反转 List 。 I am not allowed to use the Method collections.reverse() or other Methods like that.我不允许使用 Method collections.reverse()或其他类似的方法。 I am also not allowed to make a new field.我也不允许创建一个新的领域。 I can't just use a new List as well.我也不能只使用新列表。 The input has to be changed!必须改输入法!

This is what I got so far.这是我到目前为止所得到的。 But the input isn't changed:但输入没有改变:

public static <T> List<T> reverse(List <T> input) {
    ListIterator <T> listIterator2 = input.listIterator(input.size());
     ListIterator <T> listIterator =  input.listIterator(input.size());
     int u = input.size()-1;
     while(listIterator.hasNext()) {        
             listIterator.next();
            while (listIterator2.hasPrevious()) {
                listIterator.set(input.get(u));
                 listIterator2.previous(); 
                 u--;
            }
     }
     return input;
}

Here's a way to solve the problem recursively:这是递归解决问题的一种方法:

static <T> void reverse(List<T> list) {
    reverse0(list.listIterator(), list.listIterator());
}

static <T> void reverse0(ListIterator<T> in, ListIterator<T> out) {
    if (in.hasNext()) {
        T t = in.next();
        reverse0(in, out);
        out.next();
        out.set(t);
    }
}

This recurs all the way down to the end of the list using one iterator, and then on the way back up the call stack it runs forward through the list using the second iterator, setting elements along the way.这使用一个迭代器一直递归到列表的末尾,然后在返回调用堆栈的过程中,它使用第二个迭代器向前遍历列表,沿途设置元素。 This doesn't use a second list, although you could say it's cheating because the entire contents of the list are stored on the call stack....这不使用第二个列表,尽管您可以说这是作弊,因为列表的全部内容都存储在调用堆栈中....

Here's a non-recursive approach, using a similar technique to what others have shown.这是一种非递归方法,使用与其他人展示的技术类似的技术。 I think the loop and swapping logic are a bit simpler, though:不过,我认为循环和交换逻辑要简单一些:

static <T> void reverse_nonrecur(List<T> list) {
    ListIterator<T> fwd = list.listIterator();
    ListIterator<T> rev = list.listIterator(list.size());
    while (rev.previousIndex() > fwd.nextIndex()) {
        T t = rev.previous();
        rev.set(fwd.next());
        fwd.set(t);
    }
}

I've avoided using Collections.swap since that seems to be a restriction of the problem (but you wouldn't want to use it to swap elements if the list were a LinkedList (but you should almost never be using LinkedList anyway)).我已经避免使用Collections.swap因为这似乎是问题的一个限制(但如果列表是LinkedList你不会想用它来交换元素(但无论如何你几乎永远不应该使用LinkedList ))。

Doing this with iterators is a weird way, as the Collections.swap method (which is probably the easiest way to get what you need to achieve) specifically asks for indexes.使用迭代器执行此操作是一种奇怪的方式,因为Collections.swap方法(这可能是获得所需实现的最简单方法)专门要求索引。 So using those in the first place would be the way to go.因此,首先使用这些将是要走的路。 Nonetheless, you can obviously also do this with iterators.尽管如此,您显然也可以使用迭代器来做到这一点。 This could look like the following:这可能如下所示:

public static <T> List<T> reverse(List<T> input)
{
    ListIterator<T> it = input.listIterator();
    ListIterator<T> itR = input.listIterator(input.size());

    while (it.nextIndex() - itR.previousIndex() < 0)
    {
        Collections.swap(input, it.nextIndex(), itR.previousIndex());
        it.next();
        itR.previous();
    }

    return input;
}

You begin by setting up your iterators.您首先要设置迭代器。 One starts at the beginning of the list, one at the end.一个从列表的开头开始,一个在列表的末尾。

Then you loop as long as it.nextIndex() - itR.previousIndex() < 0 .然后你循环只要it.nextIndex() - itR.previousIndex() < 0 This is basically moving both iterators to the center of the List without them crossing so you don't swap back already swapped elements.这基本上是将两个迭代器移动到 List 的中心而它们不会交叉,因此您不会交换回已经交换的元素。

Finally you simply swap the elements at the corresponding indexes and move the iterators.最后,您只需交换相应索引处的元素并移动迭代器。

Update更新

As you specified that you can't directly use Collections.swap (for whatever reason) you can obviously also reinvent the wheel and just rewrite what the method does.正如您指定不能直接使用Collections.swap (无论出于何种原因),您显然也可以重新发明轮子并重写该方法的作用。

public static <T> List<T> reverse(List<T> input)
{
    ListIterator<T> it = input.listIterator();
    ListIterator<T> itR = input.listIterator(input.size());

    while (it.nextIndex() - itR.previousIndex() < 0)
    {
        T temp = input.get(it.nextIndex());
        input.set(it.nextIndex(), input.get(itR.previousIndex()));
        input.set(itR.previousIndex(), temp);

        it.next();
        itR.previous();
    }

    return input;
}

Does the exact same just without using the (honestly in all cases preferred) Collections.swap method.不使用(老实说在所有情况下都是首选) Collections.swap方法的情况下完全相同。

Using ListIterator<T> for this issue is pretty weird, however here is the solution which iterates the list twice.对这个问题使用ListIterator<T>非常奇怪,但是这里是迭代列表两次的解决方案。 Here we go without using the Collections class:这里我们不使用Collections类:

public static <T> List<T> reverse(List <T> input) {
    ListIterator<T> iterator = input.listIterator(input.size());
    List<T> reversedList = new ArrayList<>(input.size());
    while (iterator.hasPrevious()) {
        T temp = iterator.previous();
        reversedList.add(temp);
    }
    return reversedList;
}

Edit: I made a mistake.编辑:我犯了一个错误。 The method ListIterator<E> listIterator(int index) provides a ListIterator starting on the index. ListIterator<E> listIterator(int index)提供了一个从索引开始的 ListIterator。 Since you start in the end, you can iterate once and add all the elements to anew List.由于你是从最后开始,你可以迭代一次并将所有元素添加到一个新的 List 中。


Edit2: Without creating a new list, I have found you have to iterate the half of the List and get items from the end/beginning to the middle and swap them. Edit2:在不创建新列表的情况下,我发现您必须迭代列表的一半并从末尾/开头到中间获取项目并交换它们。

public static <T> List<T> reverse(List <T> input) {
    ListIterator<T> iterator = input.listIterator(input.size());
    ListIterator<T> reversedIterator = input.listIterator();
    for (int i=0; i<input.size()/2; i++) {
        T previous = iterator.previous();
        T next  = reversedIterator.next();
        iterator.set(next);
        reversedIterator.set(previous);
    }
    return input;
}

Something like this?像这样的东西?

 private static <T> List<T> reverse(List<T> list) {
        ListIterator<T> fIterator = list.listIterator();
        ListIterator<T> bIterator = list.listIterator(list.size());
        for(int i = 0; i < list.size()/2; i++) {
            T backward = bIterator.previous();
            T forward = fIterator.next();
            bIterator.set(forward);
            fIterator.set(backward);
        }
        return list;
    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM