Priority Queue 소스 코드 분석
7189 단어 우선 순위 대기 열최소 더미PriorityQueue
우선 순위 더미 의 최대 우선 순위 대기 열.우선 순위 대기 열 은 먼저 대기 열 을 나 가 는 다른 대기 열 과 다르다.매번 대기 열 에서 꺼 내 는 것 은 최고 우선권 을 가 진 요소 이다.Comparator 를 제공 하지 않 으 면 우선 대기 열 에 있 는 요 소 는 기본적으로 자연 순서대로 배열 되 어 있 습 니 다. 즉, 숫자 는 기본적으로 작은 대기 열 에 있 고 문자열 은 사전 순서에 따라 배열 되 며 Comparator 에 따라 지정 할 수 있 습 니 다. 이것 은 어떤 구조 방법 을 사용 하 느 냐 에 달 려 있 습 니 다.우선 순위 대기 열 에 서 는 null 요 소 를 허용 하지 않 습 니 다.자연 정렬 에 의존 하 는 우선 순위 대기 열 은 비교 할 수 없 는 대상 을 삽입 할 수 없습니다. (이렇게 하면 ClassCastException 을 초래 할 수 있 습 니 다)
우선 순위 대기 열 은 무한 하지만 내부 용량 이 있어 대기 열 요 소 를 저장 하 는 배열 크기 를 제어 합 니 다.그것 은 보통 적어도 대열 의 크기 와 같다.우선 순위 대기 열 에 요 소 를 계속 추가 하면 서 용량 이 자동 으로 증가 합 니 다.용량 증가 정책 의 세부 사항 을 지정 할 필요 가 없습니다.
우 리 는 소스 코드 의 측면 에서 Priority Queue 가 어떻게 실현 되 었 는 지 보 자.
쌓 기:
Priority Queue 내부 의 배열 설명 은 다음 과 같 습 니 다.
private static final int DEFAULT_INITIAL_CAPACITY = 11;
/**
* Priority queue represented as a balanced binary heap: the two
* children of queue[n] are queue[2*n+1] and queue[2*(n+1)]. The
* priority queue is ordered by comparator, or by the elements'
* natural ordering, if comparator is null: For each node n in the
* heap and each descendant d of n, n <= d. The element with the
* lowest value is in queue[0], assuming the queue is nonempty.
*/
private transient Object[] queue;
우 리 는 queue 앞에서 키워드 transient 를 사용 한 것 을 발 견 했 습 니 다. 왜 일 까요?Priority Queue 의 기본 길 이 는 11 이 고 Priority Queue 는 확 대 됩 니 다
/**
* Increases the capacity of the array.
*
* @param minCapacity the desired minimum capacity
*/
private void grow(int minCapacity) {
int oldCapacity = queue.length;
// Double size if small; else grow by 50%
int newCapacity = oldCapacity + ((oldCapacity < 64) ?
(oldCapacity + 2) :
(oldCapacity >> 1));
// overflow-conscious code
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
queue = Arrays.copyOf(queue, newCapacity);
그래서 대부분의 경우 실제 데이터 의 크기 는 배열 의 quue 실제 크기 보다 작 습 니 다. 전체 quue 를 직렬 화하 면 낭비 하 는 공간 이 많 습 니 다.그래서 Priority Queue 는 스스로 writeObject 와 readObject 를 실현 하여 성능 을 향상 시 켰 다.(대상 의 서열 화 에 대해 서 는 여 기 를 보십시오)
Priority Queue 초기 화 과정 은 가장 많은 쌓 기 과정 과 대체적으로 같 습 니 다.이 과정 도 hepify 라 고 합 니 다.
물론 기 존 데 이 터 를 Priority Queue 로 바 꾸 려 면 쌓 아야 합 니 다. 빈 Priority Queue 에 새 요 소 를 추가 할 때 만 조정 하 는 과정 입 니 다.
/**
* Creates a {@code PriorityQueue} containing the elements in the
* specified collection. If the specified collection is an instance of
* a {@link SortedSet} or is another {@code PriorityQueue}, this
* priority queue will be ordered according to the same ordering.
* Otherwise, this priority queue will be ordered according to the
* {@linkplain Comparable natural ordering} of its elements.
*
* @param c the collection whose elements are to be placed
* into this priority queue
* @throws ClassCastException if elements of the specified collection
* cannot be compared to one another according to the priority
* queue's ordering
* @throws NullPointerException if the specified collection or any
* of its elements are null
*/
@SuppressWarnings("unchecked")
public PriorityQueue(Collection<? extends E> c) {
if (c instanceof SortedSet<?>) {
SortedSet<? extends E> ss = (SortedSet<? extends E>) c;
this.comparator = (Comparator<? super E>) ss.comparator();
initElementsFromCollection(ss);
}
else if (c instanceof PriorityQueue<?>) {
PriorityQueue<? extends E> pq = (PriorityQueue<? extends E>) c;
this.comparator = (Comparator<? super E>) pq.comparator();
initFromPriorityQueue(pq);
}
else {
this.comparator = null;
initFromCollection(c);
}
}
Priority Queue 는 Collection 형식 을 직접 변환 하 는 것 을 지원 합 니 다.
PriorityQueue。
쌓 기 과정:
private void heapify() {
for (int i = (size >>> 1) - 1; i >= 0; i--)
siftDown(i, (E) queue[i]);
}
private void siftDown(int k, E x) {
if (comparator != null)
siftDownUsingComparator(k, x);
else
siftDownComparable(k, x);
}
private void siftDownComparable(int k, E x) {
Comparable<? super E> key = (Comparable<? super E>)x;
int half = size >>> 1; // loop while a non-leaf
while (k < half) {
int child = (k << 1) + 1; // assume left child is least
Object c = queue[child];
int right = child + 1;
if (right < size &&
((Comparable<? super E>) c).compareTo((E) queue[right]) > 0)
c = queue[child = right];
if (key.compareTo((E) c) <= 0)
break;
queue[k] = c;
k = child;
}
queue[k] = key;
}
private void siftDownUsingComparator(int k, E x) {
int half = size >>> 1;
while (k < half) {
int child = (k << 1) + 1;
Object c = queue[child];
int right = child + 1;
if (right < size &&
comparator.compare((E) c, (E) queue[right]) > 0)
c = queue[child = right];
if (comparator.compare(x, (E) c) <= 0)
break;
queue[k] = c;
k = child;
}
queue[k] = x;
}
새로운 요 소 를 추가 하 는 과정 은 다음 과 같 습 니 다.
public boolean offer(E e) {
if (e == null)
throw new NullPointerException();
modCount++;
int i = size;
if (i >= queue.length)
grow(i + 1);
size = i + 1;
if (i == 0)
queue[0] = e;
else
siftUp(i, e);
return true;
}
매번 새로운 요 소 를 추가 할 때마다 실제로는 배열 의 맨 뒤에 증가한다.이 요 소 를 증가 시 킬 때 배열 의 길 이 를 판단 하고 조정 하 는 일련의 동작 이 있다.이 동작 들 이 조정 되면 siftUp 방법 을 조정 해 야 합 니 다.이렇게 하 는 것 은 원래 의 성질 을 보증 하기 위해 서 이다.
기타:
1. 이 실현 은 동기 화 된 것 이 아니다.스 레 드 안전 이 아 닙 니 다.여러 스 레 드 의 임의의 스 레 드 가 구조 적 으로 목록 을 수정 했다 면 이 스 레 드 는 Priority Queue 인 스 턴 스 를 동시에 방문 해 서 는 안 됩 니 다. 이 때 스 레 드 가 안전 한 Priority BlockingQueue 류 를 사용 하 십시오.
2. 이 는 offer, poll, add 방법 에 O (logn) 시간 을 제공 합 니 다.reove (Object) 와 contains (Object) 방법 에 O (n) 시간 을 제공 합 니 다.검색 방법 (peek, element, size) 에 O (1) 를 제공 합 니 다.
3. 방법 iterator () 에서 제공 하 는 교체 기 는 우선 순위 대기 열 에 있 는 요 소 를 질서 있 게 옮 겨 다 니 는 것 을 보장 하지 않 습 니 다.최소 더 미 는 뿌리 결점 이 가장 작 을 뿐 전체 가 질서 가 있다 는 것 을 보장 할 수 없 기 때문이다.
Reference: 1. http://cuisuqiang.iteye.com/blog/2019157
2. http://shmilyaw-hotmail-com.iteye.com/blog/1827136
3. http://zhidao.baidu.com/link?url=jJlf0fLjuv6Y0OjvvQqLo46PhAMdVTHau9NkmHpBYgDBDAtlBnUJrtUfDxS22ftpeR9su6m6n85K6X8W7FpvO_
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
색인 우선 대기 열: 최소 색인 우선 대기 열많은 응용 프로그램 에서 우선 대기 열 에 있 는 데 이 터 를 참조 할 수 있 습 니 다. 우 리 는 이러한 데이터 구 조 를 최소 요소 에 빠르게 접근 할 수 있 는 배열 로 볼 수 있 습 니 다....
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.