선택 알고리즘

Selection algorithm

컴퓨터 과학에서 선택 알고리즘목록이나 배열에서 k번째 가장 작은 숫자를 찾기 위한 알고리즘이다. 그러한 숫자를 k번째 순서 통계량이라고 한다. 여기에는 최소, 최대중위수 원소를 찾는 경우가 포함된다. O(n)-시간(최악의 경우 선형 시간) 선택 알고리즘이 있으며, 구조화된 데이터의 경우 비선형 성능이 가능하며, 정렬된 데이터의 배열은 극단적으로 O(1)가 가능하다. 선택은 가장 가까운 이웃최단 경로 문제처럼 더 복잡한 문제의 하위 문제다. 많은 선택 알고리즘은 정렬 알고리즘을 일반화함으로써 도출되며, 반대로 일부 선별 알고리즘은 반복적인 선택 적용으로 도출될 수 있다.

선택 알고리즘의 가장 간단한 경우는 목록을 반복하여 최소(또는 최대) 요소(현재까지의 최소)를 추적함으로써 최소(또는 최대) 요소를 찾는 것이며, 선택 정렬과 관련된 것으로 볼 수 있다. 반대로 선택 알고리즘의 가장 어려운 경우는 중위수를 찾는 것이다. 실제로, 전문화된 중위수 선택 알고리즘을 사용하여 중위수의 중위수와 같이 일반 선택 알고리즘을 구축할 수 있다. 가장 잘 알려진 선택 알고리즘은 Quicksort와 관련된 Quickselect로, Quicksort와 마찬가지로 (비교적으로) 최적의 평균 성능을 갖지만, 최악의 경우 최적 성능을 제공하도록 수정할 수 있다.

정렬을 통한 선택

목록 또는 배열을 정렬하고 원하는 요소를 선택하면 선택 항목을 정렬줄일 수 있다. 이 방법은 단일 요소를 선택하는 데는 비효율적이지만, 무작위 액세스의 부족으로 인해 정렬되더라도 링크된 목록에서 O(n)가 선택되지만, 어레이에 대해 하나의 초기적이고 값비싼 정렬만 필요한 어레이에서 많은 선택을 해야 할 때는 효율적이다. 일반적으로 분류에는 O(n log n) 시간이 필요하며, 여기서 radix 정렬counting sort와 같은 비비교 정렬 알고리즘으로는 하한이 가능하지만 n은 리스트의 길이다.

전체 목록 또는 배열을 정렬하는 대신 부분 정렬을 사용하여 k 가장 작은 요소 또는 k 가장 큰 요소를 선택할 수 있다. k번째 가장 작은 요소(resp, k번째 가장 큰 요소)는 부분 정렬된 리스트 중 가장 큰 요소(resp, 가장 작은 요소)가 된다. 그러면 배열에서 액세스하려면 O(1)가, 목록에서 액세스하려면 O(k)가 필요하다.

정렬되지 않은 부분 정렬

k 최소 원소가 순서가 아니라 반환되도록 부분 정렬을 완화하면 O(k log k) 계수를 제거할 수 있다. 추가 최대 선택(O(k) 시간 소요)이 필요하지만, k 이후 여전히 O(n)의 점증상 복잡성을 산출한다 실제로 파티션 기반 선택 알고리즘은 k번째 최소 요소 자체와 k번째 최소 요소(순서가 맞지 않는 다른 요소 포함)를 모두 산출한다. 이는 O(n) 시간 – Quick select의 평균 복잡성 및 정제된 파티션 기반 선택 알고리즘의 최악의 복잡성인 O(n) 시간에 수행될 수 있다.

반대로 선택 알고리즘을 지정하면 목록을 반복하고 k번째 요소보다 작은 모든 요소를 기록함으로써 O(n) 시간에 정렬되지 않은 부분 정렬(k 최소 요소 순서가 아닌 k)을 쉽게 얻을 수 있다. 이로 인해 k - 1개 미만의 원소가 발생하는 경우, 나머지 원소는 k번째 원소와 동일하다. 원소의 동일성 가능성 때문에 주의해야 한다: k번째 원소보다 크거나 큰 원소도 같을 수 있으므로 k번째 원소보다 작거나 같은 모든 원소를 포함해서는 안 된다.

