2016-09-02 1 views
1

최대로 서로 교차하는 세그먼트 범위가 있습니다. 이 세그먼트를 폴리선으로 병합하고 싶습니다.폴리 라인 범위에 세그먼트 범위를 병합/결합하는 알고리즘이 필요합니다.

여분의 저장소를 사용하지 않고 O(N_segments)에이 작업을 수행하는 알고리즘이 있습니까 (예 : 세그먼트 포인트에 대한 트리 또는 기타 공간 데이터 구조를 작성하지 않고 작업해야 함)?

내가 가지고있는 세그먼트 수는 O (10) 작습니다. 따라서 해쉬 테이블이나 맵 (적색 - 검은 색 트리)과 같은 동적 데이터 구조에 넣는다면 스택에 데이터 구조를 넣지 않고 메모리 할당을 피하기 만하면 끝 부분에서 루프보다 O(N^2) 루프가 더 비쌉니다. . (내가 사용 폴리 라인은 한 점의 수를 충분히 작은으로 할당을 피하는 small_vector 사용하여 현재 나는이 함께 왔어요

구현 :

polylines = [] 
// 1. Append each segment to a range of polylines, merging when possible: 
for each segment in segments: 
    for each polyline in polylines: 
     merge_result = merge(segment, polyline) 
     if (not merge_result) continue 
     polyline = merge_result 
     goto done 

    // either polylines empty or no merge possible 
    polylines.append(segment) 

    done: 
     continue 

// 2. Try to merge the polylines among themselves until no more merges are possible 
// Pure brute force, quadratic 
done = false 
while not done: 
    for p1 in polylines: 
     for p2 in polylines[p1..end]: 
      merge_result = merge(p1, p2) 
      if not merge: continue 
      p1 = merge_result 
      polylines.remove(p2) 
      done = false 
      goto restart 
    restart: continue 

을하지만 두 번째 루프 명확하게 2 차선이므로, 세그먼트 사이에 세그먼트 시퀀스를 병합/조인/결합하는 더 나은 알고리즘이 있는지 궁금합니다.

+1

왜 데이터 구조가 생성되지 않습니까? 하나 이상의 세그먼트가 O (n) 시간에 끝점을 공유하는지 탐지하기 위해 세그먼트의 끝점 맵을 작성합니다. – MrSmith42

+1

[관련 게시물] (http://stackoverflow.com/questions/1436091/joining-unordered-line-segments?rq=1)은 검색 속도를 높이기 위해 끝점의 해시를 계산할 것을 제안합니다. –

+0

@ MrSmith42 나는 O (10) 세그먼트의 순서를 다루므로, 스택에서 맵을 생성하지 않으면 동적 맵 생성 비용이 최종 O (N^2) 루프 비용을 초과 할 가능성이 있습니다. 이것이 내가 여분의 데이터 구조없이 더 나은 알고리즘에 관심이 있었던 이유이다. 나는 그것을 스택에 맵으로 시험해보고 그것을 벤치 마크 할 것이다. 제안 해 주셔서 감사합니다. – gnzlbg

답변

1

나는 O (n) 방법이 존재할 수 있다는 것을 심각하게 의심합니다.

정확하게 동일한 좌표를 가진 세그먼트 사지를 감지하는 O (n log (n)) 메소드입니다. 그것은 "데이터 구조"를 사용하지만 매우 단순한 벡터 (그냥 벡터)입니다 :

1) 모든 세그먼트의 모든 말단의 벡터를 만듭니다. 여기서 x, y 는 말단의 좌표를 나타내며, i는 말단의 지수를 나타냅니다 (예 : 세그먼트의 두 말단에 대한 2 * 세그먼트 인덱스 및 2 * 세그먼트 인덱스 +1).

2)와 완전히 동일한 좌표 점은 벡터 인접, 벡터 스캔 (X, Y)

3)의 사전 식 순서 벡터를 정렬 (인덱스로 난은 retreive 수

나는이 알고리즘을 3D 메쉬의 정점 병합에 사용하고 있으며, 해시 맵 또는 세트를 사용하는 경우보다 훨씬 간단하고 빠르다. (만큼 큰 점 집합에서 중복을 검출한다. 10 초 만에 포인트).

0

문제는 배열에서 중복을 찾는 것과 같습니다. 이 문제는 일반적으로 O (N) 시간 및 0 (1) 공간에서 해결 될 수 없습니다. O (N log N)의 복잡성을 가지거나 데이터 구조를 사용하기 위해 제안 된대로 정렬을 사용할 수 있습니다. 일반적으로 케이스에서 중복을 찾는 경우 this 토론을 볼 수 있습니다. 특수의 경우, 크기 n의 배열에 0, ... n-1 범위의 요소가 포함되어 있으면 O (N) 시간 및 0 (1) 공간 솔루션이 있으며, 이는 요소 색인으로 사용할 수 있습니다 (this 게시 참조).

그러나 어쨌든 약 10 개의 요소 만 말하는 경우에도 2 차 루프가 많이 손상되지 않습니다. 시간이 정말로 중요한 경우, 추측하기보다는 두 가지 방법 모두를 벤치 마크해야합니다. 문제는 순수한 복잡성 클래스가 대형 N에 대해서만 중요하기 때문에 아무도 당신의 컴퓨터에서 단 10 개의 요소만으로 더 빠를 것이라고 말할 수 없다는 것입니다. 작은 N, O (N^2) 알고리즘은 O (N log n) 알고리즘보다 훨씬 빠릅니다. 또한, 메모리 할당, 캐시 효율 및 그 밖의 다른 것들이 제공됩니다. 그래서, 제 제안 : 속도에 대해 정말로 염려한다면 벤치마킹을, 그렇지 않으면 신경 쓰지 마십시오.