метод подсписка связанного списка-java

Я пытаюсь написать метод subList, который возвращает список, состоящий из текущего списка объектов включительно между индексами fromIndex и toIndex.

Например, если бы у меня был список, состоящий из

3 5 7 9 11 20 23

и я позвонил subList(0,3), я должен получить новый список

3 5 7 9

вернулся.

Я использую вспомогательные методы, чтобы помочь в написании метода. Моя логика при написании этого метода заключается в том, что я назначаю головной узел узлу с индексом fromIndex, а последний узел в списке назначаю узлу с индексом toIndex, но ничего не возвращается. Любая помощь приветствуется!

РЕДАКТИРОВАТЬ: я создал метод добавления, который добавляет узлы в список. Я все еще пытаюсь написать свой собственный метод subList для работы.

EDIT2: я обновил некоторые коды, которые можно увидеть внизу (не обращайте внимания на старые выше). fromIndex и toIndex включаются в новый подсписок.

private class Node<N extends Comparable<N>> {
    private N data;
    private Node<N> next;
}

private Node<L> head;

public List() {
    head=null;
}   

public void add(Node<L> node) {
        Node<L> add = new Node<L>();
        add.data = node.data;
        add.next = null;
        getFinal().next = add;
    } 

public Node<L> getFinal(){
    Node<L> node = head;
    while (node.next != null) {
        node = node.next;
    }
    return node;
}

public int size() {
    if (head == null) return 0;
    int counter = 0;
    for (Node<L> curr = head; curr != null; curr = curr.next)
        counter++;
    return counter;
}

public List<L> subList(int fromIndex, int toIndex)
            throws IndexOutOfBoundsException {
        List<L> n=new List<L>();
        Node<L> tail= new Node<L>();
        n.head=nthItem(fromIndex);
        tail=n.getFinal();
        tail=nthItem(toIndex);
        return n;
    }

public Node<L> nthItem(int index) {
    if (index < 0 || index >= size()) 
        throw new IndexOutOfBoundsException();

    Node<L> ptr = head;

    int i = 0;
    while (ptr != null) {
        if (i == index) return ptr;
        i++;
        ptr = ptr.next;
    }

    throw new IndexOutOfBoundsException();
}

обновленный код

private void add(Node<L> node) {
        if(head==null){
            head=node;
        } else {
            getFinal().next = node;
        }
    }

public List<L> subList(int fromIndex, int toIndex)
        throws IndexOutOfBoundsException {
    if(fromIndex<0 || fromIndex>size()-1 || toIndex<0 || toIndex>size()-1){ //size() is 1 bigger than max index so I subtract 1 from size() to equal them out
         throw new IndexOutOfBoundsException();
    }

    List<L> n=new List<L>();
    Node<L> startNode = head;
    int counter=0;
    while(startNode!=null){
         if(counter>=fromIndex && counter<=toIndex){ //fromIndex and toIndex are inclusive so I've added the equals to them. However, it enters an infinite loop, which I do not understand why.
              n.add(startNode);
         }
         startNode=startNode.next;
         counter++;
    }
    return n;
}

person Community    schedule 15.10.2014    source источник


Ответы (4)


Вопрос 1 - зачем вы это делаете? LinkedList подойдет, и его не нужно переписывать...

Пункт 2 (или б) - ваша функция подсписка создает новый список, устанавливает его заголовок, а затем устанавливает временную переменную, содержащую желаемый конец подсписка...

В связанном списке, если у вас есть узел, то этот узел представляет оставшуюся часть этого списка, начиная с этой точки. Чтобы решить вашу проблему, вам нужно будет клонировать все узлы, чтобы создать свой подсписок, установив хвост последнего клона равным нулю.

Но зачем это делать?

--- РЕДАКТИРОВАТЬ - уточнить ответ