따라서 정렬되지 않은 부분 정렬(가장 낮은 k 요소, 그러나 순서가 정해지지 않음)과 k번째 요소의 선택은 매우 유사한 문제다. 그들은 같은 점증적 복잡성인 O(n)를 가지고 있을 뿐만 아니라, 둘 중 하나에 대한 해결책은 간단한 알고리즘에 의해 다른 하나의 해결책으로 변환될 수 있다(k 원소의 최대치를 찾거나 k번째 원소의 값 컷오프 이하에서 목록의 필터링 원소를 찾는다).

부분 선택 정렬

부분 정렬에 의한 간단한 선택 예제는 부분 선택 정렬을 사용하는 것이다.

최소(최소)를 찾기 위한 분명한 선형 시간 알고리즘(목록 위로 반복하고 지금까지 최소(최소) 요소를 추적하기 위한 선형 시간 알고리즘은 가장 작은 1개의 원소를 선택하는 부분 선택 정렬로 볼 수 있다. 그러나 많은 다른 부분 정렬도 부분 힙 정렬과 같은 사례 k =1에 대해 이 알고리즘으로 감소한다.

보다 일반적으로 부분 선택 정렬은 O(kn) 시간이 걸리는 단순 선택 알고리즘을 산출한다. 이는 점증적으로 비효율적이지만, k가 작으면 충분히 효율적일 수 있고, 구현이 용이하다. 구체적으로는 단순히 최소값을 찾아서 시작점까지 이동시켜 k 원소가 축적될 때까지 남은 리스트에 반복한 다음 k번째 원소를 반환한다. 다음은 부분 선택 정렬 기반 알고리즘:

함수 선택(list[.n], k)은 1 ~ kminIndex = iminValue = list[i] 목록(list[.n] 목록(list[.n] ~ n do 목록(list[minValue], minValue = list[j] 및 목록[minIndex] 리턴 목록[k]을 i+1 ~ n do). 

파티션 기반 선택

선형 성능은 파티션 기반 선택 알고리즘, 가장 기본적으로 Quick selection에 의해 달성될 수 있다. Quickselect는 Quicksort의 변종이다 - 둘 다 피벗을 선택한 다음 그 피벗에 의해 데이터를 분할하지만 Quicksort는 파티션의 양쪽에서 반복하는 반면 Quickselect는 한쪽, 즉 원하는 k번째 요소가 있는 쪽에서만 반복된다. Quicksort와 마찬가지로, 이 경우 선형이지만 최악의 경우 2차 성능은 좋지 않은 최적의 평균 성능은 최적이다. 예를 들어 첫 번째 요소를 피벗으로 삼고 데이터가 이미 정렬되어 있는 경우 최대 요소를 검색하는 방식으로 이러한 현상이 발생한다. 실제로 이것은 거의 특정한 선형 성능을 산출하는 임의 요소를 피벗으로 선택함으로써 피할 수 있다. 또는 중위수의 중위수와 같은 보다 신중한 결정론적 피벗 전략을 사용할 수 있다. 이러한 것들은 하이브리드 인트로셀렉트 알고리즘(아날로그에서 인트로토트까지)에 결합되어 있는데, 퀵 선택으로 시작하지만 진행이 느리면 중위수 중위수로 떨어져 빠른 평균 성능과 O(n)의 최적 최악의 성능을 모두 얻는다.

파티션 기반 알고리즘은 일반적으로 제자리에 수행되므로 데이터가 부분적으로 정렬된다. O(n)의 추가 공간 비용으로 원본 데이터를 변경하지 않고 제자리에 배치하여 수행할 수 있다.

피벗 전략으로 중앙값 선택

Quick select 또는 Quicksort에서 피벗 전략으로 적용하여 일반 선택 알고리즘 또는 정렬 알고리즘을 산출하는 데 중위수 선택 알고리즘을 사용할 수 있으며, 중위수 선택 알고리즘이 점증적으로 최적(선형 시간)인 경우 결과 선택 알고리즘이나 정렬 알고리즘도 사용할 수 있다. 사실 정확한 중위수는 필요하지 않다. 대략적인 중위수가 충분하다. 중위수 선택 알고리즘의 중위수에서 피벗 전략은 대략적인 중위수를 계산하고 이를 피벗으로 사용하여 이 피벗을 계산하기 위해 더 작은 집합에 반복한다. 실제로 피벗 계산의 오버헤드는 유의하기 때문에 이러한 알고리즘은 일반적으로 사용되지 않지만, 이 기법은 선택 및 정렬 알고리즘과 관련하여 이론적으로 관심이 있다.

세부적으로 중앙분리대 선택 알고리즘을 부여하면 Quick select에서 피벗 전략으로 활용할 수 있어 선택 알고리즘을 얻을 수 있다. 중위수 선택 알고리즘이 O(n)를 의미하는 최적의 경우, 결과 일반 선택 알고리즘도 최적이며 다시 선형을 의미한다. 왜냐하면 Quickselect는 분할정복 알고리즘이며, 각 피벗에서 중위수를 사용하는 것은 각 스텝에서 검색 세트의 크기가 절반씩 감소하므로, 전체적인 복잡성은 각 스텝의 복잡성을 곱한 기하학적 시리즈로, 따라서 단순히 한 스텝의 복잡성을 =/ ( - ( /)의 일정한 곱으로 나눈다는 것을 의미하기 때문이다.) (시리즈 포함)

마찬가지로 중앙분리대를 찾기 위해 적용된 중앙분리대 선택 알고리즘이나 일반선택 알고리즘이 주어진다면 Quicksort에서 피벗 전략으로 활용할 수 있어 정렬 알고리즘을 얻을 수 있다. 선택 알고리즘이 O(n)를 의미하는 최적이라면 결과 정렬 알고리즘이 O(n log n)를 의미하는 최적이다. 중위수는 데이터를 균등하게 나누기 때문에 선택 알고리즘이 최적이라고 가정할 때 최적의 정렬을 보장하는 최적의 피벗이다. Quicksort의 피벗 전략(대략 중위수)을 사용하여 중위수 중위수에 대한 정렬 아날로그가 존재하며, 이와 유사하게 최적의 Quicksort를 산출한다.

선택별 증분 정렬

정렬을 통한 선택과 반대로, 반복 선택으로 점진적으로 정렬할 수 있다. 추상적으로, 선택은 오직 하나의 요소인 k번째 요소만을 산출한다. 그러나 실제 선택 알고리즘은 부분 정렬을 수반하는 경우가 많으며, 그렇게 하도록 수정할 수 있다. 부분 정렬에 의한 선택은 자연적으로 그렇게 되고, 요소들을 k까지 정렬하며, 분할에 의한 선택 또한 일부 요소들을 정렬한다: 피벗은 정확한 위치로 정렬되고, k번째 요소는 최종 피벗이 되며, 피벗들 사이의 요소들은 피벗 값 사이에 값을 가진다. Quickselect 대 Quicksort에서와 같이 파티션 기반 선택과 파티션 기반 정렬의 차이는 선택에서 각 피벗의 한 쪽에만 반복되어 피벗 양쪽에서 재귀하는 것이 아니라 피벗(로그(n) 피벗의 평균이 사용됨)만 정렬한다는 것이다.

이것은 동일한 데이터에 대한 후속 선택 속도를 높이는 데 사용될 수 있다. 극단적으로 완전히 정렬된 배열은 O(1) 선택을 허용한다. 또한 전체 정렬을 먼저 수행하는 것과 비교하여, 반복 선택에 의한 증분 정렬은 다중 선택보다 정렬 비용을 상각한다.

부분 정렬된 데이터(최대 k)의 경우, 부분 정렬된 데이터와 데이터가 정렬되는 지수 k를 기록하는 한, k보다 작거나 같은 j의 후속 선택은 이미 정렬된 것처럼 j번째 요소를 간단히 선택할 수 있고, k보다 큰 j를 선택하면 k번째 위치 위의 요소만 정렬하면 된다.

분할 데이터의 경우, 피벗 목록이 저장된 경우(예: 색인 정렬된 목록), 후속 선택은 두 피벗 사이의 간격(아래와 위의 가장 가까운 피벗)에서만 선택하면 된다. 가장 큰 이득은 비용이 많이 드는 대형 파티션을 제거하는 최상위 피벗에서 얻을 수 있는 것이다. 데이터 중간 근처에 하나의 피벗을 사용하면 향후 선택 시간이 절반으로 단축된다. 피벗 목록은 데이터가 더 정렬됨에 따라 후속 선택 항목에 걸쳐 증가할 것이며, 전체 정렬의 기초로 파티션 기반 정렬로 전달될 수도 있다.

데이터 구조를 사용하여 비선형 시간 선택

정리되지 않은 데이터 목록을 보면 최소 원소를 찾으려면 선형 시간(Ω(n))이 필요하다. 모든 원소를 조사해야 하기 때문이다(그렇지 않으면 놓칠 수도 있다). 예를 들어 목록을 항상 정렬하여 정리하면 k번째 큰 요소를 선택하는 것은 사소한 것이지만, 두 개의 목록을 결합하는 등의 다른 작업처럼 삽입하는 데는 선형 시간이 필요하다.

하위 선형의 시간에서 순서 통계를 찾는 전략은 선택을 용이하게 하는 적절한 데이터 구조를 이용하여 데이터를 정리하여 저장하는 것이다. 그러한 두 가지 데이터 구조는 트리 기반 구조와 주파수 테이블이다.

최소(또는 최대)만 필요한 경우, 삽입을 포함한 다른 모든 작업이 O(log n) 이상인 반면, 일정한 시간에 최소(또는 최대) 요소를 찾을 수 있는 을 사용하는 것이 좋은 방법이다. 보다 일반적으로 자가 균형 이진 검색 트리는 쉽게 증강되어 요소를 삽입하고 O(log n) 시간에 k번째 큰 요소를 찾을 수 있다. 이를 순서 통계 트리라고 한다. 우리는 단지 그것이 얼마나 많은 후손들을 가지고 있는지에 대한 카운트를 각 노드에 저장하고, 이것을 이용해서 어떤 경로를 따를지 결정한다. 노드를 추가하는 것은 O(log n) 선조들의 수에만 영향을 미치고, 나무 회전은 회전과 관련된 노드의 수에만 영향을 미치기 때문에 정보는 효율적으로 업데이트될 수 있다.

또 다른 간단한 전략은 해시 테이블과 몇 가지 동일한 개념에 기초한다. 우리가 값의 범위를 미리 알고 있을 때, 우리는 그 범위를 h 하위 절편으로 나누고, 그것들을 h 버킷에 할당할 수 있다. 요소를 삽입할 때, 요소가 들어가는 간격에 따라 버킷에 추가한다. 최소 또는 최대 요소를 찾기 위해 첫 번째 비어 있지 않은 버킷을 시작 또는 끝에서 스캔하고 해당 버킷에서 최소 또는 최대 요소를 찾으십시오. 일반적으로 k번째 요소를 찾기 위해 각 버킷에 있는 요소 수의 카운트를 유지한 다음, 원하는 요소를 포함하는 버킷을 찾을 때까지 왼쪽에서 오른쪽으로 버킷을 스캔하여 카운트를 추가한 다음 예상 선형 시간 알고리즘을 사용하여 해당 버킷에서 올바른 요소를 찾는다.

대략 sqrt(n) 크기의 h를 선택하고 입력이 균일하게 분포된 경우, 이 체계는 예상 O(sqrt(n) 시간에 선택을 수행할 수 있다. 불행히도 이 전략은 또한 좁은 간격의 요소들의 군집화에도 민감하게 반응하여, 많은 수의 요소가 있는 버킷을 초래할 수 있다(클러스터링은 좋은 해시함수를 통해 제거할 수 있지만, k번째 해시값을 가진 요소를 찾는 것은 그리 유용하지 않다). 또한 해시 테이블과 마찬가지로 이 구조는 요소가 추가되고 nh보다2 훨씬 더 커짐에 따라 효율을 유지하기 위해 테이블 재설정을 요구한다. 이것의 유용한 경우는 유한한 범위의 데이터에서 순서 통계량이나 극단값을 찾는 것이다. 위 표를 버킷 간격 1과 함께 사용하고 각 버킷의 카운트를 유지하는 것은 다른 방법보다 훨씬 우수하다. 이러한 해시 테이블은 기술 통계량에서 데이터를 분류하는 데 사용되는 빈도 테이블과 같다.

하한

컴퓨터 프로그래밍의 기술에서, 도널드 E. 크누스는 비조직화된 n개 항목의 목록 중 가장 작은 항목(비교만 사용)을 찾는 데 필요한 비교 횟수에 대한 많은 하한을 논의하였다. 최소 또는 최대 입력에 대해 n - 1이라는 사소한 하한이 있다. 이를 보려면 각 경기가 하나의 비교를 나타내는 토너먼트를 고려해 보십시오. 토너먼트 우승자를 제외한 모든 선수는 우리가 우승자를 알기 전에 반드시 한 게임에서 패해야 하기 때문에, 우리는 n - 1 비교의 하한선을 가지고 있다.

그 이야기는 다른 지수들에 비해 더 복잡해진다. ( ) 을(를) 가장 작은 t 을 찾는 데 필요한 최소 비교 수로 정의한다. Knuth는 S. S. Kislitsyn이 발행한 논문을 언급하는데, 이 논문은 이 가치에 대한 상한선을 보여준다.

이 경계는 t=2에 대해 달성할 수 있지만 더 좋고, 더 복잡한 경계는 더 큰 t에 대해 알려져 있다.[citation needed]

공간 복잡성

선택 시 필요한 공간 복잡성은 선택이 수행되고 있는 배열을 저장하는 것 외에 O(1) 추가 저장이다. 이러한 공간 복잡성은 최적 O(n) 시간 복잡성을 보존하면서 달성할 수 있다.[1]

온라인 선택 알고리즘

온라인 선택은 스트림의 k번째 최소 요소 계산에 근소하게 언급할 수 있으며, 이 경우 지금까지 k개의 최소 요소들을 위한 k + O(1) 공간을 가진 부분 정렬 알고리즘을 사용할 수 있지만, 파티션 기반 알고리즘은 사용할 수 없다.

대안적으로, 선택 자체는 온라인으로 요구될 수 있다. 즉, 관찰의 경우 순차 입력에서만 요소를 선택할 수 있으며, 각 선택사항은 각각 거부될 수 없다. 문제는 이러한 제약조건 하에서 (예를 들어 가장 크거나 가장 작은 값과 같이) 가장 큰 확률의 입력 시퀀스의 특정 요소를 선택하는 것이다. 이 문제는 독립 조건 하에서 최적을 산출하는 오즈 알고리즘에 의해 다루어질 수 있다. 또한 입력 길이에서 계산 횟수가 선형인 알고리즘으로서 최적이다.

가장 간단한 예는 높은 확률의 최대값을 선택하는 비서 문제인데, 이 경우 (임의 데이터에 대한) 최적 전략은 첫 번째 n/e 요소의 실행 최대치를 추적하여 이를 거부한 다음, 이 최대값보다 높은 첫 번째 요소를 선택하는 것이다.

관련 문제

선택 문제를 일반화하여 목록 내의 범위에 적용할 수 있으며 범위 쿼리 문제가 발생할 수 있다. 범위 중위수 쿼리(다중 범위의 중위수 계산)의 문제가 분석되었다.

언어 지원

목록의 가장 작거나 가장 큰 요소를 찾을 수 있는 시설을 제공하는 언어가 많지만, 일반 선택을 지원하는 언어는 거의 없다. 주목할 만한 예외는 템플리트를 제공하는 C++이다. nth_element 예상 선형 시간을 보장하고 데이터를 분할하여 n번째 요소를 정확한 위치로 정렬해야 하는 방법, n번째 요소 이전의 요소가 그것보다 작으며 n번째 요소 이후의 요소가 그것보다 크다. 예상 선형 시간 및 데이터의 분할 요구조건에 의해 Hoare의 알고리즘(또는 일부 변종)에 기초한다는 것은 함축적이지만 필수적이지는 않다.[2][3]

의 경우 모듈 정렬::키::CPAN에서 이용할 수 있는 은 여러 가지 순서와 사용자 정의 키 추출 절차를 사용하여 목록에서 상위 n개 요소를 선택하는 일련의 기능을 제공한다. 또한 통계는 다음과 같다.:CaseResampling 모듈은 Quickselect를 사용하여 정량량을 계산하는 기능을 제공한다.

Python의 표준 라이브러리(2.4 이후)는 heapq.nsmallest() 그리고 nlargest()정렬된 목록 반환, O(n 로그 k) 시간.[4]

Matlab은 다음을 포함한다. maxk() 그리고 mink() 함수, 벡터 내의 최대값(최대값) k 값과 그 지수를 반환한다.

분류에 대한 언어지원이 보편적이기 때문에 속도가 불리함에도 불구하고 많은 환경에서 색인화에 따른 분류의 단순화 접근법이 선호되고 있다. 실제로 게으른 언어의 경우, 이러한[citation needed] 단순화된 접근방식은 k가 충분히 게으른 경우(특수 사례로서 최대/최소) 가장 작은/큰 분류에 대해 가능한 최고의 복잡성을 달성할 수 있다.

참고 항목

참조

  1. ^ 라이 T.W. 우드 D. (1988) 암묵적 선택. 인: Karlsson R, Lingas A. (eds) SWAT 88. SWAT 1988. 컴퓨터 과학 강의 노트, 제318권. 베를린 하이델베르크 스프링거
  2. ^ ISO/IEC 14882:2003(E) 및 14882:1998(E)의 섹션 25.3.2
  3. ^ nth_element, SGI STL
  4. ^ "Python - What is the time complexity of heapq.nlargest?".

참고 문헌 목록

외부 링크