기능적 사전 데이터 구조를 어떻게 선택합니까?


10

다음 데이터 구조에 대해 조금 읽었습니다.

  • 백웰의 이상적인 해시 시도
  • 라슨의 동적 해시 테이블
  • 레드 블랙 나무
  • 패트리샤 나무

... 그리고 거기 에 다른 많은 사람들 이 있다고 확신 합니다. 나는 각각에 더 적합한 방식 또는 왜 서로를 선택해야 하는지를 거의 보지 못했습니다. 따라서 다음과 같은 몇 가지 질문이 있습니다.

  1. 알아야 할 기능적 사전 데이터 구조는 무엇입니까?
  2. 이러한 접근 방식의 장단점은 무엇입니까?
  3. 보다 필수적인 데이터 구조를 사용하는 것이 언제 합리적입니까?

숫자 2와 3이 더 중요합니다. :-)


관련 : 오카 사키 이후 순수하게 기능적인 데이터 구조의 새로운 기능 (이 질문은 사전에 국한되지 않습니다.)
Tsuyoshi Ito

이 질문 (3 번 항목 이외)에는 [큰 목록] 느낌이 있습니다.
Kaveh

2
위에 링크 된 질문이 귀하의 우려를 해결하는지 여부를 아는 것이 도움이 될 것입니다.
Suresh Venkat

@Suresh-그 대답은 # 1이지만 2와 3이 더 중요한 것들입니다. 나는 주로 큰 그림 개요를 찾고 있기 때문에 더 깊이 공부할 가치가있는 것을 결정할 수 있습니다.
Jason

2
확인. 질문을 편집하는 것이 좋습니다.
Suresh Venkat

답변:


16

잃지 않고 # 2에 실제로 대답 할 수는 없지만 (이 구조를 비교할 수있는 너무 많은 차원이 있습니다), # 3에 대한 대답은 매우 간단합니다.

(a) 앨리어싱이 전혀 없거나 (b) 효율적인 브로드 캐스트를 위해 실제로 앨리어싱을 사용해야하는 경우 명령형 데이터 구조를 사용하십시오.

데이터 구조의 앨리어싱이 전혀 없다면 기능적인 데이터 구조가 영구적이라는 사실을 이용하지 않는 것입니다. 따라서 비용을 지불 할 이유가 없습니다. 이 조언에는 두 가지주의 사항이 있습니다. 우선, 기능적인 데이터 구조를 구현하는 단순함을 선호 할 수 있습니다. 기능적인 레드-블랙 트리에 대한 삭제를 구현하면 저주가되지만 부모 포인터로 명령적인 레드-블랙 트리에 삭제를 구현하면 자살을 고민하게됩니다. 둘째, 쓰기는 데이터 구조가 젊은 세대에서 벗어날 수 있기 때문에 gc'd 언어에서 예상하는 것보다 할당이 더 비쌀 수 있습니다. 우리는 실제로 캐시 효과와 gc에 대한 좋은 이론을 가지고 있지 않으므로 벤치마킹을 할 수밖에 없습니다.

둘째, 방송 채널이 필요한 경우 공유 데이터 구조를 사용하는 것이 좋습니다. 일정 시간 업데이트를 통해 다른 많은 사람들에게 값이 변경되었음을 알릴 수 있습니다. (이것이 union-find가 훌륭한 데이터 구조 인 이유입니다.) 순전히 기능적인 설정을 사용하면 다른 모든 사람들을 수정하거나 수동으로 코딩 한 상태로 추상 포인터를 제공해야합니다. 해야 할 일).

앨리어싱 및 객체 소유권에 대해 추론하고 싶지 않거나 동일한 데이터 구조의 여러 버전이 필요한 경우 (예 : 새 버전과 이전 버전 모두 필요) 기능적인 데이터 구조 만 사용하십시오.

