1. Приоритетная структура данных
Структура данных приоритета (приоритетная очередь) в JDK7 представляет собой двоичную кучу. Чтобы быть точным, это самая маленькая куча.
Двоичная куча - это особая куча, которая представляет собой приблизительно полное двоичное дерево. Двоичная куча удовлетворяет характеристикам: значение ключа родительского узла всегда поддерживает связь с фиксированным порядком со значением ключа любого дочернего узла, а левый поддерек и правый поддерек каждого узла являются двоичной кучей.
Максимальная куча - это когда значение ключа родительского узла всегда больше или равна значению ключа любого дочернего узла. Минимальная куча - это когда значение ключа родительского узла всегда меньше или равна значению ключа любого дочернего узла.
Следующий рисунок - максимальная куча
Заголовок команды DiporityQueue - самый маленький элемент в данном порядке.
Приоритет quistieue не допускает нулевых значений и не поддерживает не совместимые объекты. Приоритет требует использования сопоставимых и сравнительных интерфейсов для сортировки объектов, и элементы в них будут обрабатываться в соответствии с приоритетом при сортировке.
Размер приоритета не ограничен, но начальный размер может быть указан при создании. При добавлении элементов очереди очередь автоматически расширяется.
Приоритет не является нитью, аналогичный приоритет BlockingQueue-это защита.
Мы знаем, что очереди следуют за первым в режиме, но иногда объекты должны обрабатываться на основе приоритета в очереди. Например, у нас есть приложение, которое генерирует отчеты о акциях в течение ежедневной торговли, которая требует обработки большого количества данных и занимает много времени обработки. Когда клиент отправляет запрос в это приложение, он фактически входит в очередь. Сначала нам нужно иметь дело с приоритетными клиентами, а затем с обычными пользователями. В этом случае приоритет Java (приоритетная очередь) будет очень полезно.
Приоритет - это неограниченная очередь, основанная на приоритетной куче. Элементы в этой очереди приоритета могут быть отсортированы естественным образом по умолчанию или отсортированы, когда очередь создается предоставленным компаратором.
Приоритетные очереди не допускают нулевых значений и не поддерживают не соответствующие объекты, такие как пользовательские классы. Приоритетная очередь требует использования сопоставимых интерфейсов Java и компаратора для сортировки объектов, и элементы в них будут обрабатываться в соответствии с приоритетом при сортировке.
Заголовок очереди приоритета - это самый маленький элемент, основанный на естественной сортировке или сортировке компаратора. Если несколько объектов имеют одинаковый вид, можно случайным образом взять любой из них. Когда мы получаем очередь, мы возвращаем объект заголовка очереди.
Размер очереди приоритета неограничен, но начальный размер может быть указан во время создания. Когда мы добавляем элементы в очередь приоритета, размер очереди автоматически увеличится.
Приоритет quire-queeue не загружена, поэтому Java обеспечивает приоритетную блокировку (реализация интерфейса блокировки) для многопоточных средах Java.
2. Приоритетный анализ исходного кода
член:
PRIAVTE TRANGEET OBJECT [] QUEUE; Private Int Size = 0;
1. Процесс построения небольшой верхней кучи по приоритету
Здесь мы используем конструктор PrivationQueue для прохождения в контейнере в качестве параметра PrialityQueue (collecntion <? Extends e> Пример:
Процесс построения небольшой верхней кучи примерно разделен на два шага:
Скопируйте данные контейнера и проверьте, являются ли данные контейнера NULL
private void initelementsfromCollection (collection <? Extends e> c) {object [] a = c.toarray (); // Если C.ToArray неправильно не возвращает объект [], скопируйте его. if (a.getClass ()! = Object []. Class) a = arrays.copyof (a, a.length, object []. class); int len = a.length; if (len == 1 || this.comparator! = null) для (int i = 0; i <len; i ++) if (a [i] == null) бросить новый nullpointerexception (); this.queue = a; this.size = a.length;} Настройтесь, чтобы данные удовлетворяли структуре небольшой верхней кучи.
Во -первых, два метода корректировки: Siftup и Siftdown
SIFTDOWN: Когда задается элемент инициализации, элемент должен быть скорректирован так, чтобы он соответствовал структурным свойствам минимальной кучи. Следовательно, значение ключа элемента x постоянно сравнивается и обменивается с ребенком сверху вниз, пока не будет обнаружено, что значение ключа элемента x меньше или равное значению ключа ребенка (то есть оно гарантированно будет меньше, чем его значения левого и правого узла) или оно падает на узел листья.
Например, как показано на следующей диаграмме, отрегулируйте этот узел 9:
private void siftdowncomparable (int k, e x) {сопоставимо <? Super E> Key = (сопоставимо <? Super E>) x; int половина = размер >>> 1; // размер/2 - это индекс первого листового узла //, если узел листьев не достигнут, пока (k <половина) {int child = (k << 1) + 1; // Left Kide объект C = очередь [ребенок]; int right = ребенок + 1; // Узнайте самых маленьких и самых маленьких детей левого и правого детей (справа <размер && ((сопоставимый <? Супер E>) c) .compareto ((e) queue [справа])> 0) c = queue [child = right]; if (key.compareto ((e) c) <= 0) Break; очередь [k] = c; k = ребенок; } queue [k] = key;} Siftup: Приоритет встает новый элемент в хвост каждый раз, когда добавляется новый элемент. Следовательно, должен быть тот же процесс регулировки, что и Siftdown, за исключением того, что он приспосабливается от нижнего (листа) вверх.
Например, заполните узел ключом 3 на следующей диаграмме:
private void siftupcomparable (int k, e x) {сопоставимо <? Super E> Key = (сопоставимо <? Super E>) x; while (k> 0) {int parent = (k - 1) >>> 1; // Получить родительский объект подписка e = queue [parent]; if (key.compareto ((e) e)> = 0) break; очередь [k] = e; k = родитель; } queue [k] = key;}Общий процесс построения небольшой верхней кучи:
Private void initFromCollection (Collection <? Extends E> C) {initelementsFromCollection (c); тяжелый(); }Среди них Heapify - это процесс Siftdown.
2. Приоритетный процесс расширения пропускной способности
Как видно из членов экземпляра, PriorityQueue поддерживает объект [], поэтому его метод расширения аналогичен ArrayList Table Order.
Здесь приведен только исходный код метода выращивания
private void grow (int mincapacity) {int oldCapacity = queue.length; // двойной размер, если маленький; иначе выращивать на 50% int newcapacity = oldCapacity + ((OldCapacity <64)? (OldCapacity + 2): (OldCapacity >> 1)); // переполненный код if (newcapacity - max_array_size> 0) newcapacity = gugecapacity (mincapacity); queue = arrays.copyof (queue, newcapacity); }Можно видеть, что, когда емкость массива не большая, емкость с каждым раз не большая. Когда емкость массива превышает 64, двойной расширяется каждый раз.
3. Приоритетная применение
EG1:
Вот самое простое применение: найти наибольшее число K-го динамических данных.
Идея состоит в том, чтобы поддерживать небольшую верхнюю кучу с размером = k.
// Данные являются динамическими данными // Хип поддерживает динамические данные // Res используется для сохранения значения K-most public boolean kthlargest (int data, int k, privityqueue <Integer> heap, int [] res) {if (heap.size () <k) {heap.offer (data); if (heap.size () == k) {res [0] = heap.peek (); вернуть истину; } вернуть false; } if (heap.peek () <data) {heap.poll (); heap.offer (data); } res [0] = heap.peek (); вернуть истину; }
EG2:
У нас есть клиент пользовательского класса, который не предоставляет никаких видов. Когда мы используем его для создания приоритетной очереди, мы должны предоставить его объектом компаратора.
Customer.java
пакет com.journaldev.collections; Public Class Customer {Private Int ID; Приватное название строки; Общественный клиент (int i, string n) {this.id = i; this.name = n; } public int getId () {return id; } public String getName () {return name; }} Мы используем случайные числа Java для генерации случайных пользовательских объектов. Для естественной сортировки мы используем целочисленный объект, который также является инкапсулированным объектом Java.
Вот последний тестовый код, показывающий, как использовать PriorityQueue:
Приоритет
пакет com.journaldev.collections; Импорт java.util.comparator; импорт java.util.priorityqueue; импорт java.util.queue; импорт java.util.random; public class privationqueeexample {public static void main (string [] args) {// Приоритетная очередь примеров примеров сортировки Случайный rand = new Random (); for (int i = 0; i <7; i ++) {integerPriorityQueue.add (новое целое число (rand.nextint (100))); } for (int i = 0; i <7; i ++) {integer in = integerPriorityQueue.poll (); System.out.println ("Процедура целого числа:"+in); } // Приоритетная очередь использования очередей в очереди <Customer> CustomerPriorityQueue = new DiportionQueue <> (7, idComparator); addDatatoQueue (CustomerPriorityQueue); PolldataFromQueue (CustomerPriorityQueue); } // Анонимный компаратор реализует общественный статический компаратор <Customer> idComparator = новый компаратор <Customer> () {@Override public int compare (клиент C1, клиент C2) {return (int) (c1.getId () - c2.getId ()); }}; // Универсальный метод, используемый для добавления данных в очередь частной статической void addDatatoQueue (Queue <Customer> CustomerPriorityQueue) {случайный rand = new Random (); for (int i = 0; i <7; i ++) {int id = rand.nextint (100); CustomerpriorityQueue.Add (новый клиент (ID, "pankaj"+id)); }} // Общий метод получения данных из очереди Private Static void polldataFromQueue (queue <Customer> customerpriorityqueue) {while (true) {customer cust = customer proiroqueue.poll (); if (cust == null) перерыв; System.out.println ("Обработка клиента с id ="+cust.getid ()); }}}} Обратите внимание, что я использую анонимный класс Java, который реализует интерфейс компаратора и реализует компаратор на основе идентификатора.
Когда я запускаю вышеуказанную программу тестирования, я получаю следующий вывод:
Обработка целое число: 9 Процессиона Интеллект: 16 Процесс Интеллект: 18 Процесс. Интеллекция: 25 Процессии целое число: 33 Процессиона Интеллекция: 75 Процессиона Интеллекция: 77 Процесс с клиентом с идентификацией = 28Processing с клиентом ID = 20 -процесс с клиентом идентификатором и ID ID. ID = 82 -й клиент с идентификатором = 96
Из выходных результатов можно ясно видеть, что затем наименьший элемент вынимается сначала в голове очереди. Если компаратор не будет реализован, при создании CustomerPriorityQueue будет брошено ClassCastException.
Исключение в потоке "Main" java.lang.classcastexception: com.journaldev.collections.customer не может быть поднят на java.lang.comparable на java.util.prioretequeue.siftupcomparable (Приоритет. java.util.priorityqueue.offer (dripityqueue.java:329) на java.util.priorityqueue.add (Приоритет com.journaldev.collections.priorityqueueexample.main (driaptionQueEexample.java:25)