πŸ–‡οΈμ•Œκ³ λ¦¬μ¦˜ μŠ€ν„°λ”” 2μ£Όμ°¨(2)

μ΅œμ§€μ›Β·2023λ…„ 7μ›” 22일
0

μ•Œκ³ λ¦¬μ¦˜

λͺ©λ‘ 보기
3/7

03.검색 μ•Œκ³ λ¦¬μ¦˜

검색?
μ–΄λ–€ 쑰건을 λ§Œμ‘±ν•˜λŠ” 데이터λ₯Ό μ°Ύμ•„λ‚΄λŠ” 것.

ν‚€?
μ£Όλͺ©ν•˜λŠ” ν•­λͺ©. 주둜 λ°μ΄ν„°μ˜ 일뢀.

κ²€μƒ‰μ˜ μ’…λ₯˜?
λ°°μ—΄ 검색/ μ—°κ²° 리슀트 검색/ 이진 검색 트리 검색

λ°°μ—΄ κ²€μƒ‰μ˜ μ•Œκ³ λ¦¬μ¦˜

1) μ„ ν˜• 검색: λ¬΄μž‘μœ„λ‘œ λŠ˜μ–΄λ†“μ€ 데이터 μ§‘ν•©μ—μ„œ 검색을 μˆ˜ν–‰
2) 이진 검색: μΌμ •ν•œ κ·œμΉ™μœΌλ‘œ λŠ˜μ–΄λ†“μ€ 데이터 μ§‘ν•©μ—μ„œ μ•„μ£Ό λΉ λ₯Έ 검색을 μˆ˜ν–‰
3) ν•΄μ‹œλ²•: μΆ”κ°€, μ‚­μ œκ°€ 자주 μΌμ–΄λ‚˜λŠ” 데이터 μ§‘ν•©μ—μ„œ μ•„μ£Ό λΉ λ₯Έ 검색을 μˆ˜ν–‰
- 체인법: 같은 ν•΄μ‹œκ°’ 데이터λ₯Ό μ—°κ²° 리슀트둜 μ—°κ²°ν•˜λŠ” 방법
- μ˜€ν”ˆ μ£Όμ†Œλ²•: 데이터λ₯Ό μœ„ν•œ ν•΄μ‹œκ°’μ΄ μΆ©λŒν•  λ•Œ μž¬ν•΄μ‹œν•˜λŠ” 방법

μ›ν•˜λŠ” 킀값을 가진 μ›μ†Œλ₯Ό 찾을 λ•ŒκΉŒμ§€ 맨 μ•žλΆ€ν„° μŠ€μΊ”ν•˜μ—¬ μˆœμ„œλŒ€λ‘œ κ²€μƒ‰ν•˜λŠ” μ•Œκ³ λ¦¬μ¦˜
μ’…λ£Œμ‘°κ±΄ 1. i==len(a) 2.a[i]=key
μ•„λž˜λŠ” μž„μ˜μ˜ μžλ£Œν˜•μΈ μ‹œν€€μŠ€μ—μ„œ 검색할 수 있음.

from typing import Any, Sequence

def seq_search(a: Sequence, key: Any) -> int:
	i=0
    
    while True:
    	if i==len(a):
        	return -1	#검색에 μ‹€νŒ¨ν•˜μ—¬ -1 λ°˜ν™˜
        if a[i]==key:
        	return i	#검색에 μ„±κ³΅ν•˜μ—¬ ν˜„μž¬ κ²€μ‚¬ν•œ λ°°μ—΄μ˜ 인덱슀 λ°˜ν™˜
        i+=1
    ###############or#################
    for i in range(len(a)):
    	if a[i]==key:
        	return i
    return -1

