답변:
각 세트가 다른 세트의 존재에 대한 레코드를 유지하고 총 세트를 갖는 경우 콜렉션의 데이터 구조 ( 예 : 이진 검색 트리 등 )를 검색 할 수있는 것으로 쉽게 변환 할 수 있습니다 . 시간의 두 집합의 교집합의 원소 O ( 로그 들 ) .
각 세트에는 완전히 정렬 된 세트의 고유 식별자가 있어야합니다. 세트의 이름을 로 명시 적으로 지정 하면 식별자가 색인 일 수 있습니다.
세트의 "레지스트리"를 구현해야합니다. 정의한 모든 세트의 콜렉션을 유지 보수하는 데이터 구조. 레지스트리는 검색 트리 데이터 구조로 구현되어 세트를 쉽게 검색 ( 예 : 세트를 삭제하려는 경우)하고 선형 시간 순회를 수행 할 수 있습니다.
각 세트 아닌 -도 다른 세트의 각각의 "인덱스"유지 복사 오히려 그하지만 다른 세트의 라벨에 의해 인덱스되는 데이터 구조. 이 인덱스는 각각의 세트에 대해 유지하기 위해 사용되는 S K 의 모든 요소의 이진 검색 트리 S의 J ∩ S K . (두 세트 S J 와 S의 유전율 공유 하나는 검색 트리의 복사).
초기화
세트의 초기화 구성 O ( 1 ) 작업 요소의 트리를 초기화, O ( S ) (레지스트리에서 복사) 작업이 초기화로 세트에 대한 인덱스 T 와 O ( S 로그 의 ) 당신과 같은 작업은 레지스트리 추가 횡단 T를 다른 세트의 각각의 인덱스에 S J . T 의 인덱스에서 T ∩ S j = ∅을 나타내는 검색 트리를 만듭니다.다른 세트 ; 우리의 인덱스에 대해 동일한 포인터를 복사 S의 J .
세트 T에 요소 추가
세트 T에 를 추가하면 평소와 같이 시간 O ( log n T ) 가 걸립니다 . 여기서 n T = | T | . 우리는 또한 각각의 다른 세트 S 1 , S 2 , … 에서 x의 멤버쉽을 테스트 하는데, 시간 O ( log n S 1 + log n S 2 + ⋯ ) ⊆ O ( s log n 여기서 n = | V | 은 유니버스의 크기 (또는 가장 큰 집합 S j )이고 s 는 레지스트리의 집합 수입니다. 각 세트를 들면 S의 J 되도록 X ∈ S J , 또한 삽입 X 세트에 대한 인덱스로 S의 J ∩ T . 이러한 각각의 세트를 들면 S의 J ,이 걸리는 O ( 로그 S +의 로그 N T ) 조회 시간을, S의 J를
세트에서 중복을 허용하지 않으면 멤버쉽 테스트를 취소하고 다른 세트 T에 대한 삽입을 생략하여 의 경우 시간을 절약 할 수 있습니다 . x 가 이미 존재 하는 경우 "삽입"은 단지 O ( log n T )의 시간 만 걸립니다 .
교차점 테스트
각 세트의 인덱스는 두 세트의 여부를 빠르게 평가 허용하기 위해 정확하게 유지 와 S의 유전율 이 교차한다. 설정된 내용은 S의 J 간단히 세트에 대한 인덱스를 선택하여 S를 (k)를 , 우리는 시간으로 결정할 수 O ( 로그 들 ) 여부 S j 개의 교차 S K , 그러나 또한 전체 세트를 포함하는 이진 트리 검색 할 S j ∩ S k .
요소 제거
집합 T 에서 요소 를 삭제하기 위해 T 자체 의 검색 트리 뿐만 아니라 색인 의 집합 S j 에 대한 각 교차점 S j ∩ T 에서 요소 x 를 제거합니다 . 이것은 시간이 걸리는 O ( S 로그 N T를 ) 여기서 n은 T = | T | .
삭제 설정
레지스트리 검색 오버 헤드로 인해 많은 세트가있는 경우 더 이상 필요하지 않은 세트를 삭제하는 것이 좋습니다. 전체 레지스트리를 통과함으로써, 우리는 삭제 될 수 있습니다 다른 모든 세트의 인덱스에서 S J 시간에 O ( s의 N T ) 대표 검색 트리 삭제의 비용에 의해 지배, S J ∩ T를 다른 세트의 각각 S J를 , 여기서 n T = | T | .
비고
일정한 수의 세트 만 구현할 것으로 예상되는 경우 위의 런타임은 다음과 같이 줄어 듭니다.
초기화 :
요소 삽입 :
교차로 테스트 (및 교차로 검색) :
요소 제거 :
삭제 설정 :
여기서 은 레지스트리에서 가장 큰 집합의 크기이며 n T = | T | 작동중인 세트 T 에 대해
당신이 기대하는 경우 여기서 세트, V는 당신의 우주는 당신이 이러한 작업은 하위 선형 시간에 운영하려는 경우, 당신은 서로 다른 데이터 구조를해야 할 수도 있습니다. 그러나 교차점을 테스트하지 않을 세트 쌍이있는 경우 교차점을 테스트 할 세트를 포함하지 않고 세트의 색인 크기를 줄이거 나 둘 이상의 레지스트리를 사용할 수 있습니다 ( 교차점을 테스트 할 수있는 각 세트 모음마다 하나씩). 실제로 레지스트리는 각 세트의 쌍이 인덱스에서 서로의 레코드를 갖도록 중앙 집중식 제어를 원하는 경우에만 유용합니다. 경우에 따라 세트 S 의 초기화시 단순히 기록 하는 것이 실용적 일 수 있습니다.각각의 새로운 세트 는 S 와의 교차점 에 관심 이있는 다른 세트 의 인덱스에 임시 로 배치 됩니다.
최악의 경우에도 선형 시간보다 짧은 시간 내에이를 수행 할 수있는 데이터 구조가 있습니다. http://research.microsoft.com/pubs/173795/vldb11intersection.pdf (및 해당 문서 참조)를 참조 하십시오 .
두 세트 S와 T의 교차점이 크고 S에 대한 사전이있는 경우 임의의 순서로 T의 요소를 검색하면 공통 요소가 빠르게 나타납니다. 가장 어려운 경우는 교점 크기가 0 또는 1 인 경우입니다.
일반적으로 선택한 프로그래밍 언어는 고유 한 요소가있는 데이터 구조를 지원합니다. 일반적으로 트리, 해시 및 비트 마스크의 세 가지 접근 방식이 있습니다. 트리 요소는 비교 가능해야하고 해시 요소는 해시 가능해야하며 비트 마스크 요소는 정수로 변환 할 수있는 방법이 있어야합니다.
트리 세트는 O (log n)에서의 삽입과 최악의 경우 O (n log n)에서의 교차점 테스트를 지원합니다.
해시 세트는 Amortized O (1 * h)에서의 삽입을 지원합니다. 여기서 'h'는 해싱 알고리즘의 실행 시간이며 최악의 경우 O (n)의 교차 테스트입니다.
비트 마스크 세트는 일반적으로 트리 및 해시 세트와 같이 사용되지 않습니다.
귀하의 사례에서 오 탐지가 허용되는 경우 단일 해시 함수로 Bloom Filter 를 사용 합니다.
다음과 같이 구현할 수 있습니다.
빈 세트를 초기화
세트에 요소를 추가하십시오.
두 세트 (B1, B2)가 주어지면 교차하는지 여부를보고하십시오.
복잡성