public List<L> subList(int fromIndex, int toIndex) {
    Node<L> currentInOriginal = nthItem(fromIndex);

    int count = (toIndex - fromIndex) + 1;

    List<L> newSubList = new List<L>();
    newSubList.head = new Node<L>(current.data);

    Node<L> lastItemInList = newSubList.head;
    int soFar = 1;

    currentInOriginal = currentInOriginal.next;
    while(currentInOriginal!=null && soFar<count) {
        lastItemInList.next = new Node<L>(currentInOriginal.data);
        listItemInList = lastItemInList.next;

        currentInOriginal=currentInOriginal.next;
        soFar++;
    }

    return newSubList;
}
person Ashley Frieze    schedule 15.10.2014

Возможно, вы уже это знаете, но пробовали ли вы LinkedList.sublist()? Вот вам пример:

import java.util.LinkedList;
import java.util.List;

public class GetSubListLinkedListJavaExample {

  public static void main(String[] args) {

    //create LinkedList object
    LinkedList lList = new LinkedList();

    //add elements to LinkedList
    lList.add("1");
    lList.add("2");
    lList.add("3");
    lList.add("4");
    lList.add("5");

    System.out.println("LinkedList contains : " + lList);

    /*
     * To get a sublist from Java LinkedList, use
     * List subList(int start, int end) method.
     *
     * This method returns portion of list containing element from start index
     * inclusive to end index exclusive.
     */

    List lst = lList.subList(1,4);
    System.out.println("Sublist contains : " + lst);

    /*
     * Please note that sublist is backed by the original list, so any changes
     * made to sublist will also be reflected back to original LinkedList
     */

     //remove element from sublist
     lst.remove(2);
     System.out.println("Sublist now contains : " + lst);
     System.out.println("Original LinkedList now contains : " + lList);
  }
}

/*
Output would be
LinkedList contains : [1, 2, 3, 4, 5]
Sublist contains : [2, 3, 4]
Sublist now contains : [2, 3]
Original LinkedList now contains : [1, 2, 3, 5]
*/

Надеюсь, поможет.

Клеменсио Моралес Лукас.

person Clemencio Morales Lucas    schedule 15.10.2014
comment
Это не ответ, ОП ясно сказал, что они пишут собственную реализацию. - person StackFlowed; 15.10.2014
comment
Я не вижу, что ты говоришь. Я ясно написал Может быть, вы уже знаете это. Иногда вы пишете метод и обнаруживаете, что он уже существует, взглянув на API. - person Clemencio Morales Lucas; 15.10.2014
comment
Хотя для фактического использования Java API был бы предпочтительнее, это выглядит как домашнее задание, поэтому я полагаю, что Mob Barley хотел бы получить немного больше информации о том, как использовать связанные списки, а не о том, что использовать. - person Alan; 15.10.2014

Ваш подход неверен, вы должны зацикливаться, начиная с головы, и возвращать все значения, если индекс находится между fromIndex и toIndex. Прежде чем начать, вам также необходимо убедиться, что предоставленные индексы действительны.

Что-то в этой строке

public List<L> subList(int fromIndex, int toIndex)
        throws IndexOutOfBoundsException {
    if(fromIndex<0 || fromIndex>size() || toIndex<fromIndex || toIndex>size()){
         throw new IndexOutOfBoundsException();
    }

    List<L> n=new List<L>();
    Node<L> startNode = head;
    int counter=0;
    while(startNode!=null){
         if(counter>fromIndex && counter<toIndex){
              n.add(startNode);
         }
         startNode=startNode.next;
         counter++;
    }
    return n;
}

В этом мы проверяем правильность fromIndex и toIndex, если нет, то выдается исключение. Мы перебираем весь список и вставляем элементы, которые находятся только между предоставленными индексами.


Согласно комментарию

Да, ваше добавление также неверно. То, что вы хотите сделать, это сначала установить головной узел.