if __name__='__main__':
	num=int(input('μ›μ†Œ 수 μž…λ ₯: '))
    x=[None]*num
    
    for i in range(num):
    	x[i]=int(input*f'x[{i}]: '))
        
    ky=int(input('검색할 κ°’ μž…λ ₯: '))		#검색할 ν‚€ kyλ₯Ό μž…λ ₯λ°›μŒ
    
    idx=seq_search(x, ky)				#ky와 값이 같은 μ›μ†Œλ₯Ό xμ—μ„œ 검색
    
    if idx==-1:
    	print('검색값을 κ°–λŠ” μ›μ†Œκ°€ μ‘΄μž¬ν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€.')
    else:
    	print(f'검색값은 x[{idx}]에 μžˆμŠ΅λ‹ˆλ‹€.')

1-2) λ³΄μ΄ˆλ²•

맨끝에 검색할 킀값을 보초둜 μΆ”κ°€
-> μ’…λ£Œμ‘°κ±΄ 1λ²ˆμ„ νŒλ‹¨ν•  ν•„μš”κ°€ μ—†μŒ
-> λ°˜λ³΅μ„ μ’…λ£Œν•˜λŠ” νŒλ‹¨νšŸμˆ˜λ₯Ό 절반으둜 μ€„μž„

from typing import Any, Sequence
import copy

def seq_search(seq: Sequence, key: Any) -> int:
	a=copy.deecopy(seq)		#seq λ°°μ—΄ 볡사
    a.append(key)			#보초 key μΆ”κ°€
    
    i=0
    while True:
    	if a[i]==key:
        	break
        i+=1
    return -1 if i==len(seq) else i
(μƒλž΅)

μ›μ†Œκ°€ μ˜€λ¦„μ°¨μˆœμ΄λ‚˜ λ‚΄λ¦Όμ°¨μˆœμœΌλ‘œ μ •λ ¬λœ λ°°μ—΄μ—μ„œ μ’€ 더 효율적으둜 검색할 수 μžˆλŠ” μ•Œκ³ λ¦¬μ¦˜
μ’…λ£Œμ‘°κ±΄ 1.a[pc]와 keyκ°€ μΌμΉ˜ν•˜λŠ” 경우 2.검색 λ²”μœ„κ°€ 더 이상 μ—†λŠ” 경우(=pl이 pr보닀 컀짐)

from typing import Any, Sequence

def bin_search(a: Sequence, key: Any) -> int:
	pl=0			#검색 λ²”μœ„ 맨 μ•ž μ›μ†Œμ˜ 인덱슀
    pr=len(a)-1		#검색 λ²”μœ„ 맨 끝 μ›μ†Œμ˜ 인덱슀

	while True:
    	pc=(pl+pr)//2	#쀑앙 μ›μ†Œμ˜ 인덱슀
        if a[pc]==key:
        	return pc	#검색 성곡
        elif a[pc]<key:
        	pl=pc+1		#검색 λ²”μœ„λ₯Ό λ’€μͺ½ 절반으둜 쒁힘
        else:
        	pr=pc-1		#검색 λ²”μœ„λ₯Ό μ•žμͺ½ 절반으둜 쒁힘
		if pl>pr:
        	break
    return -1			#검색 μ‹€νŒ¨
    
if __name__='__main__':
	num=int(input('μ›μ†Œ 수λ₯Ό μž…λ ₯ν•˜μ„Έμš”: '))
    x=[None]*num		#μ›μ†Œ μˆ˜κ°€ num인 λ°°μ—΄ 생성
    
    print('λ°°μ—΄ 데이터λ₯Ό μ˜€λ¦„μ°¨μˆœμœΌλ‘œ μž…λ ₯ν•˜μ„Έμš”.')
    
    x[0]=int(input('x[0]: '))
    
    for i in range(1, num):
    	while True:
        	x[i]=int(input(f'x[{i}]: '))
            if x[i] >= x[i-1]:		#λ°”λ‘œ 직전에 μž…λ ₯ν•œ μ›μ†Ÿκ°’λ³΄λ‹€ 큰 κ°’ μž…λ ₯
            	break
                
    ky=int(input('검색할 값을 μž…λ ₯ν•˜μ„Έμš”.: '))	#검색할 ν‚€κ°’ ky μž…λ ₯
    
    idx=bin_search(x, ky)
    
    if idx==-1:
    	print('검색값을 κ°–λŠ” μ›μ†Œκ°€ μ‘΄μž¬ν•˜μ§€ μ•ŠμŒ')
    else:
    	print(f'검색값은 x[{idx}]에 있음')