이 조언을 따르는 것이 가장 어려운 곳은 그래프 알고리즘입니다. 정말 우아한 명령형 그래프 알고리즘이 많이 있지만, 종종 (예를 들어 컴파일러를 작성할 때) 지속성을 원할 수도 있습니다. 사람들은 일반적으로 차이점을 나누고 멋진 명령 알고리즘을 사용하지만 지속성을 얻기 위해 버전 관리를 측면에 볼트로 연결하려고합니다. 이것은 일반적으로 매우 끔찍하고 버그로 가득 차 있으며 명령형 알고리즘의 성능 이점을 잃기 쉽습니다.


2
이 문맥에서 앨리어싱은 무엇입니까?
Suresh Venkat

6
앨리어싱은 동일한 데이터에 대한 참조가 여러 개인 경우입니다. 해당 데이터가 변경 가능한 경우, 데이터를 사용하는 프로그램에 대한 추론은 데이터를 액세스하고 수정할 수있는 다른 모든 서브 프로그램을 명시 적으로 고려해야합니다. 해당 데이터가 변경 불가능한 경우, 데이터에 액세스 할 수있는 사람이 데이터를 수정할 수있는 사람이 없기 때문에이를 사용하는 프로그램에 대해 로컬로 추론 할 수 있습니다.
Neel Krishnaswami

"그러나 부모 포인터가있는 명령적인 적-검은 나무에서 삭제를 구현하면 자살을 고민하게 될 것입니다." 삭제의 일반적인 경우는 표준 트릭에 의해 delete-min으로 감소되며 delete-min 자체는 LLRB 트리에서 매우 간단합니다. 부모 포인터가 필요하지 않습니다.
당 Vognsen

1
"이것은 일반적으로 끔찍하고 버그로 가득 차 있으며 명령형 알고리즘의 성능 이점을 잃기 쉽습니다." 최적화 컴파일러에서 제어 흐름 그래프를 위해 지퍼를 사용하는 것에 대한 Norman Ramsey의 논문은 강력한 절충안의 예를 제공합니다. CFG에서 기본 블록 사이의 쉽고 효율적인 내부 재배치 지원을위한 로컬 힙을 효과적으로 보유하고 있지만 기본 블록의 내용 조작은 기능적입니다 (또는 지퍼의 철학적 관점에 따라 반 기능적임).
당 Vognsen

1

알아야 할 기능적 사전 데이터 구조는 무엇입니까?

높이가 균형 잡힌 이진 트리와 그 시도는 좋은 만능 타협입니다. 또한:

  • 패트리샤 나무.
  • 해시가 시도됩니다.

이러한 접근 방식의 장단점은 무엇입니까?

균형 잡힌 이진 트리와 그 시도는 원자 키에 대한 만능 타협입니다. 시도는 문자열 키와 같이 시퀀스 인 키와 동일합니다.

패트리샤 트리는 몇 배 더 빠를 수 있지만 정수 키만 허용합니다.

해시 시도는 균형 잡힌 이진 트리보다 몇 배 빠를 수 있습니다. 특히 해싱이 비교보다 저렴하고 다형성에 오버 헤드 (예 : .NET의 문자열)가 있고 힙에 포인터를 쓰는 것이 빠르면 (예 : JVM 및 CLR과 같은 VM) 기능적 언어보다는 명령형 언어에 최적화 됨). 해시 시도는 또한 최적화로서 돌연변이의 내부 사용을 허용합니다.

적-검은 나무는 높이 균형이 잡힌 나무에 비해 큰 이점이 없지만 효율적인 결합, 교차 및 차이를 허용하지 않는다는 큰 단점이 있기 때문에 덜 중요합니다.

마찬가지로 손가락 나무는 실제로 더 나쁘지 않습니다.

보다 필수적인 데이터 구조를 사용하는 것이 언제 합리적입니까?

사전이 한 번 채워지고 조회에만 사용되는 경우 (예 : 고정)

성능이 필요할 때 (.NET과 같은 적절한 해시 테이블 Dictionary은 일반적으로 일반 순수 기능 사전보다 10-40 배 빠릅니다).

순전히 기능적인 약한 사전이 없기 때문에 약한 사전이 필요한 경우.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.