C # 사전의 효율성


14

C # 사전은 무언가 등이 있는지 확인하는 간단한 방법입니다. 작동 방식에 대한 질문이 있습니다. 사전 대신 ArrayList를 사용한다고 가정 해 봅시다. 사용 ContainsKey하거나 다른 언어의 동등한 방법 을 사용하는 대신 ArrayList를 반복하여 무언가가 있는지 확인하거나 데이터가 정렬되거나 비슷한 경우 이진 검색을 수행합니다. 효율성의 차이는 무엇입니까? 이 ContainsKey방법은 키를 반복하고 검색하는 것이 있는지 확인하는 것보다 더 효율적인 방법을 사용합니까?

내가 가지고있는 데이터 유형에 해당하는 특정 해시 함수를 만들고 해당 데이터 세트를 위해 특별히 설계된 경우 해시 함수는 실제로 데이터를 반복하는 것보다 빠릅니다. 그러나 사전은 일반적입니다. ContainsKey 메서드는 가져 오는 데이터에만 국한되지 않으며 일반적인 검색 방법입니다.

기본적으로 내가 묻는 것은. 사전은 프로그래머에게 도움이됩니다. 여기에는 많은 일을 돕는 메소드가 포함되어 있으며 문자열을 정수, 키 및 값 등으로 결합합니다. 그러나 효율성과 관련하여 무엇을 제공합니까? 을 가진 차이 무엇 dictionaryArrayList의가structs(string,int)


당신은 사과를 오렌지와 실제로 비교하고 있습니다. 찾고있는 키워드는 Data Structures 이 위키 링크가 도움이 될 것입니다.
Ampt

답변:


23

당신은 어떻게보고 조금 파고있어 사전이 아니라 그것의하지 분명 - C #으로 구현 되는 HashMap (해시 테이블) 또는 트리 맵 (정렬 된 나무) (또는 ConcurrentSkipListMap과 - 스킵리스트 ).

"비고"섹션을 살펴보면 :

Dictionary 일반 클래스는 키 세트에서 값 세트로의 맵핑을 제공합니다. 사전에 추가 할 때마다 값과 관련 키로 구성됩니다. Dictionary 클래스는 해시 테이블로 구현되기 때문에 키를 사용하여 값을 검색하는 것은 O (1)에 가까운 매우 빠릅니다.

그리고 우리는 그것을 가지고 있습니다. 그것은이다 해시 테이블 . Wikipedia 기사를 링크했습니다. 충돌 해결에 대한 섹션을 읽으십시오. 조회가 O (N)으로 이동하는 병리학적인 데이터 세트를 얻을 수 있습니다 (예를 들어 삽입하는 모든 것이 해시 테이블의 동일한 해시 값 또는 인덱스에 속하며 어떤 이유로 선형 프로빙으로 남습니다 ).

사전은 범용 솔루션이지만 사전과 같은 구체적인 유형을 통과해서는 안되며 인터페이스를 통과해야합니다. 이 경우 해당 인터페이스는 IDictionary( docs )입니다. 이를 위해 보유한 데이터에 대해 최적의 작업을 수행하는 사전 구현을 완벽하게 작성할 수 있습니다.

다양한 조회 / 포함의 효율성에 대해?

  • 분류되지 않은 목록 걷기 : O (N)
  • 정렬 된 배열의 이진 검색 : O (log N)
  • 정렬 된 트리 : O (log N)
  • 해시 테이블 : O (1)

대부분의 사람들에게 해시 테이블은 원하는 것입니다.

SortedDictionary 가 원하는 것을 찾을 수 있습니다 .

SortedDictionary<TKey, TValue>제네릭 클래스는 n은 사전에있는 요소의 수입니다 O (로그 n)이 검색과 이진 검색 트리입니다. 이와 관련하여 SortedList<TKey, TValue>일반 클래스 와 유사합니다 . 두 클래스는 비슷한 객체 모델을 가지며 둘 다 O (log n) 검색을 갖습니다.

데이터 구조가 데이터와 이상적으로 작동하는 것이 아니라면 데이터에 가장 적합한 구조를 작성할 수있는 도구 (인터페이스)가 제공됩니다.

사전 자체는 추상 데이터 유형 입니다. 당신은 나에게 사전을 주었고 나는 그것으로 할 수있는 일과 거기에있는 모든 도구가 사전이라는 성격으로 사용할 수 있다는 것을 알고 있습니다. ArrayList를 주면 목록에서 항목을 검색, 삽입 또는 삭제하기위한 자체 코드를 작성하는 것을 알 수 있습니다. 이것은 내 시간을 낭비하고 코드를 반복해서 복사 할 때 버그가 발생할 가능성이 더 크다는 것을 의미합니다.


5
O (1)이 반드시 "빠른"것은 아닙니다. 응용 프로그램이 처리하는 컬렉션 크기의 해시 테이블보다 목록을 반복하는 것이 여전히 빠를 수 있습니다.
whatsisname

5
@whatsisname 아무 시점에서 나는 O (1)이 빠르다고 주장합니까? 그것은 가장 빠른 잠재력을 가지고 있습니다. 해시 테이블의 키를 반복하는 것은 ArrayList의 키보다 느립니다 ( Java가 제공 하는 LinkedHashMap 과 같은 것을 사용하지 않는 한 ). 데이터와 데이터의 작동 방식 및 적절한 컬렉션을 선택하는 것이 중요합니다. 존재하지 않는 경우에는 데이터를 쓰십시오. 물론 그러한 노력이 실제로 가치가 있다고 가정합니다 (첫 번째 프로파일!).

귀하의 인용문은 "사전 테이블이 해시 테이블로 구현되기 때문에 키를 사용하여 값을 검색하는 것이 O (1)에 매우 빠르다"고 말하며 OP는 두 개념을 혼동시킬 수 있습니다. 다시 말해, 나는 큰 O가 "속도"에 관한 모든 이야기를 말하지 않는다는 것을 분명히하고 싶었다.
whatsisname

3
@whatsisname은 Microsoft에서 직접 제공합니다. 병리학 적 해시 테이블 (다른 메커니즘과의 해시 충돌을 해결하는)이없는 한 키를 사용하여 값을 조회하면 트리 또는 정렬 된 목록 (또는 정렬되지 않은 목록)에서 찾는 것보다 빠릅니다. 예를 들어, Java는 충돌 해결을 위해 선형 프로빙 (1 단계)을 사용합니다 . 이는 테이블이 가득 차거나 너무 많은 해시가 충돌하는 경우 속도가 느려질 있습니다. 그러나 일반적인 경우에는 충분합니다.

관련 예제로, 최근에 원래 약 20 개 항목의 데이터 세트에 해시 테이블을 사용하고 완료하는 데 약 400ms가 걸리는 c ++의 일부 코드를 최적화했습니다. 이진 트리로 전환하면 트리가 액세스하기 쉽기 때문에 200ms로 줄었습니다. 그러나 이름 값 쌍의 배열과 과거 액세스 패턴을 기반으로 어디에서 시작해야하는지 추측 한 휴리스틱 룩업 기능을 사용하여이를 더욱 줄일 수있었습니다. 따라서 데이터 양과 액세스에 어떤 패턴이 있는지 (예 : 지역) 문제가됩니다.
Jules
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.