public void add(Node<L> node) {
    if(head==null){
       head=node;
    } else {
      getFinal().next = node;
    }
} 
person StackFlowed    schedule 15.10.2014
comment
Я рассмотрел ваше предложение и в итоге написал свой собственный метод добавления. Я не уверен, почему он до сих пор не работает... хотя я полагаю, во-первых, не могли бы вы сказать мне, почему мой метод добавления неверен (что, как я предполагаю, является причиной)? - person ; 15.10.2014
comment
@MobBarley Пожалуйста, проверьте правку. Твоя голова тоже была не в порядке - person StackFlowed; 15.10.2014
comment
@MobBarley закончил тем, что написал свой собственный метод добавления, звучит так, как будто вам был предоставлен метод добавления как часть назначенного, и вам нужно написать свой код для этого. Если это так, может быть хорошей идеей не изменять его, если он полностью не сломан. - person Alan; 15.10.2014
comment
@wrongAnswer Я исправил метод добавления. Это просто практика, поэтому мне не давали никаких письменных методов заранее. Я попробовал то, что вы мне дали для цикла while, изменив несколько вещей, чтобы они соответствовали тому, что я получаю (toIndex и fromIndex включают в себя, поэтому я добавил равные, а не просто меньше или больше), но теперь я m входит в бесконечный цикл с equals. Я не понимаю, почему это происходит, хотя код выглядит нормально... - person ; 16.10.2014
comment
@MobBarley, не глядя на ваш код, это выстрел в темноту. Вы изменили && на || ? если вы поделитесь своим кодом, я мог бы взглянуть на него. Пожалуйста, отредактируйте вопрос. Не размещайте код в качестве комментария. - person StackFlowed; 16.10.2014
comment
@wrongAnswer Да, я отредактировал свой вопрос, забыл упомянуть об этом. Обновленный код находится внизу. Я попытался изменить && на || но я все еще вхожу в бесконечный цикл - person ; 16.10.2014
comment
Когда вы создаете узел и отправляете его в add(Node), какой следующий указатель этого узла? Кажется, у вас есть петля в связанном списке. - person StackFlowed; 16.10.2014
comment
@wrongAnswer, но тогда он должен выйти из цикла, когда узел станет нулевым после прохождения цикла. Разве это не то, что делает код (кажется)? - person ; 16.10.2014
comment
@MobBarley прочитайте это, чтобы прояснить свои сомнения. - person StackFlowed; 16.10.2014
comment
@wrongAnswer, значит, вы говорите, что мой последний узел ссылается на головной узел? Я думал, что использую единственный связанный список, а не циклический. - person ; 16.10.2014
comment
Я не могу сказать вам наверняка. Возможно, это указывает на какой-то узел в списке, который может не быть головным узлом. - person StackFlowed; 16.10.2014

Используя функцию java 8 Stream, вы можете получить подсписок из любого заданного типа списка

если вам нужен определенный тип списка вместо списка‹>, вы можете привести возвращаемый тип в методе к этому конкретному типу списка

Чтобы получить подсписок любого типа предоставления списка, такого как ArrayList, LinkedList, ArrayDeque, метод ниже может использоваться для получения подсписка любого типа.

package com.techsqually.datastructure.collections.lists.linkedlist;

import java.util.LinkedList;
import java.util.List;
import java.util.stream.Collectors;

public class LinkedListTest {


    public static void main(String[] args) {

        LinkedList<Integer> giveString = new LinkedList<>();
        giveString.add(1);
        giveString.add(2);
        giveString.add(3);
        giveString.add(4);
        giveString.add(3);
        giveString.add(5);

        System.out.println(giveString);
        System.out.println(getSubList(giveString,0,3));
    }

    public static List getSubList(LinkedList<Integer> givenList, int startIndexInclusive, int endIndexExclusive){

        return givenList.stream().collect(Collectors.toList()).subList(startIndexInclusive,endIndexExclusive);
    }
}

ВЫВОД:

[1, 2, 3, 4, 3, 5]

[1, 2, 3]

person Arpan Saini    schedule 03.09.2019