2-2) λ³΅μž‘λ„

  1. μ‹œκ°„ λ³΅μž‘λ„
    데이터 수 nκ³Ό λ¬΄κ΄€ν•˜κ²Œ 1번 μ‹€ν–‰λ˜λŠ” λ³΅μž‘λ„ ex.return : O(1)
    n에 λΉ„λ‘€ν•˜λŠ” 횟수만큼 μ‹€ν–‰λ˜λŠ” λ³΅μž‘λ„: O(n) (μ‹€ν–‰νšŸμˆ˜λŠ” 평균)

O(f(n))+O(g(n))==O(max(f(n),g(n)))
->2개 ν˜Ήμ€ κ·Έ μ΄μƒμ˜ κ³„μ‚°μœΌλ‘œ κ΅¬μ„±λœ μ•Œκ³ λ¦¬μ¦˜μ˜ 전체 λ³΅μž‘λ„λŠ” 차원이 κ°€μž₯ 높은 λ³΅μž‘λ„λ₯Ό 선택함.

μ„ ν˜•κ²€μƒ‰ μ•Œκ³ λ¦¬μ¦˜μ˜ λ³΅μž‘λ„: O(1)+O(n)+O(1)+O(n)+O(1)=O(max(1,n,n,1,n,1))=O(n)
이진검색 μ•Œκ³ λ¦¬μ¦˜μ˜ λ³΅μž‘λ„: O(1)+O(1)+O(log n)+O(1)+O(log n)+...+O(1)=O(log n)

3-1) ν•΄μ‹œλ²•

'데이터λ₯Ό μ €μž₯ν•  μœ„μΉ˜=인덱슀'λ₯Ό κ°„λ‹¨ν•œ μ—°μ‚°μœΌλ‘œ κ΅¬ν•˜λŠ” 것.
ν•΄μ‹œκ°’: λ°°μ—΄μ˜ ν‚€(=μ›μ†Œμ˜ κ°’)λ₯Ό μ›μ†Œ 개수둜 λ‚˜λˆˆ λ‚˜λ¨Έμ§€. 데이터에 μ ‘κ·Όν•  λ•Œ κΈ°μ€€
ν•΄μ‹œ ν…Œμ΄λΈ”: ν•΄μ‹œκ°’μ„ 인덱슀둜 ν•œ 배열에 ν‚€λ₯Ό μ €μž₯
버킷: ν•΄μ‹œ ν…Œμ΄λΈ”μ—μ„œ λ§Œλ“€μ–΄μ§„ μ›μ†Œ

ν•΄μ‹œ 좩돌: 킀와 ν•΄μ‹œκ°’μ˜ λŒ€μ‘κ΄€κ³„λŠ” 일반적으둜 n:1. μ €μž₯ν•  버킷이 μ€‘λ³΅λ˜λŠ” ν˜„μƒ.

sol1. 체인법 (=μ˜€ν”ˆ ν•΄μ‹œλ²•)

ν•΄μ‹œκ°’μ΄ 같은 데이터λ₯Ό 체인 λͺ¨μ–‘μ˜ μ—°κ²° 리슀트둜 μ—°κ²°ν•˜λŠ” 방법.
Node 클래슀:
ν•„λ“œ-key, value, next
κ°œλ³„ 버킷을 λ‚˜νƒ€λƒ„, 킀와 값이 짝을 μ΄λ£¨λŠ” ꡬ쑰, 킀에 ν•΄μ‹œν•¨μˆ˜λ₯Ό μ μš©ν•˜μ—¬ ν•΄μ‹œκ°’μ„ ꡬ함.

from __future__ import annotations
from typing import Any, Type
import hashlib

class Node:
	def __init__(self, key: Any, value: Any, next: Node)->None:
    	self.key=key
        self.value=value
        self.next=next

