Вставка в отсортированный массив LinkedList в Java

У меня есть этот код ниже, где я вставляю новое целое число в сортированный LinkedList ints, но я не думаю, что это "правильный" способ делать вещи, поскольку я знаю, что есть один linkedlist с указателем на следующее значение и дважды linkedlist с указателями на следующее и Предыдущее значение. Я попытался использовать узлы для реализации приведенного ниже случая, но Java импортирует эту организацию импорта.консорциума W3C.дом.Узел (объектная модель документа) так застрял.

вставки Дела

  1. вставить в пустой массив
  2. если значение должно быть вставлено меньше всего, вставьте в начале.
  3. если значение для вставки больше, чем все, вставьте в последнем.
  4. может быть между, если значение меньше / больше определенных значений в LL.

    import java.util.*;
    
    public class MainLinkedList {
    public static void main(String[] args) {
    LinkedList<Integer> llist = new LinkedList<Integer>();
    
    llist.add(10);
    llist.add(30);
    llist.add(50);
    llist.add(60);
    llist.add(90);
    llist.add(1000);
    System.out.println("Old LinkedList " + llist);
    
    //WHat if you want to insert 70 in a sorted LinkedList
    LinkedList<Integer> newllist = insertSortedLL(llist, 70);
    System.out.println("New LinkedList " + newllist);
    }
    
    public static LinkedList<Integer> insertSortedLL(LinkedList<Integer> llist, int value){
    
        llist.add(value);
        Collections.sort(llist);
        return llist;
    
    }
    

    }

7 ответов


Это может отлично служить вашей цели:

используйте этот код:

import java.util.*;

public class MainLinkedList {
    private static LinkedList<Integer> llist;

    public static void main(String[] args) {
        llist = new LinkedList<Integer>();

        addValue(60);
        addValue(30);
        addValue(10);
        addValue(-5);
        addValue(1000);
        addValue(50);
        addValue(60);
        addValue(90);
        addValue(1000);
        addValue(0);
        addValue(100);
        addValue(-1000);
        System.out.println("Linked List is: " + llist);

    }

    private static void addValue(int val) {

        if (llist.size() == 0) {
            llist.add(val);
        } else if (llist.get(0) > val) {
            llist.add(0, val);
        } else if (llist.get(llist.size() - 1) < val) {
            llist.add(llist.size(), val);
        } else {
            int i = 0;
            while (llist.get(i) < val) {
                i++;
            }
            llist.add(i, val);
        }

    }

}

этот метод будет управлять вставкой в список отсортированным образом без использования Collections.sort(list)


если мы используем listIterator, сложность для выполнения get будет O (1).

public class OrderedList<T extends Comparable<T>> extends LinkedList<T> {

    private static final long serialVersionUID = 1L;


    public boolean orderedAdd(T element) {      
        ListIterator<T> itr = listIterator();
        while(true) {
            if (itr.hasNext() == false) {
                itr.add(element);
                return(true);
            }

            T elementInList = itr.next();
            if (elementInList.compareTo(element) > 0) {
                itr.previous();
                itr.add(element);
                System.out.println("Adding");
                return(true);
            }
        }
    }
}

@Atrakeur

"сортировка всего списка при каждом добавлении нового элемента неэффективна"

Это правда, но если вам нужно, чтобы список всегда был в отсортированном состоянии, это действительно единственный вариант.

" лучший способ-вставить элемент непосредственно туда, где он должен быть (в его правильном положении). Для этого вы можете зациклить все позиции, чтобы найти, где это число принадлежит"

это именно то, что делает пример кода.

"или используйте коллекции.binarySearch, чтобы этот оптимизированный алгоритм поиска сделал эту работу за вас"

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

Итак, какие данные структура / подход к принятию будет зависеть от ваших требований к хранению и доступу.

[редактирование] На самом деле, есть одна проблема с образцом кода: это приводит к многократному сканированию списка при циклировании.

int i = 0;
while (llist.get(i) < val) {
    i++;
}
llist.add(i, val);

вызов get (i) будет проходить список один раз, чтобы добраться до I-й позиции. Затем вызов add (i, val) пересекает его снова. Так что это будет очень медленно.

лучшим подходом было бы использовать ListIterator для обхода списка и выполните вставку. Этот интерфейс определяет метод add (), который может использоваться для вставки элемента в текущей позиции.


посмотреть com.гуглить.общий.собирать.TreeMultiset.

Это фактически отсортированный набор, который позволяет нескольким экземплярам одного и того же значения.

Это хороший компромисс для того, что вы пытаетесь сделать. Вставка дешевле, чем ArrayList, но вы все равно получаете преимущества поиска двоичного/дерева.


связанный список не является лучшей реализацией для SortedList

кроме того, сортировка всего списка при каждом добавлении нового элемента не эффективна. Лучший способ-вставить элемент непосредственно там, где он должен быть (в его правильном положении). Для этого можно зациклить все позиции, чтобы найти, где этот номер принадлежит, затем вставить его или использовать коллекции.binarySearch, чтобы этот оптимизированный алгоритм поиска сделал эту работу за вас.

BinarySearch возвращает индекс объекта, если объект находится в списке (вы можете проверить наличие дубликатов здесь, если это необходимо) или (-(точка вставки) - 1), если объект не готов в списке (а точка вставки-это индекс, где объект должен быть помещен для поддержания порядка)


вы должны найти, куда вставить данные, зная критерии заказа.

простой метод заключается в поиске грубой силы позиции вставки (перейдите по списку, двоичный поиск...).

другой метод, если вы знаете характер ваших данных, заключается в оценке позиции вставки, чтобы сократить количество проверок. Например, если вы вставляете "Zorro", и список упорядочен по алфавиту, вы должны начать с задней части списка... или оцените, где ваше письмо может быть (вероятно, ближе к концу). Это также может работать для чисел, если вы знаете, откуда они берутся и как они распределяются. Это называется интерполяционным поиском:http://en.wikipedia.org/wiki/Interpolation_search

также подумайте о пакетной вставке: Если вы вставляете много данных быстро, вы можете рассмотреть возможность выполнения многих вставок за один раз и сортировать только один раз.


вы можете сделать это в log (N) сложность времени просто. Нет необходимости перебирать все значения. вы можете использовать двоичный поиск, чтобы добавить значение, отсортированный связанный список.просто добавить значение в положение верхней границы этой функции. Контрольный код... возможно, ты лучше поймешь.

    public static int ubound(LinkedList<Integer> ln, int x) {
        int l = 0;
        int h = ln.size();
        while (l < h) {
            int mid = (l + h) / 2;
            if (ln.get(mid) <= x) l = mid + 1;
            else h = mid;
        }
        return l;
    }

    public void solve() 
    {
        LinkedList<Integer> ln = new LinkedList<>();
        ln.add(4);
        ln.add(6);
        ln.add(ubound(ln, 5), 5);
        out.println(ln);

    }

Выход : [4, 5, 6]

вы можете узнать про бинарный поиск в : https://www.topcoder.com/community/data-science/data-science-tutorials/binary-search/