600 likes | 1.27k Views
제 12 장 디지털 탐색 구조. a. 1000. b. c. 0010. 1001. d. e. 0001. 1100. f. 0000. 디지털 탐색 트리 (digital search tree). 정의 각 노드가 하나의 원소만을 갖는 이진 트리. (a) 초기 트리. a. 1000. b. c. 0010. 1001. d. e. 0001. 1100. f. g. 0000. 0011. 탐색 , 삽입 , 삭제. 이원 탐색 트리에 대한 함수들과 매우 유사함
E N D
a 1000 b c 0010 1001 d e 0001 1100 f 0000 디지털 탐색 트리(digital search tree) • 정의 • 각 노드가 하나의 원소만을 갖는 이진 트리 (a) 초기 트리
a 1000 b c 0010 1001 d e 0001 1100 f g 0000 0011 탐색, 삽입, 삭제 • 이원 탐색 트리에 대한 함수들과 매우 유사함 • 이동할 서브트리가 탐색 키의 비트에 의해서 결정됨 • 각각의 연산은 O(h) 시간 내에 수행됨 • h : 디지털 탐색 트리의 높이 • 각 키가 keySize 비트 가지면, 트리 높이 최대 keySize + 1 (b) 0011을 삽입한 후
이진 트라이와 패트리샤 • 키가 아주 긴 경우에 비효율적인 탐색 구조 • 패트리샤(Patricia) 구조 • 키 비교의 횟수를 한 번으로 줄일 수 있음 • 3 단계 • 이진 트라이(binary trie) 구조 도입 • 이진 트라이를 압축 이진 트라이(compressed binary trie)로 변환 • 압축 이진 트라이부터 패트리샤 얻음
1010 0010 0000 0001 1000 1001 이진 트라이 예 이진 트라이 • 두 종류의 노드를 갖는 이진 트리 • 분기 노드(branch node) • leftChild와 rightChild, 두 개의 데이타 멤버 • 원소 노드(element node) • data 데이타 멤버 • 성공적인 탐색은 항상 원소 노드에서 끝남 • 성공적이지 못한 탐색은 원소 노드 또는 0포인터에서 종료
1 2 3 4 4 0010 1010 0000 0001 1000 1001 이진 트라이에서 차수가 1인 노드를 제거한 압축 이진 트라이 압축 이진 트라이 • 차수 1인 분기 노드를 포함하지 않기 위해 수정된 이진 트라이 • 분기 노드의 bitNumber 데이터 멤버는 이 노드에서 사용되는 키의 비트 번호를 나타냄 • bitNumber : 노드 밖에 번호를 나타냄
1100 0000 0010 1001 0001 1000 패트리샤의 예 패트리샤 • 부가 분기 노드(augmented branch node) • 원래의 분기 노드에 data라는 데이터 멤버를 추가한 노드 • 패트리샤 구조 얻는 방법 • 각 분기 노드를 부가 분기 노드로 대체 • 원소 노드 제거 0 1 3 2 4 4
패트리샤에서의 탐색 • 헤더 노드에서 시작하여 k가 가지고 있는 비트들에 의해 결정되는 경로를 따라감 template <class K, class E> E* Patricia <K,E>::Search(const K&k) const { // 패트리샤 탐색, 키가 k인 원소에 대한 포인터를 반환한다. // 그런 원소가 없으면 NULL로 반환한다 if(!root) return NULL; // 패트리샤는 공백이다. PatNode<K,E> *y = root->leftChild; // 헤드노드의 왼쪽자식으로 이동. for(PatNode<K, E> *p = root; y-> bitNumber > p-> bitNumber;) { // 분기 포인터를 따라간다. p = y; if (!bit(x.key, y->bitNumber)) y = y->leftChild; else y = y->rightChild; } // y에 키를 검사 if(y->key==k) return &y->element; return NULL; }
0 root 1000 0 1000 1 0010 패트리샤에서의 삽입 (1/3) 1000 삽입 0010 삽입 0 1000 1 0010 4 1001 1001 삽입
패트리샤에서의 삽입 (2/3) 0 0 1000 1000 1 0010 1 0010 2 3 2 1100 0000 1100 4 4 1001 1001 1100 삽입 0000 삽입
0 1000 1 0010 0000 1100 0001 1001 0001 삽입 패트리샤에서의 삽입 (3/3) • 복잡도: O(h) • h : 패트리샤의 높이이다. • h는 min{keySize+1, n}만큼 클 수 있음 • keySize : 키의 비트 수, n : 원소 수 • 키들이 균등하게 분포되어 있을 때 높이는: O(logn) 3 2 4 4
다원 트라이(multiway trie) (1/5) • 정의 • 키 값이 가변 길이일 때 유용한 구조 • 이진 트라이를 일반화한 것 • 모든 레벨의 분기가 일부에 의해서 결정된 차수 m>=2인 트라이 • 두 종류의 노드 타입 • 원소(element) 노드 • 분기(branch) 노드
다원 트라이 (2/5) • 왼쪽에서 오른쪽으로 한 번에 하나씩 키 값의 문자를 이용하여 생성한 트라이 b a b c g o t w 0 0 … … … … … l u a h o u h oriole wren d s r gull bluebird bunting a u cardinal chickadee godwit goshawk thrasher thrush
다원 트라이 (3/5) • 종료 문자(이 경우에는 공백 문자) 의 필요성을 보여주는 트라이 t … … o … … b g … … to together
다원 트라이 (4/5) • 키 필드 • 9자리의 10진수로 표현된 사회보장번호 5개의 원소(학생 레코드)
다원 트라이 (5/5) • 트라이의 예 0 1 2 3 4 5 6 7 8 9 A 5 7 562-44-2169 C B D 1 1 8 E F 2 9 271-16-3624 278-49-1515 G H I 951-23-7625 951-94-1654 J K
template <class K,E> E* Trie<K,E>::Search (const K& k) const {//트라이를 탐색. 키가 k인 원소의 포인터를 반환. //키가 k인 원소가 없으면 NULL을 반환. TrieNode<K,E> *p = root; for (int i=1 ; p는 분기노드 ; i++) p = p→child[digit(k,i)]; if (p == NULL || p->key != k) returnNULL; elsereturn &p→element; } 트라이에서의 탐색 • p=NULL이면, 분기 노드가 아니고 digit(k, i)함수는 k의 i번째 문자를 반환한다고 가정함 • Trie::Search의 분석 • 레벨 l일 때, 최악의 경우 탐색시간은 O(l)임
샘플링 전략 (1/4) • 오른쪽에서 왼쪽으로 한 번에 한 문자씩 샘플링하여 구성한 트라이 b a b c d e f g h i k l m n o p q r s t bluebird bunting goshawk wren thrasher godwit thrush e l a l chickadee oriole cardinal gull
b a b c d e f g h i k l m n o p q r s t u v w 샘플링 전략 (2/4) • 키의 네번째 문자를 사용하여 첫 레벨에서 샘플링한 최적 트라이 goshawk wren cardinal bunting godwit thrasher gull chickadee bluebird oriole thrush
b a b c d e f g h i k l m n o p q r s t u v w 샘플링 전략 (3/4) • 레벨수가 3으로 제한되어 있을때 데이터에 대해 키를 왼쪽에서 오른쪽으로 한 번에 한 문자씩 얻어진 트라이 o u h u l bluebird bunting godwit goshawk gull thrasher thrush wren a h oriole cardinal chickadee
샘플링 전략 (4/4) • 인덱스로 표현할 키 값들이 주어졌을 때 트라이가 가지는 레벨 수는 키 샘플링 방식에 따라 달라짐 • 샘플링 함수 sample(x,i)를 통해 정의할 수 있음 • i번째 레벨에서의 분기를 위해 키 x를 적절히 샘플링 함 • [sample(x, i) = x의 i번째 문자] (1) sample(x,i) = xn-i+1 (2) sample(x,i) = xr(x,i)단, r(x,i)는 난수 함수 (3) sample(x,i) = xi/2 (i가 짝수일 때) xn-(i-1)/2 (i가 홀수일 때)
트라이로의 삽입 • bobwhite와 bluejay를 삽입한 후 b l o u u bobwhite bunting e b j bluebird bluejay
트라이에서의 삭제 • bobwhite를 삭제할 경우 • σ.link['o']=0으로 지정 • bluejay를 삭제할 경우 • 서브트라이 δ3에 단 하나의 키 값만을 남김 • 노드 δ3를 제거하여 ρ를 한 레벨 위로 올릴 수 있다는 것 • 노드 δ1이나 δ2에 대해서도 같은 작업을 수행 • 노드 σ에 도달하게 됨.σ.link['l'] = ρ로 지정함 • 각 분기 노드가 적어도 두 개의 자식 노드를 갖는 압축 트라이를 정의할 수 있음
상이한 길이의 키 • 트라이에서는 어떤 키도 다른 키의 접두사이면 안 됨 • 각 키의 끝에 특수 문자를 첨가하는 방법 • 키가 모두 끝나는 노드마다 원소를 저장하기 위한 data 필드를 두는 방법
트라이의 높이 • 최대 numberofdigits + 1 • 사회보장번호를 저장하는 트라이의 높이 최대 10임 • SS#이 아홉 숫자이기 때문에 사회 보장 번호를 위한 트라이는 109개의 원소를 가질 수 있음 • 109개의 원소를 갖는 AVL 트리의 높이는 약 1.44log2(109+2)=44 가 됨
필요 공간과 또 다른 노드 구조 (1/4) • 분기 노드에 기수만큼 자식 필드를 두면 빠르게 탐색할 수 있음 • 노드의 체인 • 체인의 각 노드는 digitValue, child, next의 세 필드로 구성 1 G 8 H NULL firstNode 노드 E에 대한 체인
필요 공간과 또 다른 노드 구조 (2/4) • (균형) 이원 탐색 트리 • 이원 트라이 0 1 1,G 8, H 0001 = 1 1000 = 8 노드 E에 대한 이원 탐색 트리 노드 E에 대한 이진트라이
필요 공간과 또 다른 노드 구조 (3/4) • 해시 테이블 • 분기 노드에서 자식 필드가 NULL인 부분은 노드마다 다양 • 트라이에서 아래로 내려갈수록 늘어날 것 • 모든 분기 노드를 하나의 해시 테이블로 통합하면 공간 효율을 최대로 할 수 있음 • 최대의 공간 효율을 얻기 위해서 트라이에 있는 각 노드에 번호를 매김 • 부모에서 자식으로 가는 포인터들은 3-원소 쌍 (currentNode, digitValue, childNode)로 대체함 노드에 부여한 번호
필요 공간과 또 다른 노드 구조 (4/4) • 적재 밀도가 α인 선형 개방 주소 해시 테이블을 사용하면 해시 테이블은 체인 방식을 사용했을 때보다 약 (1/α-1)* 100%의 공간이 더 필요함 • 체인 방식 사용할 때 • O(r) 시간 안에 포인터를 찾음 • 해시 테이블 방식 사용할 때 • O(1) 시간 안에 찾을 수 있음 • (균형) 이원 탐색 트리나 이진 트라이 방식이 사용할 때 • 포인터를 찾는 데 O(logr)의 시간이 걸림 • 해시 테이블로 표현한 트라이에서 원소를 삭제하기 위해서 원소 노드를 재사용해야만 함
접두 탐색과 응용 • 트라이를 탐색하기 위해 키의 처음 몇 숫자만이 필요함 • 범죄학 • 명령어 자동 완성(automatic command completion) • 다른 환경에서 명령어 자동 완성 (1) 웹 브라우저는 방문했던 사이트의 URL의 기록 유지 (2) 워드 프로세서의 단어들의 모음을 유지 (3) 자동 다이얼 장치(automatic phone dialler) ps2ascii ps2pdf psbook psmandup psselect ps2epsi ps2pk pscal psmerge pstopnm ps2frag ps2ps psidtopgm psnup pstops ps2gif psbb pslatex psresize pstruct ps로 시작하는 명령어들
4 3 1 압축 트라이 (1/10) • 단 하나의 자식만 가진 모든 분기 노드들을 제거함으로써 트라이의 시간, 공간 성능을 향상 • 숫자 번호를 가진 압축 트라이(compressed trie with digit number) • digitNumber 필드를 추가로 갖고 있음 • 숫자 번호를 가진 압축 트라이에서의 탐색 • digitNumber 필드에 주어진 숫자 번호와 탐색 키의 숫자로 어떤 서브트라이로 이동해야 할지 결정 2 0 1 3 4 5 6 7 8 9 A E 1 8 9 C L 2 562-44-2169 G H J K 271-16-3624 278-49-1515 951-23-7625 951-94-1654
4 2 3 1 압축 트라이 (2/10) • 숫자 번호를 가진 압축 트라이에서의 삽입 2 0 1 3 4 5 6 7 8 9 A C L 8 5 E 1 8 562-44-2169 G H I M 9 2 271-16-3624 278-49-1515 987-26-1615 J K 951-23-7625 951-94-1654 987-26-1615를 삽입한 후의 압축 트라이
1 4 3 3 압축 트라이 (3/10) 2 0 1 3 4 5 6 7 8 9 A L C 1 8 E 1 8 562-44-2169 G H I M 2 9 271-16-3624 278-49-1515 958-36-4194 J K 951-23-7625 951-94-1654 958-36-4194를 삽입한 후의 압축 트라이
압축 트라이 (4/10) • 숫자 번호를 가진 압축 트라이에서의 삭제 • 키가 k인 원소를 포함한 원소 노드 X를 찾음 • 노드 X를 제거 • X의 부모가 하나의 자식만 갖는다면 부모 노드도 삭제 X의 부모가 제거될 때, X의 부모의 단 하나 남은 자식은 X의 조부모(만약 있다면)의 자식이 됨.
3 3 1 압축 트라이 (5/10) 2 0 1 3 4 5 6 7 8 9 A E L C 1 8 1 8 562-44-2169 M G H J 271-16-3624 278-49-1515 951-23-7625 958-36-4194 951-94-1654를 삭제한 후의 압축 트라이
0 2 1 압축 트라이 (6/10) • 생략 필드를 가진 압축 트라이 • Skip 필드 • 현재 분기 노드와 그 부모 사이에 원래 존재했던 분기 노드의 수 2 0 1 3 4 5 6 7 8 9 A E I C 2 9 1 8 562-44-2169 K G H J 271-16-3624 278-49-1515 951-23-7625 951-94-1654 생략 필드를 가진 압축 트라이
J G C 1 0 2 압축 트라이 (7/10) • 레이블 간선을 가진 압축 트라이 • 각 분기 노드는 두 가지 추가적인 정보를 담고 있음 • 서브트라이의 한 원소(혹은 원소 노드)를 가리키는 포인터/참조 변수인 element • 분기 노드와 부모 노드 사이에서 제거된 분기 노드의 수를 나타내는 정수 skip A 2 0 1 3 4 5 6 7 8 9 E I C 2 9 1 8 562-44-2169 G K H J 271-16-3624 278-49-1515 951-23-7625 951-94-1654
J M G C 0 1 0 1 압축 트라이 (8/10) • 레이블 간선을 가진 압축 트라이에서의 삽입 A 2 0 1 3 4 5 6 7 8 9 E C L 5 9 1 8 562-44-2169 2 G I H 9 M 271-16-3624 278-49-1515 987-26-1615 K J 951-23-7625 951-94-1654 987-26-1615를 삽입한 후의 압축 트라이
J M G C 1 1 0 0 압축 트라이 (9/10) A 2 0 1 3 4 5 6 7 8 9 E C L 5 9 1 8 562-44-2169 2 G I H 9 M 271-16-3624 278-49-1515 958-36-4194 K J 951-23-7625 951-94-1654 958-36-4194를 삽입한 후의 압축 트라이
압축 트라이 (10/10) • 레이블 간선을 가진 압축 트라이에서의 삭제 • element필드가 삭제된 원소를 가리키는 분기 노드의 element필드를 갱신해야 함 • 압축 트라이의 필요 공간 • 각 분기 노드는 서브트라이에 있는 원소들을 두 개 이상의 비어 있지 않은 그룹으로 나눔 • n개의 원소를 가진 압축 트라이는 최대 n-1개의 분기 노드를 가짐 • 공간은 각각 O(nr)이 됨. r : 트라이의 기수 • 분기 노드의 포인터가 아닌 필드들을 저장하기 위한 자료 구조가 추가로 필요함
접미 트리 • 이 스트링을 본 적이 있는가? • 기존의 패턴 매치 알고리즘을 사용하면 • Pi를 찾는 데는 O(|Pi|+|S|)가 걸림 • 스트링 S에서 패턴 P1, P2, …, Pk를 찾을 때 O(|P1|+|P2|+…+|Pk|+k|S|) 의 시간이 걸림 • 접미 트리 자료 구조는 복잡도를 O(|P1|+|P2|+…+|Pk|+|S|)로 줄임 • 스트링 S의 접미 트리를 만드는 데 쓰이는 시간: O(|S|) • S의 접미 트리가 만들어진 후에 각 패턴들을 탐색하는 데 O(|Pi|)가 걸림
접미 트리 자료 구조 (1/4) • S의 접미 트리(suffix tree)는 스트링 S의 공백이 아닌 접두사에 대한 압축 트라이 e p r H I A e p r e r E 2 H 3 r B C D eeper eper er peeper per E F G H I peeper의 접미사에 대한 압축 트라이
접미 트리 자료 구조 (2/4) • peeper의 접미사에 대한 압축 트라이 e p r H I A e p r e r E 2 H 3 6 C D B 2 3 5 1 4 E F G H I 1 2 3 4 5 6 S = p e e p e r peeper의 접미사에 대한 변경된 압축 트라이
접미 트리 자료 구조 (3/4) • peeper에 대한 접미 트리 e p r 1 1 A e p r e r 2 2 1 3 6 B C D 2 3 5 1 4 E F G H I 1 2 3 4 5 6 S = p e e p e r
A pe e r D B C eper per r eper per E F G H I 접미 트리 자료 구조 (4/4) • 친인간적 접미 트리 • 어떤 루트에서 원소 노드로 가는 경로의 간선에 붙은 레이블은 원소 노드에 의해 표현된 접미사를 구분하여 철자를 씀 친 인간적 그린 접미 트리
서브스트링 탐색(접미 트리 탐색) • 용어 • n=|S|는 접미 트리를 만들려는 스트링의 길이를 나타냄 • 숫자 1부터 시작해서 왼쪽에서 오른쪽으로 S의 각 숫자에 번호를 매김 • S[i]는 S의 i번째 숫자를 나타내고, suffix(i)는 1≤i≤n일 때 i번째 숫자에서 시작하는 접미사 S[i] … S[n]을 나타냄 • 탐색 • 스트링 S에서 패턴 P를 찾을 때 • P가 S에 있으면(즉, P가 S의 서브스트링이면) P가 S의 어떤 접미사의 접두사이고 그 역도 성립한다는 것 • P=P[1] … P[k]=S[i] … S[i+k-1]이라고 하면 P는 suffix(i)의 접두사 • suffix(i) : 압축 트라이에 있으므로 압축 트라이에서 키의 접두사를 찾는 방법을 사용해서 P를 찾을 수 있음.
접미 트리의 응용 (1/3) • 스트링 S가 패턴 P를 포함하고 있는지 아닌지를 O(|P|) 시간에 알 수 있음 • 패턴 P의 출현을 모두 탐색 • P의 접미 트리를 탐색함으로써 수행할 수 있음 (a) 접미 트리에 있는 모든 원소 노드를 체인으로 연결하는데 원소 노드를 왼쪽에서 오른쪽으로 훑을 때 만나는 원소 노드의 순서로 연결함 (b) 각 분기 노드에서 그 분기 노드를 루트로 하는 서브트라이에 있는 처음과 마지막 원소 노드에 대한 참조 정보를 유지함
접미 트리의 응용 (2/3) • 패턴 P를 포함하는 모든 스트링 탐색 • 스트링 S1, S2, …, Sk 있을 때 질의 패턴 P를 포함하는 모든 스트링을 찾고 싶을 때 • 스트링 S1$S2$...$Sk#의 접미사를 포함하는 압축 트라이(다중 스트링 접미 트리(multiple string suffix tree))를 만듦. • $와 #는 S1, S2, …, Sk에서 나타나지 않는 두 개의 다른 숫자임 • 접미 트리의 각 노드에는 모든 스트링 Si의 리스트를 유지하는데, 각 Si는 서브트라이에 있는 원소 노드로 표현된 접미사의 시작점
접미 트리의 응용 (3/3) • 최소 m>1번 나타나는 S의 가장 긴 서브스트링 탐색 • O(|S|) 시간 안에 수행될 수 있음 • 루트에서부터 레이블 길이의 합과 서브트라이에 있는 정보 노드의 숫자를 분기 노드에 표시하면서 접미 트리를 순회함 (b) 원소 노드의 계수≥m인 분기 노드를 방문하면서 접미 트리를 순회함. 방문한 분기 노드를 가장 긴 레이블 길이로 정함 • 스트링 S와 T의 가장 긴 공통 서브스트링 탐색 • O(|S|+|T|)시간 안에 수행될 수 있음 • S$T#을 위한 접미 트리를 만듦 (b) 접미 트리를 순회함
트라이와 인터넷 패킷 전송 • IP 라우팅 • 인터넷에서 데이타 패킷(data packet)은 여러 라우터(router)들을 거쳐 송신지에서 수신지까지 전송됨 • 인터넷 라우터 테이블은 (P, NH) 형식의 규칙의 모임 • P : 접두사, NH : 다음 홉(hop) • 상용 라우터 테이블에서 수신지 주소가 둘 이상의 규칙에 정확히 일치하는 경우는 보기 드믊 • 다음 홉은 일치하는 가장 긴 접두사에 의해 결정됨 • 인터넷 라우터 테이블의 자료 구조 • 수신지 주소가 주어졌을 때 일치되는 가장 긴 접두사를 위한 다음 홉을 결정하는 탐색 연산에 대해 최적화되어 있음