ChainnedHash 클래슀:
ν•„λ“œ-capacity(ν•΄μ‹œν…Œμ΄λΈ”μ˜ 크기), table(ν•΄μ‹œν…Œμ΄λΈ”μ„ μ €μž₯ν•˜λŠ” listν˜• λ°°μ—΄)
keyκ°€ intν˜•μΈ 경우 / intν˜•μ΄ μ•„λ‹Œ 경우

1) search()
1. ν•΄μ‹œ ν•¨μˆ˜λ₯Ό μ΄μš©ν•˜μ—¬ ν‚€λ₯Ό ν•΄μ‹œκ°’μœΌλ‘œ λ³€ν™˜
2. ν•΄μ‹œκ°’μ„ 인덱슀둜 ν•˜λŠ” 버킷에 μ£Όλͺ©
3. 버킷이 μ°Έμ‘°ν•˜λŠ” μ—°κ²°λ¦¬μŠ€νŠΈλ₯Ό 맨 μ•žλΆ€ν„° μ°¨λ‘€λ‘œ μŠ€μΊ”. 킀와 같은 값이 발견되면 검색에 성곡, μ›μ†Œμ˜ 맨 λκΉŒμ§€ μŠ€μΊ”ν•΄μ„œ λ°œκ²¬λ˜μ§€ μ•ŠμœΌλ©΄ 검색에 μ‹€νŒ¨.

2) add()
1,2. (동일)
3. 버킷이 μ°Έμ‘°ν•˜λŠ” μ—°κ²° 리슀트 맨 μ•žλΆ€ν„° μ°¨λ‘€λ‘œ μ„ ν˜• 검색, 킀와 같은 κ°’ 발견 μ‹œ ν‚€κ°€ 이미 λ“±λ‘λœ κ²½μš°μ΄λ―€λ‘œ μΆ”κ°€ μ‹€νŒ¨. μ›μ†Œ λ§¨λκΉŒμ§€ λ°œκ²¬λ˜μ§€ μ•ŠμœΌλ©΄ ν•΄μ‹œκ°’μΈ 리슀트의 맨 μ•žμ— λ…Έλ“œ μΆ”κ°€

3) remove()
1,2. (동일)
3. 버킷이 μ°Έμ‘°ν•˜λŠ” μ—°κ²° 리슀트 맨 μ•žλΆ€ν„° μ°¨λ‘€λ‘œ μ„ ν˜• 검색, 킀와 같은 κ°’ 발견 μ‹œ κ·Έ λ…Έλ“œλ₯Ό λ¦¬μŠ€νŠΈμ—μ„œ μ‚­μ œ, 그렇지 μ•ŠμœΌλ©΄ μ‚­μ œμ— μ‹€νŒ¨.

4) dump() : ν•΄μ‹œν…Œμ΄λΈ”μ˜ λ‚΄μš©μ„ ν•œκΊΌλ²ˆμ— ν†΅μ§Έλ‘œ 좜λ ₯

sol2. μ˜€ν”ˆ μ£Όμ†Œλ²•

좩돌이 λ°œμƒν–ˆμ„ λ•Œ μž¬ν•΄μ‹œλ₯Ό μˆ˜ν–‰ν•˜μ—¬ 빈 버킷을 μ°ΎλŠ” 방법(λ‹«νžŒ ν•΄μ‹œλ²•)
μ›μ†Œ μΆ”κ°€- μ„ ν˜• 탐사법
μ›μ†Œ μ‚­μ œ- ν•΄μ‹œκ°’μ΄ λ‹€λ₯Έ κ°’μ˜ 검색 ν˜Όλˆμ„ 막기 μœ„ν•΄ μ‚­μ œ μ™„λ£Œλœ μœ„μΉ˜ 버킷에 속성 β˜…μ„ μ €μž₯
- λΉ„μ–΄μžˆλŠ” 버킷이 '-'
μ›μ†Œ 검색- β˜…μ„ λ§Œλ‚  μ‹œ μž¬ν•΄μ‹œ λ°˜λ³΅ν•˜μ—¬ 검색 성곡

profile
@JiwonChoi0805

0개의 λŒ“κΈ€