답변:
이 스레드 에 따르면 :
실제로 CPython의 세트는 더미 값 (키가 세트의 멤버 임)을 가진 사전과 같은 것으로 구현되며, 이러한 값 부족을 악용하는 최적화가 있습니다.
기본적으로 a set
는 기본 데이터 구조로 해시 테이블을 사용합니다. 해시 테이블에서 항목을 찾는 것이 평균적으로 O (1) 작업이므로 O (1) 멤버쉽 확인에 대해 설명합니다.
Achim Domma 에 따르면 대부분 구현 에서 잘라내어 붙여 넣는 set에 대한 CPython 소스 코드를 찾아 볼 수도 있습니다 .dict
사람들이 세트에 O (1) 회원 확인이 있다고 말하면 평균 사례 에 대해 이야기하고 있습니다. 에서 최악의 경우 (모든 해시 값이 충돌 할 때) 멤버 검사가 O (N)이다. 시간 복잡성에 대한 파이썬 위키를 참조하십시오 .
위키 백과 문서는 말한다 최상의 경우 크기 조정하지 않는 해시 테이블에 대한 시간 복잡도를 O(1 + k/n)
. Python 세트는 크기가 조정되는 해시 테이블을 사용하므로이 결과는 Python 세트에 직접 적용되지 않습니다.
위키 피디 기사에있어서 약간은에 대해 말한다 평균 케이스와 시간 복잡도는 간단 균일 해싱 함수를 가정하고 O(1/(1-k/n))
, k/n
일정에 의해 제한 될 수 c<1
.
Big-O는 점근 적 행동만을 n → ∞로 나타냅니다. k / n은 n과 관계 없이 상수 c <1에 의해 제한 될 수 있으므로 ,
O(1/(1-k/n))
보다 더 큰 없습니다 O(1/(1-c))
에 해당하는 O(constant)
= O(1)
.
따라서 균일 한 간단한 해싱을 가정 할 때 평균적 으로 파이썬 세트에 대한 멤버십 확인은 O(1)
입니다.
나는 일반적인 실수, set
조회 (또는 그 문제에 대한 해시 테이블)가 O (1)이 아니라고 생각합니다 .
위키 백과에서
가장 간단한 모델에서 해시 함수는 완전히 지정되어 있지 않으며 테이블 크기는 조정되지 않습니다. 최적의 해시 함수 선택을 위해 열린 주소 지정을 사용하는 크기 n의 테이블은 충돌이없고 최대 n 개의 요소를 보유하며, 성공적인 조회를위한 단일 비교와 연결 및 k 키가있는 크기 n의 테이블은 최대 값이 최소입니다. 조회에 대한 (0, kn) 충돌 및 O (1 + k / n) 비교 해시 함수의 최악의 선택의 경우, 모든 삽입시 충돌이 발생하고 해시 테이블은 선형 검색으로 퇴보합니다. 삽입 당 Ω (k)의 상각 비교와 성공적인 조회를 위해 최대 k 개의 비교가 이루어집니다.
관련 : 자바 해시 맵은 O (1) 정말?
우리 모두는 소스에 쉽게 접근 할 수 있으며 , 앞의 주석은 set_lookkey()
다음과 같습니다.
/* set object implementation
Written and maintained by Raymond D. Hettinger <python@rcn.com>
Derived from Lib/sets.py and Objects/dictobject.c.
The basic lookup function used by all operations.
This is based on Algorithm D from Knuth Vol. 3, Sec. 6.4.
The initial probe index is computed as hash mod the table size.
Subsequent probe indices are computed as explained in Objects/dictobject.c.
To improve cache locality, each probe inspects a series of consecutive
nearby entries before moving on to probes elsewhere in memory. This leaves
us with a hybrid of linear probing and open addressing. The linear probing
reduces the cost of hash collisions because consecutive memory accesses
tend to be much cheaper than scattered probes. After LINEAR_PROBES steps,
we then use open addressing with the upper bits from the hash value. This
helps break-up long chains of collisions.
All arithmetic on hash should ignore overflow.
Unlike the dictionary implementation, the lookkey function can return
NULL if the rich comparison returns an error.
*/
...
#ifndef LINEAR_PROBES
#define LINEAR_PROBES 9
#endif
/* This must be >= 1 */
#define PERTURB_SHIFT 5
static setentry *
set_lookkey(PySetObject *so, PyObject *key, Py_hash_t hash)
{
...
조금을 사이에 많은 차이를 강조하기 위해 set's
그리고 dict's
여기 것은로부터 발췌 한 것입니다 setobject.c
dicts에 대한 일련의의 주요 차이점을의 명확하게 코멘트 섹션.
세트의 사용 사례는 조회 키가 존재할 가능성이 높은 사전과 상당히 다릅니다. 반대로 세트는 주로 요소의 존재를 미리 알 수없는 멤버쉽 테스트에 관한 것입니다. 따라서 세트 구현은 발견 된 사례와 발견되지 않은 사례 모두에 대해 최적화해야합니다.
github의 소스
set
구현은 사실 이었다dict
더미 값으로하고, 나중에 최적화되었다.